mirror of
https://github.com/esphome/esphome.git
synced 2026-08-24 07:06:20 +00:00
Merge branch 'esp8266-native-build-infra' into esp8266-native-framework-installer
This commit is contained in:
+1
-1
@@ -766,7 +766,7 @@ def _wrap_to_code(name, comp, yaml_util):
|
||||
# unsorted dump would churn main.cpp and relink every run
|
||||
conf_str = yaml_util.dump(conf, sort_keys=True)
|
||||
conf_str = conf_str.replace("//", "")
|
||||
# remove tailing \ to avoid multi-line comment warning
|
||||
# remove trailing \ to avoid multi-line comment warning
|
||||
conf_str = conf_str.replace("\\\n", "\n")
|
||||
cg.add(cg.LineComment(indent(conf_str)))
|
||||
await coro(conf)
|
||||
|
||||
@@ -423,12 +423,6 @@ void APIServer::send_infrared_rf_receive_event([[maybe_unused]] uint32_t device_
|
||||
API_DISPATCH_UPDATE(alarm_control_panel::AlarmControlPanel, alarm_control_panel)
|
||||
#endif
|
||||
|
||||
float APIServer::get_setup_priority() const { return setup_priority::AFTER_WIFI; }
|
||||
|
||||
void APIServer::set_port(uint16_t port) { this->port_ = port; }
|
||||
|
||||
void APIServer::set_batch_delay(uint16_t batch_delay) { this->batch_delay_ = batch_delay; }
|
||||
|
||||
#ifdef USE_API_HOMEASSISTANT_SERVICES
|
||||
void APIServer::send_homeassistant_action(const HomeassistantActionRequest &call) {
|
||||
bool has_subscriber = false;
|
||||
@@ -553,10 +547,6 @@ const std::vector<APIServer::HomeAssistantStateSubscription> &APIServer::get_sta
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t APIServer::get_port() const { return this->port_; }
|
||||
|
||||
void APIServer::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; }
|
||||
|
||||
#ifdef USE_API_NOISE
|
||||
bool APIServer::update_noise_psk_(const SavedNoisePsk &new_psk, const LogString *save_log_msg,
|
||||
const LogString *fail_log_msg, bool make_active) {
|
||||
|
||||
@@ -51,8 +51,8 @@ class APIServer final : public Component,
|
||||
public:
|
||||
APIServer();
|
||||
void setup() override;
|
||||
uint16_t get_port() const;
|
||||
float get_setup_priority() const override;
|
||||
uint16_t get_port() const { return this->port_; }
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
void loop() override;
|
||||
void dump_config() override;
|
||||
void on_shutdown() override;
|
||||
@@ -63,9 +63,9 @@ class APIServer final : public Component,
|
||||
#ifdef USE_CAMERA
|
||||
void on_camera_image(const std::shared_ptr<camera::CameraImage> &image) override;
|
||||
#endif
|
||||
void set_port(uint16_t port);
|
||||
void set_reboot_timeout(uint32_t reboot_timeout);
|
||||
void set_batch_delay(uint16_t batch_delay);
|
||||
void set_port(uint16_t port) { this->port_ = port; }
|
||||
void set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; }
|
||||
void set_batch_delay(uint16_t batch_delay) { this->batch_delay_ = batch_delay; }
|
||||
uint16_t get_batch_delay() const { return batch_delay_; }
|
||||
void set_listen_backlog(uint8_t listen_backlog) { this->listen_backlog_ = listen_backlog; }
|
||||
|
||||
|
||||
@@ -4,9 +4,12 @@ The platform analog of esp32_ble / rp2040_ble: owns the Beken BDK BLE stack
|
||||
bring-up and the controller BLE address. Consumers (bk72xx_ble_tracker) build
|
||||
on this component and contain no SDK calls of their own.
|
||||
|
||||
Supported SoCs (BLE 5.x): BK7231N/BK7236 (BLE 5.1), BK7238/BK7252N/BK7253
|
||||
(BLE 5.2), and any future BLE-5.x SoC. Known non-5.x families are rejected in
|
||||
to_code; unknown families are capability-checked at compile time via
|
||||
Supported SoCs (BLE 5.x): BK7231N/BK7236 (BLE 5.1), BK7252N/BK7253 (BLE 5.2),
|
||||
and any future BLE-5.x SoC. BK7238 (BLE 5.2) is blocked for now: with BLE
|
||||
compiled in, the Beken SDK erases the bootloader flash sector at boot because
|
||||
LibreTiny's partition table has no BLE bonding entry (esphome#18646,
|
||||
libretiny-eu/libretiny#408). Known non-5.x families and BK7238 are rejected in
|
||||
to_code. Unknown families are capability-checked at compile time via
|
||||
`__has_include("app_ble.h")`, a header only on the BLE 5.x include path
|
||||
(ble_api.h ships for every SoC, so it cannot be the probe). A non-5.x build
|
||||
fails with a clear #error.
|
||||
@@ -65,6 +68,14 @@ def _unsupported_family_message(family: str) -> str | None:
|
||||
)
|
||||
if family == FAMILY_BK7231Q:
|
||||
return "bk72xx_ble does not support BK7231Q: this SoC has no BLE"
|
||||
if family == FAMILY_BK7238:
|
||||
return (
|
||||
"bk72xx_ble is disabled on BK7238: with BLE compiled in, the Beken SDK "
|
||||
"erases the bootloader flash sector at boot and the device can no longer "
|
||||
"start (see https://github.com/esphome/esphome/issues/18646); support "
|
||||
"returns once the LibreTiny partition table fix "
|
||||
"(libretiny-eu/libretiny#408) is released"
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
@@ -113,18 +124,7 @@ async def to_code(config: ConfigType) -> None:
|
||||
# BK7231N, but NOT on BK7238 (its BLE stack has no such symbol; the address is
|
||||
# derived from the WiFi MAC instead — the BDK's own fallback). Tell the C++
|
||||
# which path is available so it doesn't reference a missing symbol.
|
||||
family = libretiny.get_libretiny_family()
|
||||
if family == FAMILY_BK7231N:
|
||||
if libretiny.get_libretiny_family() == FAMILY_BK7231N:
|
||||
cg.add_define("BK72XX_BLE_HAS_COMMON_BDADDR")
|
||||
elif family == FAMILY_BK7238:
|
||||
# ESPHome's LibreTiny disables BLE on BK7238 because the SDK can hang at
|
||||
# WiFi STA startup when BLE init runs. This component re-enables BLE, so
|
||||
# warn loudly: BK7238 is accepted but not hardware-verified and may be
|
||||
# WiFi-unstable with BLE on.
|
||||
_LOGGER.warning(
|
||||
"bk72xx_ble on BK7238: enabling BLE is known to risk a WiFi STA startup "
|
||||
"hang on this family and is not yet hardware-verified. Expect possible "
|
||||
"instability."
|
||||
)
|
||||
|
||||
cg.add_define("USE_BK72XX_BLE")
|
||||
|
||||
@@ -511,29 +511,6 @@ ClimateTraits Climate::get_traits() {
|
||||
return traits;
|
||||
}
|
||||
|
||||
#ifdef USE_CLIMATE_VISUAL_OVERRIDES
|
||||
void Climate::set_visual_min_temperature_override(float visual_min_temperature_override) {
|
||||
this->visual_min_temperature_override_ = visual_min_temperature_override;
|
||||
}
|
||||
|
||||
void Climate::set_visual_max_temperature_override(float visual_max_temperature_override) {
|
||||
this->visual_max_temperature_override_ = visual_max_temperature_override;
|
||||
}
|
||||
|
||||
void Climate::set_visual_temperature_step_override(float target, float current) {
|
||||
this->visual_target_temperature_step_override_ = target;
|
||||
this->visual_current_temperature_step_override_ = current;
|
||||
}
|
||||
|
||||
void Climate::set_visual_min_humidity_override(float visual_min_humidity_override) {
|
||||
this->visual_min_humidity_override_ = visual_min_humidity_override;
|
||||
}
|
||||
|
||||
void Climate::set_visual_max_humidity_override(float visual_max_humidity_override) {
|
||||
this->visual_max_humidity_override_ = visual_max_humidity_override;
|
||||
}
|
||||
#endif
|
||||
|
||||
ClimateCall Climate::make_call() { return ClimateCall(this); }
|
||||
|
||||
ClimateCall ClimateDeviceRestoreState::to_call(Climate *climate) {
|
||||
|
||||
@@ -228,11 +228,22 @@ class Climate : public EntityBase {
|
||||
ClimateTraits get_traits();
|
||||
|
||||
#ifdef USE_CLIMATE_VISUAL_OVERRIDES
|
||||
void set_visual_min_temperature_override(float visual_min_temperature_override);
|
||||
void set_visual_max_temperature_override(float visual_max_temperature_override);
|
||||
void set_visual_temperature_step_override(float target, float current);
|
||||
void set_visual_min_humidity_override(float visual_min_humidity_override);
|
||||
void set_visual_max_humidity_override(float visual_max_humidity_override);
|
||||
void set_visual_min_temperature_override(float visual_min_temperature_override) {
|
||||
this->visual_min_temperature_override_ = visual_min_temperature_override;
|
||||
}
|
||||
void set_visual_max_temperature_override(float visual_max_temperature_override) {
|
||||
this->visual_max_temperature_override_ = visual_max_temperature_override;
|
||||
}
|
||||
void set_visual_temperature_step_override(float target, float current) {
|
||||
this->visual_target_temperature_step_override_ = target;
|
||||
this->visual_current_temperature_step_override_ = current;
|
||||
}
|
||||
void set_visual_min_humidity_override(float visual_min_humidity_override) {
|
||||
this->visual_min_humidity_override_ = visual_min_humidity_override;
|
||||
}
|
||||
void set_visual_max_humidity_override(float visual_max_humidity_override) {
|
||||
this->visual_max_humidity_override_ = visual_max_humidity_override;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Set the supported custom fan modes (stored on Climate, referenced by ClimateTraits).
|
||||
|
||||
@@ -135,10 +135,6 @@ CoverCall &CoverCall::set_stop(bool stop) {
|
||||
this->stop_ = stop;
|
||||
return *this;
|
||||
}
|
||||
bool CoverCall::get_stop() const { return this->stop_; }
|
||||
|
||||
CoverCall Cover::make_call() { return {this}; }
|
||||
|
||||
void Cover::publish_state(bool save) {
|
||||
this->position = clamp(this->position, 0.0f, 1.0f);
|
||||
this->tilt = clamp(this->tilt, 0.0f, 1.0f);
|
||||
@@ -184,9 +180,6 @@ optional<CoverRestoreState> Cover::restore_state_() {
|
||||
return recovered;
|
||||
}
|
||||
|
||||
bool Cover::is_fully_open() const { return this->position == COVER_OPEN; }
|
||||
bool Cover::is_fully_closed() const { return this->position == COVER_CLOSED; }
|
||||
|
||||
CoverCall CoverRestoreState::to_call(Cover *cover) {
|
||||
auto call = cover->make_call();
|
||||
auto traits = cover->get_traits();
|
||||
|
||||
@@ -50,7 +50,7 @@ class CoverCall {
|
||||
void perform();
|
||||
|
||||
const optional<float> &get_position() const;
|
||||
bool get_stop() const;
|
||||
bool get_stop() const { return this->stop_; }
|
||||
const optional<float> &get_tilt() const;
|
||||
const optional<bool> &get_toggle() const;
|
||||
|
||||
@@ -123,7 +123,7 @@ class Cover : public EntityBase {
|
||||
float tilt{COVER_OPEN};
|
||||
|
||||
/// Construct a new cover call used to control the cover.
|
||||
CoverCall make_call();
|
||||
CoverCall make_call() { return {this}; }
|
||||
|
||||
template<typename F> void add_on_state_callback(F &&f) { this->state_callback_.add(std::forward<F>(f)); }
|
||||
|
||||
@@ -139,9 +139,9 @@ class Cover : public EntityBase {
|
||||
virtual CoverTraits get_traits() = 0;
|
||||
|
||||
/// Helper method to check if the cover is fully open. Equivalent to comparing .position against 1.0
|
||||
bool is_fully_open() const;
|
||||
bool is_fully_open() const { return this->position == COVER_OPEN; }
|
||||
/// Helper method to check if the cover is fully closed. Equivalent to comparing .position against 0.0
|
||||
bool is_fully_closed() const;
|
||||
bool is_fully_closed() const { return this->position == COVER_CLOSED; }
|
||||
|
||||
protected:
|
||||
friend CoverCall;
|
||||
|
||||
@@ -37,8 +37,6 @@ void DateEntity::publish_state() {
|
||||
#endif
|
||||
}
|
||||
|
||||
DateCall DateEntity::make_call() { return DateCall(this); }
|
||||
|
||||
void DateCall::validate_() {
|
||||
if (this->year_.has_value() && (this->year_ < 1970 || this->year_ > 3000)) {
|
||||
ESP_LOGE(TAG, "Year must be between 1970 and 3000");
|
||||
|
||||
@@ -96,6 +96,8 @@ class DateCall {
|
||||
optional<uint8_t> day_;
|
||||
};
|
||||
|
||||
inline DateCall DateEntity::make_call() { return DateCall(this); }
|
||||
|
||||
template<typename... Ts> class DateSetAction final : public Action<Ts...>, public Parented<DateEntity> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(ESPTime, date)
|
||||
|
||||
@@ -53,8 +53,6 @@ void DateTimeEntity::publish_state() {
|
||||
#endif
|
||||
}
|
||||
|
||||
DateTimeCall DateTimeEntity::make_call() { return DateTimeCall(this); }
|
||||
|
||||
ESPTime DateTimeEntity::state_as_esptime() const {
|
||||
ESPTime obj;
|
||||
obj.year = this->year_;
|
||||
|
||||
@@ -121,6 +121,8 @@ class DateTimeCall {
|
||||
optional<uint8_t> second_;
|
||||
};
|
||||
|
||||
inline DateTimeCall DateTimeEntity::make_call() { return DateTimeCall(this); }
|
||||
|
||||
template<typename... Ts> class DateTimeSetAction final : public Action<Ts...>, public Parented<DateTimeEntity> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(ESPTime, datetime)
|
||||
|
||||
@@ -33,8 +33,6 @@ void TimeEntity::publish_state() {
|
||||
#endif
|
||||
}
|
||||
|
||||
TimeCall TimeEntity::make_call() { return TimeCall(this); }
|
||||
|
||||
void TimeCall::validate_() {
|
||||
if (this->hour_.has_value() && this->hour_ > 23) {
|
||||
ESP_LOGE(TAG, "Hour must be between 0 and 23");
|
||||
|
||||
@@ -98,6 +98,8 @@ class TimeCall {
|
||||
optional<uint8_t> second_;
|
||||
};
|
||||
|
||||
inline TimeCall TimeEntity::make_call() { return TimeCall(this); }
|
||||
|
||||
template<typename... Ts> class TimeSetAction final : public Action<Ts...>, public Parented<TimeEntity> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(ESPTime, time)
|
||||
|
||||
@@ -43,10 +43,6 @@ void DeepSleepComponent::loop() {
|
||||
this->begin_sleep();
|
||||
}
|
||||
|
||||
void DeepSleepComponent::set_sleep_duration(uint32_t time_ms) { this->sleep_duration_ = uint64_t(time_ms) * 1000; }
|
||||
|
||||
void DeepSleepComponent::set_run_duration(uint32_t time_ms) { this->run_duration_ = time_ms; }
|
||||
|
||||
void DeepSleepComponent::begin_sleep(bool manual) {
|
||||
if (this->prevent_ && !manual) {
|
||||
this->next_enter_deep_sleep_ = true;
|
||||
@@ -76,8 +72,4 @@ void DeepSleepComponent::begin_sleep(bool manual) {
|
||||
|
||||
float DeepSleepComponent::get_setup_priority() const { return setup_priority::LATE; }
|
||||
|
||||
void DeepSleepComponent::prevent_deep_sleep() { this->prevent_ = true; }
|
||||
|
||||
void DeepSleepComponent::allow_deep_sleep() { this->prevent_ = false; }
|
||||
|
||||
} // namespace esphome::deep_sleep
|
||||
|
||||
@@ -132,7 +132,7 @@ template<typename... Ts> class PreventDeepSleepAction;
|
||||
class DeepSleepComponent final : public Component {
|
||||
public:
|
||||
/// Set the duration in ms the component should sleep once it's in deep sleep mode.
|
||||
void set_sleep_duration(uint32_t time_ms);
|
||||
void set_sleep_duration(uint32_t time_ms) { this->sleep_duration_ = uint64_t(time_ms) * 1000; }
|
||||
#if defined(USE_ESP32)
|
||||
/** Set the pin to wake up to on the ESP32 once it's in deep sleep mode.
|
||||
* Use the inverted property to set the wakeup level.
|
||||
@@ -157,7 +157,7 @@ class DeepSleepComponent final : public Component {
|
||||
#if !defined(USE_ESP32_VARIANT_ESP32C2) && !defined(USE_ESP32_VARIANT_ESP32C3) && \
|
||||
!defined(USE_ESP32_VARIANT_ESP32C5) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
|
||||
!defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32H2)
|
||||
void set_touch_wakeup(bool touch_wakeup);
|
||||
void set_touch_wakeup(bool touch_wakeup) { this->touch_wakeup_ = touch_wakeup; }
|
||||
#endif
|
||||
|
||||
// Set the duration in ms for how long the code should run before entering
|
||||
@@ -166,7 +166,7 @@ class DeepSleepComponent final : public Component {
|
||||
#endif // USE_ESP32
|
||||
|
||||
/// Set a duration in ms for how long the code should run before entering deep sleep mode.
|
||||
void set_run_duration(uint32_t time_ms);
|
||||
void set_run_duration(uint32_t time_ms) { this->run_duration_ = time_ms; }
|
||||
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
@@ -176,8 +176,8 @@ class DeepSleepComponent final : public Component {
|
||||
/// Helper to enter deep sleep mode
|
||||
void begin_sleep(bool manual = false);
|
||||
|
||||
void prevent_deep_sleep();
|
||||
void allow_deep_sleep();
|
||||
void prevent_deep_sleep() { this->prevent_ = true; }
|
||||
void allow_deep_sleep() { this->prevent_ = false; }
|
||||
|
||||
protected:
|
||||
// Returns nullopt if no run duration is set. Otherwise, returns the run
|
||||
|
||||
@@ -74,12 +74,6 @@ void DeepSleepComponent::set_wakeup_pin_mode(WakeupPinMode wakeup_pin_mode) {
|
||||
void DeepSleepComponent::set_ext1_wakeup(Ext1Wakeup ext1_wakeup) { this->ext1_wakeup_ = ext1_wakeup; }
|
||||
#endif
|
||||
|
||||
#if !defined(USE_ESP32_VARIANT_ESP32C2) && !defined(USE_ESP32_VARIANT_ESP32C3) && \
|
||||
!defined(USE_ESP32_VARIANT_ESP32C5) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
|
||||
!defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32H2)
|
||||
void DeepSleepComponent::set_touch_wakeup(bool touch_wakeup) { this->touch_wakeup_ = touch_wakeup; }
|
||||
#endif
|
||||
|
||||
void DeepSleepComponent::set_run_duration(WakeupCauseToRunDuration wakeup_cause_to_run_duration) {
|
||||
wakeup_cause_to_run_duration_ = wakeup_cause_to_run_duration;
|
||||
}
|
||||
|
||||
@@ -685,9 +685,6 @@ void Display::show_page(DisplayPage *page) {
|
||||
}
|
||||
}
|
||||
|
||||
void Display::show_next_page() { this->page_->show_next(); }
|
||||
void Display::show_prev_page() { this->page_->show_prev(); }
|
||||
|
||||
void Display::do_update_() {
|
||||
if (this->auto_clear_enabled_) {
|
||||
this->clear();
|
||||
@@ -892,9 +889,6 @@ void DisplayPage::show_prev() {
|
||||
this->prev_->show();
|
||||
}
|
||||
|
||||
void DisplayPage::set_parent(Display *parent) { this->parent_ = parent; }
|
||||
void DisplayPage::set_prev(DisplayPage *prev) { this->prev_ = prev; }
|
||||
void DisplayPage::set_next(DisplayPage *next) { this->next_ = next; }
|
||||
const display_writer_t &DisplayPage::get_writer() const { return this->writer_; }
|
||||
|
||||
const LogString *text_align_to_string(TextAlign textalign) {
|
||||
|
||||
@@ -802,9 +802,9 @@ class DisplayPage final {
|
||||
void show();
|
||||
void show_next();
|
||||
void show_prev();
|
||||
void set_parent(Display *parent);
|
||||
void set_prev(DisplayPage *prev);
|
||||
void set_next(DisplayPage *next);
|
||||
void set_parent(Display *parent) { this->parent_ = parent; }
|
||||
void set_prev(DisplayPage *prev) { this->prev_ = prev; }
|
||||
void set_next(DisplayPage *next) { this->next_ = next; }
|
||||
const display_writer_t &get_writer() const;
|
||||
|
||||
protected:
|
||||
@@ -814,6 +814,9 @@ class DisplayPage final {
|
||||
DisplayPage *next_{nullptr};
|
||||
};
|
||||
|
||||
inline void Display::show_next_page() { this->page_->show_next(); }
|
||||
inline void Display::show_prev_page() { this->page_->show_prev(); }
|
||||
|
||||
template<typename... Ts> class DisplayPageShowAction final : public Action<Ts...> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(DisplayPage *, page)
|
||||
|
||||
@@ -233,6 +233,7 @@ DEFAULT_EXCLUDED_IDF_COMPONENTS = (
|
||||
"esp_driver_touch_sens", # Touch sensor driver - only needed by esp32_touch
|
||||
"esp_driver_twai", # TWAI/CAN driver - only needed by esp32_can component
|
||||
"esp_eth", # Ethernet driver - only needed by ethernet component
|
||||
"esp_gdbstub", # GDB stub panic handler - unused by ESPHome; bt pulls it back
|
||||
"esp_hid", # HID host/device support - ESPHome doesn't implement HID functionality
|
||||
"esp_http_client", # HTTP client - only needed by http_request component
|
||||
"esp_https_ota", # ESP-IDF HTTPS OTA - ESPHome has its own OTA implementation
|
||||
|
||||
@@ -643,8 +643,28 @@ void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_pa
|
||||
App.wake_loop_threadsafe();
|
||||
return;
|
||||
|
||||
// Log the result of connection parameter updates: a peer can reject or
|
||||
// never answer an update, and without this the link silently stays on the
|
||||
// old parameters (visible only as unexplained supervision timeouts).
|
||||
case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: {
|
||||
if (param->update_conn_params.status != ESP_BT_STATUS_SUCCESS) {
|
||||
char mac_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
|
||||
format_mac_addr_upper(param->update_conn_params.bda, mac_s);
|
||||
ESP_LOGW(TAG, "[%s] Conn param update failed, status=%d", mac_s, param->update_conn_params.status);
|
||||
}
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||
else {
|
||||
char mac_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
|
||||
format_mac_addr_upper(param->update_conn_params.bda, mac_s);
|
||||
ESP_LOGV(TAG, "[%s] Conn params updated: interval=%u (x1.25ms) latency=%u timeout=%u (x10ms)", mac_s,
|
||||
param->update_conn_params.conn_int, param->update_conn_params.latency,
|
||||
param->update_conn_params.timeout);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore these GAP events as they are not relevant for our use case
|
||||
case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
|
||||
case ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT:
|
||||
case ESP_GAP_BLE_PHY_UPDATE_COMPLETE_EVT: // BLE 5.0 PHY update complete
|
||||
case ESP_GAP_BLE_CHANNEL_SELECT_ALGORITHM_EVT: // BLE 5.0 channel selection algorithm
|
||||
|
||||
@@ -118,8 +118,6 @@ static const LogString *get_exception_cause(uint32_t cause) {
|
||||
}
|
||||
|
||||
static const LogString *get_reset_reason(uint32_t reason) {
|
||||
if (reason == REASON_WDT_RST)
|
||||
return LOG_STR("Hardware WDT");
|
||||
if (reason == REASON_EXCEPTION_RST)
|
||||
return LOG_STR("Exception");
|
||||
if (reason == REASON_SOFT_WDT_RST)
|
||||
@@ -162,13 +160,20 @@ void crash_handler_log() {
|
||||
if (!is_crash_reason(resetInfo.reason))
|
||||
return;
|
||||
|
||||
ESP_LOGE(TAG, "*** CRASH DETECTED ON PREVIOUS BOOT ***");
|
||||
if (resetInfo.reason == REASON_WDT_RST) {
|
||||
// A hardware WDT reset happens entirely in hardware: the postmortem hook
|
||||
// never runs, so rst_info epc1/exccause and the RTC backtrace are
|
||||
// leftovers from an earlier crash. Don't misattribute them (#18596).
|
||||
ESP_LOGE(TAG, " Reason: Hardware WDT (no crash state is recorded for hardware WDT resets)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Read and filter backtrace from RTC into stack-local buffer (no persistent RAM cost).
|
||||
// Both resetInfo and RTC data survive until the next reset, so this can be
|
||||
// called multiple times (logger init + API subscribe) with the same result.
|
||||
uint32_t backtrace[MAX_BACKTRACE];
|
||||
uint8_t bt_count = read_rtc_backtrace(backtrace, MAX_BACKTRACE);
|
||||
|
||||
ESP_LOGE(TAG, "*** CRASH DETECTED ON PREVIOUS BOOT ***");
|
||||
// GCC's ROM divide routine triggers IllegalInstruction (exccause=0) at specific
|
||||
// ROM addresses instead of IntegerDivideByZero (exccause=6). Patch to match
|
||||
// the Arduino core's postmortem handler behavior.
|
||||
|
||||
@@ -588,8 +588,6 @@ bool ESPHomeOTAComponent::writeall_(const uint8_t *buf, size_t len) {
|
||||
}
|
||||
|
||||
float ESPHomeOTAComponent::get_setup_priority() const { return setup_priority::AFTER_WIFI; }
|
||||
uint16_t ESPHomeOTAComponent::get_port() const { return this->port_; }
|
||||
void ESPHomeOTAComponent::set_port(uint16_t port) { this->port_ = port; }
|
||||
|
||||
void ESPHomeOTAComponent::log_socket_error_(const LogString *msg) {
|
||||
ESP_LOGW(TAG, "Socket %s: errno %d", LOG_STR_ARG(msg), errno);
|
||||
|
||||
@@ -39,14 +39,14 @@ class ESPHomeOTAComponent final : public ota::OTAComponent {
|
||||
#endif // USE_OTA_PASSWORD
|
||||
|
||||
/// Manually set the port OTA should listen on
|
||||
void set_port(uint16_t port);
|
||||
void set_port(uint16_t port) { this->port_ = port; }
|
||||
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
void loop() override;
|
||||
|
||||
uint16_t get_port() const;
|
||||
uint16_t get_port() const { return this->port_; }
|
||||
|
||||
protected:
|
||||
void handle_handshake_();
|
||||
|
||||
@@ -10,14 +10,6 @@ EthernetComponent *global_eth_component; // NOLINT(cppcoreguidelines-avoid-non-
|
||||
|
||||
EthernetComponent::EthernetComponent() { global_eth_component = this; }
|
||||
|
||||
float EthernetComponent::get_setup_priority() const { return setup_priority::WIFI; }
|
||||
|
||||
void EthernetComponent::set_type(EthernetType type) { this->type_ = type; }
|
||||
|
||||
#ifdef USE_ETHERNET_MANUAL_IP
|
||||
void EthernetComponent::set_manual_ip(const ManualIP &manual_ip) { this->manual_ip_ = manual_ip; }
|
||||
#endif
|
||||
|
||||
#ifdef USE_ETHERNET_IP_STATE_LISTENERS
|
||||
void EthernetComponent::notify_ip_state_listeners_() {
|
||||
auto ips = this->get_ip_addresses();
|
||||
|
||||
@@ -125,7 +125,7 @@ class EthernetComponent final : public Component {
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
float get_setup_priority() const override { return setup_priority::ETHERNET; }
|
||||
void on_powerdown() override { powerdown(); }
|
||||
bool is_connected() { return this->state_ == EthernetComponentState::CONNECTED; }
|
||||
|
||||
@@ -146,9 +146,9 @@ class EthernetComponent final : public Component {
|
||||
esp_netif_t *get_esp_netif() { return this->eth_netif_; }
|
||||
#endif
|
||||
|
||||
void set_type(EthernetType type);
|
||||
void set_type(EthernetType type) { this->type_ = type; }
|
||||
#ifdef USE_ETHERNET_MANUAL_IP
|
||||
void set_manual_ip(const ManualIP &manual_ip);
|
||||
void set_manual_ip(const ManualIP &manual_ip) { this->manual_ip_ = manual_ip; }
|
||||
#endif
|
||||
void set_fixed_mac(const std::array<uint8_t, MAC_ADDRESS_SIZE> &mac) { this->fixed_mac_ = mac; }
|
||||
|
||||
@@ -171,35 +171,35 @@ class EthernetComponent final : public Component {
|
||||
esp_eth_handle_t get_eth_handle() const { return this->eth_handle_; }
|
||||
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
void set_clk_pin(uint8_t clk_pin);
|
||||
void set_miso_pin(uint8_t miso_pin);
|
||||
void set_mosi_pin(uint8_t mosi_pin);
|
||||
void set_cs_pin(uint8_t cs_pin);
|
||||
void set_interrupt_pin(uint8_t interrupt_pin);
|
||||
void set_reset_pin(uint8_t reset_pin);
|
||||
void set_clock_speed(int clock_speed);
|
||||
void set_interface(spi_host_device_t interface);
|
||||
void set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; }
|
||||
void set_miso_pin(uint8_t miso_pin) { this->miso_pin_ = miso_pin; }
|
||||
void set_mosi_pin(uint8_t mosi_pin) { this->mosi_pin_ = mosi_pin; }
|
||||
void set_cs_pin(uint8_t cs_pin) { this->cs_pin_ = cs_pin; }
|
||||
void set_interrupt_pin(uint8_t interrupt_pin) { this->interrupt_pin_ = interrupt_pin; }
|
||||
void set_reset_pin(uint8_t reset_pin) { this->reset_pin_ = reset_pin; }
|
||||
void set_clock_speed(int clock_speed) { this->clock_speed_ = clock_speed; }
|
||||
void set_interface(spi_host_device_t interface) { this->interface_ = interface; }
|
||||
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
|
||||
void set_polling_interval(uint32_t polling_interval);
|
||||
void set_polling_interval(uint32_t polling_interval) { this->polling_interval_ = polling_interval; }
|
||||
#endif
|
||||
#else
|
||||
void set_phy_addr(uint8_t phy_addr);
|
||||
void set_power_pin(int power_pin);
|
||||
void set_mdc_pin(uint8_t mdc_pin);
|
||||
void set_mdio_pin(uint8_t mdio_pin);
|
||||
void set_clk_pin(uint8_t clk_pin);
|
||||
void set_clk_mode(emac_rmii_clock_mode_t clk_mode);
|
||||
void set_phy_addr(uint8_t phy_addr) { this->phy_addr_ = phy_addr; }
|
||||
void set_power_pin(int power_pin) { this->power_pin_ = power_pin; }
|
||||
void set_mdc_pin(uint8_t mdc_pin) { this->mdc_pin_ = mdc_pin; }
|
||||
void set_mdio_pin(uint8_t mdio_pin) { this->mdio_pin_ = mdio_pin; }
|
||||
void set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; }
|
||||
void set_clk_mode(emac_rmii_clock_mode_t clk_mode) { this->clk_mode_ = clk_mode; }
|
||||
void add_phy_register(PHYRegister register_value);
|
||||
#endif // USE_ETHERNET_SPI
|
||||
#endif // USE_ESP32
|
||||
|
||||
#ifdef USE_RP2
|
||||
void set_clk_pin(uint8_t clk_pin);
|
||||
void set_miso_pin(uint8_t miso_pin);
|
||||
void set_mosi_pin(uint8_t mosi_pin);
|
||||
void set_cs_pin(uint8_t cs_pin);
|
||||
void set_interrupt_pin(int8_t interrupt_pin);
|
||||
void set_reset_pin(int8_t reset_pin);
|
||||
void set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; }
|
||||
void set_miso_pin(uint8_t miso_pin) { this->miso_pin_ = miso_pin; }
|
||||
void set_mosi_pin(uint8_t mosi_pin) { this->mosi_pin_ = mosi_pin; }
|
||||
void set_cs_pin(uint8_t cs_pin) { this->cs_pin_ = cs_pin; }
|
||||
void set_interrupt_pin(int8_t interrupt_pin) { this->interrupt_pin_ = interrupt_pin; }
|
||||
void set_reset_pin(int8_t reset_pin) { this->reset_pin_ = reset_pin; }
|
||||
#endif // USE_RP2
|
||||
|
||||
#ifdef USE_ETHERNET_IP_STATE_LISTENERS
|
||||
|
||||
@@ -908,25 +908,7 @@ void EthernetComponent::dump_connect_params_() {
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
}
|
||||
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
void EthernetComponent::set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; }
|
||||
void EthernetComponent::set_miso_pin(uint8_t miso_pin) { this->miso_pin_ = miso_pin; }
|
||||
void EthernetComponent::set_mosi_pin(uint8_t mosi_pin) { this->mosi_pin_ = mosi_pin; }
|
||||
void EthernetComponent::set_cs_pin(uint8_t cs_pin) { this->cs_pin_ = cs_pin; }
|
||||
void EthernetComponent::set_interrupt_pin(uint8_t interrupt_pin) { this->interrupt_pin_ = interrupt_pin; }
|
||||
void EthernetComponent::set_reset_pin(uint8_t reset_pin) { this->reset_pin_ = reset_pin; }
|
||||
void EthernetComponent::set_clock_speed(int clock_speed) { this->clock_speed_ = clock_speed; }
|
||||
void EthernetComponent::set_interface(spi_host_device_t interface) { this->interface_ = interface; }
|
||||
#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT
|
||||
void EthernetComponent::set_polling_interval(uint32_t polling_interval) { this->polling_interval_ = polling_interval; }
|
||||
#endif
|
||||
#else
|
||||
void EthernetComponent::set_phy_addr(uint8_t phy_addr) { this->phy_addr_ = phy_addr; }
|
||||
void EthernetComponent::set_power_pin(int power_pin) { this->power_pin_ = power_pin; }
|
||||
void EthernetComponent::set_mdc_pin(uint8_t mdc_pin) { this->mdc_pin_ = mdc_pin; }
|
||||
void EthernetComponent::set_mdio_pin(uint8_t mdio_pin) { this->mdio_pin_ = mdio_pin; }
|
||||
void EthernetComponent::set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; }
|
||||
void EthernetComponent::set_clk_mode(emac_rmii_clock_mode_t clk_mode) { this->clk_mode_ = clk_mode; }
|
||||
#ifndef USE_ETHERNET_SPI
|
||||
void EthernetComponent::add_phy_register(PHYRegister register_value) { this->phy_registers_.push_back(register_value); }
|
||||
#endif
|
||||
|
||||
|
||||
@@ -355,13 +355,6 @@ void EthernetComponent::dump_connect_params_() {
|
||||
this->get_eth_mac_address_pretty_into_buffer(mac_buf));
|
||||
}
|
||||
|
||||
void EthernetComponent::set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; }
|
||||
void EthernetComponent::set_miso_pin(uint8_t miso_pin) { this->miso_pin_ = miso_pin; }
|
||||
void EthernetComponent::set_mosi_pin(uint8_t mosi_pin) { this->mosi_pin_ = mosi_pin; }
|
||||
void EthernetComponent::set_cs_pin(uint8_t cs_pin) { this->cs_pin_ = cs_pin; }
|
||||
void EthernetComponent::set_interrupt_pin(int8_t interrupt_pin) { this->interrupt_pin_ = interrupt_pin; }
|
||||
void EthernetComponent::set_reset_pin(int8_t reset_pin) { this->reset_pin_ = reset_pin; }
|
||||
|
||||
void EthernetComponent::enable() {
|
||||
// RP2040 uses arduino-pico's LwipIntfDev which manages link state internally;
|
||||
// there is no clean enable/disable hook today. The YAML option is accepted on
|
||||
|
||||
@@ -153,11 +153,6 @@ void FanRestoreState::apply(Fan &fan) {
|
||||
fan.publish_state();
|
||||
}
|
||||
|
||||
FanCall Fan::turn_on() { return this->make_call().set_state(true); }
|
||||
FanCall Fan::turn_off() { return this->make_call().set_state(false); }
|
||||
FanCall Fan::toggle() { return this->make_call().set_state(!this->state); }
|
||||
FanCall Fan::make_call() { return FanCall(*this); }
|
||||
|
||||
const char *Fan::find_preset_mode_(const char *preset_mode) {
|
||||
return this->find_preset_mode_(preset_mode, preset_mode ? strlen(preset_mode) : 0);
|
||||
}
|
||||
|
||||
@@ -115,10 +115,10 @@ class Fan : public EntityBase {
|
||||
/// The current direction of the fan
|
||||
FanDirection direction{FanDirection::FORWARD};
|
||||
|
||||
FanCall turn_on();
|
||||
FanCall turn_off();
|
||||
FanCall toggle();
|
||||
FanCall make_call();
|
||||
FanCall turn_on() { return this->make_call().set_state(true); }
|
||||
FanCall turn_off() { return this->make_call().set_state(false); }
|
||||
FanCall toggle() { return this->make_call().set_state(!this->state); }
|
||||
FanCall make_call() { return FanCall(*this); }
|
||||
|
||||
/// Register a callback that will be called each time the state changes.
|
||||
template<typename F> void add_on_state_callback(F &&callback) {
|
||||
|
||||
@@ -75,8 +75,6 @@ void Infrared::dump_config() {
|
||||
YESNO(this->traits_.get_supports_receiver()));
|
||||
}
|
||||
|
||||
InfraredCall Infrared::make_call() { return InfraredCall(this); }
|
||||
|
||||
void Infrared::control(const InfraredCall &call) {
|
||||
if (this->transmitter_ == nullptr) {
|
||||
ESP_LOGW(TAG, "No transmitter configured");
|
||||
|
||||
@@ -134,7 +134,7 @@ class Infrared : public Component, public EntityBase, public remote_base::Remote
|
||||
const InfraredTraits &get_traits() const { return this->traits_; }
|
||||
|
||||
/// Create a call object for transmitting
|
||||
InfraredCall make_call();
|
||||
InfraredCall make_call() { return InfraredCall(this); }
|
||||
|
||||
/// Get capability flags for this infrared instance
|
||||
uint32_t get_capability_flags() const;
|
||||
|
||||
@@ -13,8 +13,6 @@ ESPColorView ESPRangeView::operator[](int32_t index) const {
|
||||
index = interpret_index(index, this->size()) + this->begin_;
|
||||
return (*this->parent_)[index];
|
||||
}
|
||||
ESPRangeIterator ESPRangeView::begin() { return {*this, this->begin_}; }
|
||||
ESPRangeIterator ESPRangeView::end() { return {*this, this->end_}; }
|
||||
|
||||
void ESPRangeView::set(const Color &color) {
|
||||
for (int32_t i = this->begin_; i < this->end_; i++) {
|
||||
|
||||
@@ -75,4 +75,7 @@ class ESPRangeIterator {
|
||||
int32_t i_;
|
||||
};
|
||||
|
||||
inline ESPRangeIterator ESPRangeView::begin() { return {*this, this->begin_}; }
|
||||
inline ESPRangeIterator ESPRangeView::end() { return {*this, this->end_}; }
|
||||
|
||||
} // namespace esphome::light
|
||||
|
||||
@@ -157,8 +157,6 @@ void LightState::loop() {
|
||||
}
|
||||
}
|
||||
|
||||
float LightState::get_setup_priority() const { return setup_priority::HARDWARE - 1.0f; }
|
||||
|
||||
void LightState::publish_state() {
|
||||
if (this->remote_values_listeners_) {
|
||||
for (auto *listener : *this->remote_values_listeners_) {
|
||||
@@ -194,25 +192,11 @@ void LightState::add_target_state_reached_listener(LightTargetStateReachedListen
|
||||
this->target_state_reached_listeners_->push_back(listener);
|
||||
}
|
||||
|
||||
void LightState::set_default_transition_length(uint32_t default_transition_length) {
|
||||
this->default_transition_length_ = default_transition_length;
|
||||
}
|
||||
uint32_t LightState::get_default_transition_length() const { return this->default_transition_length_; }
|
||||
void LightState::set_flash_transition_length(uint32_t flash_transition_length) {
|
||||
this->flash_transition_length_ = flash_transition_length;
|
||||
}
|
||||
uint32_t LightState::get_flash_transition_length() const { return this->flash_transition_length_; }
|
||||
void LightState::set_gamma_correct(float gamma_correct) { this->gamma_correct_ = gamma_correct; }
|
||||
void LightState::set_restore_mode(LightRestoreMode restore_mode) { this->restore_mode_ = restore_mode; }
|
||||
void LightState::set_initial_state(void (*callback)(LightStateRTCState &)) { this->initial_state_callback_ = callback; }
|
||||
bool LightState::supports_effects() { return !this->effects_.empty(); }
|
||||
const FixedVector<LightEffect *> &LightState::get_effects() const { return this->effects_; }
|
||||
void LightState::add_effects(const std::initializer_list<LightEffect *> &effects) {
|
||||
// Called once from Python codegen during setup with all effects from YAML config
|
||||
this->effects_ = effects;
|
||||
}
|
||||
|
||||
void LightState::current_values_as_binary(bool *binary) { this->current_values.as_binary(binary); }
|
||||
void LightState::current_values_as_brightness(float *brightness) {
|
||||
this->current_values.as_brightness(brightness);
|
||||
*brightness = this->gamma_correct_lut(*brightness);
|
||||
@@ -333,8 +317,6 @@ float LightState::gamma_uncorrect_lut(float value) const {
|
||||
}
|
||||
#endif // USE_LIGHT_GAMMA_LUT
|
||||
|
||||
bool LightState::is_transformer_active() { return this->is_transformer_active_; }
|
||||
|
||||
void LightState::start_effect_(uint32_t effect_index) {
|
||||
this->stop_effect_();
|
||||
if (effect_index == 0)
|
||||
|
||||
@@ -109,7 +109,7 @@ class LightState : public EntityBase, public Component {
|
||||
void dump_config() override;
|
||||
void loop() override;
|
||||
/// Shortly after HARDWARE.
|
||||
float get_setup_priority() const override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE - 1.0f; }
|
||||
|
||||
/** The current values of the light as outputted to the light.
|
||||
*
|
||||
@@ -157,15 +157,19 @@ class LightState : public EntityBase, public Component {
|
||||
void add_target_state_reached_listener(LightTargetStateReachedListener *listener);
|
||||
|
||||
/// Set the default transition length, i.e. the transition length when no transition is provided.
|
||||
void set_default_transition_length(uint32_t default_transition_length);
|
||||
uint32_t get_default_transition_length() const;
|
||||
void set_default_transition_length(uint32_t default_transition_length) {
|
||||
this->default_transition_length_ = default_transition_length;
|
||||
}
|
||||
uint32_t get_default_transition_length() const { return this->default_transition_length_; }
|
||||
|
||||
/// Set the flash transition length
|
||||
void set_flash_transition_length(uint32_t flash_transition_length);
|
||||
uint32_t get_flash_transition_length() const;
|
||||
void set_flash_transition_length(uint32_t flash_transition_length) {
|
||||
this->flash_transition_length_ = flash_transition_length;
|
||||
}
|
||||
uint32_t get_flash_transition_length() const { return this->flash_transition_length_; }
|
||||
|
||||
/// Set the gamma correction factor
|
||||
void set_gamma_correct(float gamma_correct);
|
||||
void set_gamma_correct(float gamma_correct) { this->gamma_correct_ = gamma_correct; }
|
||||
float get_gamma_correct() const { return this->gamma_correct_; }
|
||||
|
||||
#ifdef USE_LIGHT_GAMMA_LUT
|
||||
@@ -186,17 +190,17 @@ class LightState : public EntityBase, public Component {
|
||||
#endif // USE_LIGHT_GAMMA_LUT
|
||||
|
||||
/// Set the restore mode of this light
|
||||
void set_restore_mode(LightRestoreMode restore_mode);
|
||||
void set_restore_mode(LightRestoreMode restore_mode) { this->restore_mode_ = restore_mode; }
|
||||
|
||||
/// Set a callback to populate the initial state defaults during setup.
|
||||
/// The callback is called once, then cleared. Values live in flash as code.
|
||||
void set_initial_state(void (*callback)(LightStateRTCState &));
|
||||
void set_initial_state(void (*callback)(LightStateRTCState &)) { this->initial_state_callback_ = callback; }
|
||||
|
||||
/// Return whether the light has any effects that meet the trait requirements.
|
||||
bool supports_effects();
|
||||
bool supports_effects() const { return !this->effects_.empty(); }
|
||||
|
||||
/// Get all effects for this light state.
|
||||
const FixedVector<LightEffect *> &get_effects() const;
|
||||
const FixedVector<LightEffect *> &get_effects() const { return this->effects_; }
|
||||
|
||||
/// Add effects for this light state.
|
||||
void add_effects(const std::initializer_list<LightEffect *> &effects);
|
||||
@@ -254,7 +258,7 @@ class LightState : public EntityBase, public Component {
|
||||
}
|
||||
|
||||
/// The result of all the current_values_as_* methods have gamma correction applied.
|
||||
void current_values_as_binary(bool *binary);
|
||||
void current_values_as_binary(bool *binary) { this->current_values.as_binary(binary); }
|
||||
|
||||
void current_values_as_brightness(float *brightness);
|
||||
|
||||
@@ -281,7 +285,7 @@ class LightState : public EntityBase, public Component {
|
||||
* return;
|
||||
* }
|
||||
*/
|
||||
bool is_transformer_active();
|
||||
bool is_transformer_active() const { return this->is_transformer_active_; }
|
||||
|
||||
protected:
|
||||
friend LightOutput;
|
||||
|
||||
@@ -201,17 +201,10 @@ void Logger::process_messages_() {
|
||||
#endif // USE_ESPHOME_TASK_LOG_BUFFER
|
||||
}
|
||||
|
||||
void Logger::set_baud_rate(uint32_t baud_rate) { this->baud_rate_ = baud_rate; }
|
||||
#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
|
||||
void Logger::set_log_level(const char *tag, uint8_t log_level) { this->log_levels_[tag] = log_level; }
|
||||
#endif
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
|
||||
UARTSelection Logger::get_uart() const { return this->uart_; }
|
||||
#endif
|
||||
|
||||
float Logger::get_setup_priority() const { return setup_priority::BUS + 500.0f; }
|
||||
|
||||
// Log level strings - packed into flash on ESP8266, indexed by log level (0-7)
|
||||
PROGMEM_STRING_TABLE(LogLevelStrings, "NONE", "ERROR", "WARN", "INFO", "CONFIG", "DEBUG", "VERBOSE", "VERY_VERBOSE");
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ class Logger final : public Component {
|
||||
void loop() override;
|
||||
#endif
|
||||
/// Manually set the baud rate for serial, set to 0 to disable.
|
||||
void set_baud_rate(uint32_t baud_rate);
|
||||
void set_baud_rate(uint32_t baud_rate) { this->baud_rate_ = baud_rate; }
|
||||
uint32_t get_baud_rate() const { return baud_rate_; }
|
||||
#if defined(USE_ARDUINO) && !defined(USE_ESP32)
|
||||
Stream *get_hw_serial() const { return hw_serial_; }
|
||||
@@ -163,7 +163,7 @@ class Logger final : public Component {
|
||||
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
|
||||
void set_uart_selection(UARTSelection uart_selection) { uart_ = uart_selection; }
|
||||
/// Get the UART used by the logger.
|
||||
UARTSelection get_uart() const;
|
||||
UARTSelection get_uart() const { return this->uart_; }
|
||||
#endif
|
||||
|
||||
/// Set the default log level for this logger.
|
||||
@@ -197,7 +197,7 @@ class Logger final : public Component {
|
||||
void add_level_listener(LoggerLevelListener *listener) { this->level_listeners_.push_back(listener); }
|
||||
#endif
|
||||
|
||||
float get_setup_priority() const override;
|
||||
float get_setup_priority() const override { return setup_priority::BUS + 500.0f; }
|
||||
|
||||
void log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args); // NOLINT
|
||||
#ifdef USE_STORE_LOG_STR_IN_FLASH
|
||||
|
||||
@@ -668,9 +668,7 @@ void MQTTClientComponent::on_message(const std::string &topic, const std::string
|
||||
// Setters
|
||||
void MQTTClientComponent::disable_log_message() { this->log_message_.topic = ""; }
|
||||
bool MQTTClientComponent::is_log_message_enabled() const { return !this->log_message_.topic.empty(); }
|
||||
void MQTTClientComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; }
|
||||
void MQTTClientComponent::register_mqtt_component(MQTTComponent *component) { this->children_.push_back(component); }
|
||||
void MQTTClientComponent::set_log_level(int level) { this->log_level_ = level; }
|
||||
void MQTTClientComponent::set_keep_alive(uint16_t keep_alive_s) { this->mqtt_backend_.set_keep_alive(keep_alive_s); }
|
||||
void MQTTClientComponent::set_log_message_template(MQTTMessage &&message) { this->log_message_ = std::move(message); }
|
||||
const MQTTDiscoveryInfo &MQTTClientComponent::get_discovery_info() const { return this->discovery_info_; }
|
||||
@@ -683,10 +681,6 @@ void MQTTClientComponent::set_topic_prefix(const std::string &topic_prefix, cons
|
||||
}
|
||||
}
|
||||
const std::string &MQTTClientComponent::get_topic_prefix() const { return this->topic_prefix_; }
|
||||
void MQTTClientComponent::set_publish_nan_as_none(bool publish_nan_as_none) {
|
||||
this->publish_nan_as_none_ = publish_nan_as_none;
|
||||
}
|
||||
bool MQTTClientComponent::is_publish_nan_as_none() const { return this->publish_nan_as_none_; }
|
||||
void MQTTClientComponent::disable_birth_message() {
|
||||
this->birth_message_.topic = "";
|
||||
this->recalculate_availability_();
|
||||
@@ -766,8 +760,6 @@ MQTTClientComponent *global_mqtt_client = nullptr; // NOLINT(cppcoreguidelines-
|
||||
|
||||
// MQTTMessageTrigger
|
||||
MQTTMessageTrigger::MQTTMessageTrigger(std::string topic) : topic_(std::move(topic)) {}
|
||||
void MQTTMessageTrigger::set_qos(uint8_t qos) { this->qos_ = qos; }
|
||||
void MQTTMessageTrigger::set_payload(const std::string &payload) { this->payload_ = payload; }
|
||||
void MQTTMessageTrigger::setup() {
|
||||
global_mqtt_client->subscribe(
|
||||
this->topic_,
|
||||
|
||||
@@ -159,7 +159,7 @@ class MQTTClientComponent final : public Component {
|
||||
|
||||
/// Manually set the topic used for logging.
|
||||
void set_log_message_template(MQTTMessage &&message);
|
||||
void set_log_level(int level);
|
||||
void set_log_level(int level) { this->log_level_ = level; }
|
||||
/// Get the topic used for logging. Defaults to "<topic_prefix>/debug" and the value is cached for speed.
|
||||
void disable_log_message();
|
||||
bool is_log_message_enabled() const;
|
||||
@@ -241,7 +241,7 @@ class MQTTClientComponent final : public Component {
|
||||
|
||||
void check_connected();
|
||||
|
||||
void set_reboot_timeout(uint32_t reboot_timeout);
|
||||
void set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; }
|
||||
|
||||
void register_mqtt_component(MQTTComponent *component);
|
||||
|
||||
@@ -262,8 +262,8 @@ class MQTTClientComponent final : public Component {
|
||||
void set_on_disconnect(mqtt_on_disconnect_callback_t &&callback);
|
||||
|
||||
// Publish None state instead of NaN for Home Assistant
|
||||
void set_publish_nan_as_none(bool publish_nan_as_none);
|
||||
bool is_publish_nan_as_none() const;
|
||||
void set_publish_nan_as_none(bool publish_nan_as_none) { this->publish_nan_as_none_ = publish_nan_as_none; }
|
||||
bool is_publish_nan_as_none() const { return this->publish_nan_as_none_; }
|
||||
|
||||
void set_wait_for_connection(bool wait_for_connection) { this->wait_for_connection_ = wait_for_connection; }
|
||||
|
||||
@@ -344,8 +344,8 @@ class MQTTMessageTrigger final : public Trigger<std::string>, public Component {
|
||||
public:
|
||||
explicit MQTTMessageTrigger(std::string topic);
|
||||
|
||||
void set_qos(uint8_t qos);
|
||||
void set_payload(const std::string &payload);
|
||||
void set_qos(uint8_t qos) { this->qos_ = qos; }
|
||||
void set_payload(const std::string &payload) { this->payload_ = payload; }
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
|
||||
@@ -340,10 +340,6 @@ bool MQTTComponent::send_discovery_() {
|
||||
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
}
|
||||
|
||||
uint8_t MQTTComponent::get_qos() const { return this->qos_; }
|
||||
|
||||
bool MQTTComponent::get_retain() const { return this->retain_; }
|
||||
|
||||
bool MQTTComponent::is_discovery_enabled() const {
|
||||
return this->discovery_enabled_ && global_mqtt_client->is_discovery_enabled();
|
||||
}
|
||||
|
||||
@@ -108,11 +108,11 @@ class MQTTComponent : public Component {
|
||||
|
||||
/// Set QOS for state messages.
|
||||
void set_qos(uint8_t qos);
|
||||
uint8_t get_qos() const;
|
||||
uint8_t get_qos() const { return this->qos_; }
|
||||
|
||||
/// Set whether state message should be retained.
|
||||
void set_retain(bool retain);
|
||||
bool get_retain() const;
|
||||
bool get_retain() const { return this->retain_; }
|
||||
|
||||
/// Disable discovery. Sets friendly name to "".
|
||||
void disable_discovery();
|
||||
|
||||
@@ -39,8 +39,6 @@ uint32_t MQTTSensorComponent::get_expire_after() const {
|
||||
return *this->expire_after_;
|
||||
return 0;
|
||||
}
|
||||
void MQTTSensorComponent::set_expire_after(uint32_t expire_after) { this->expire_after_ = expire_after; }
|
||||
void MQTTSensorComponent::disable_expire_after() { this->expire_after_ = 0; }
|
||||
|
||||
void MQTTSensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
||||
|
||||
@@ -22,9 +22,9 @@ class MQTTSensorComponent final : public mqtt::MQTTComponent {
|
||||
explicit MQTTSensorComponent(sensor::Sensor *sensor);
|
||||
|
||||
/// Setup an expiry, 0 disables it
|
||||
void set_expire_after(uint32_t expire_after);
|
||||
void set_expire_after(uint32_t expire_after) { this->expire_after_ = expire_after; }
|
||||
/// Disable Home Assistant value expiry.
|
||||
void disable_expire_after();
|
||||
void disable_expire_after() { this->expire_after_ = 0; }
|
||||
|
||||
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override;
|
||||
|
||||
|
||||
@@ -81,8 +81,6 @@ void RadioFrequency::dump_config() {
|
||||
}
|
||||
}
|
||||
|
||||
RadioFrequencyCall RadioFrequency::make_call() { return RadioFrequencyCall(this); }
|
||||
|
||||
uint32_t RadioFrequency::get_capability_flags() const {
|
||||
uint32_t flags = 0;
|
||||
if (this->traits_.get_supports_transmitter())
|
||||
|
||||
@@ -157,7 +157,7 @@ class RadioFrequency : public Component, public EntityBase, public remote_base::
|
||||
const RadioFrequencyTraits &get_traits() const { return this->traits_; }
|
||||
|
||||
/// Create a call object for transmitting
|
||||
RadioFrequencyCall make_call();
|
||||
RadioFrequencyCall make_call() { return RadioFrequencyCall(this); }
|
||||
|
||||
/// Get capability flags for this radio frequency instance
|
||||
uint32_t get_capability_flags() const;
|
||||
|
||||
@@ -7,10 +7,6 @@ namespace esphome::safe_mode {
|
||||
|
||||
static const char *const TAG = "safe_mode.button";
|
||||
|
||||
void SafeModeButton::set_safe_mode(SafeModeComponent *safe_mode_component) {
|
||||
this->safe_mode_component_ = safe_mode_component;
|
||||
}
|
||||
|
||||
void SafeModeButton::press_action() {
|
||||
ESP_LOGI(TAG, "Restarting in safe mode");
|
||||
this->safe_mode_component_->set_safe_mode_pending(true);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace esphome::safe_mode {
|
||||
class SafeModeButton final : public button::Button, public Component {
|
||||
public:
|
||||
void dump_config() override;
|
||||
void set_safe_mode(SafeModeComponent *safe_mode_component);
|
||||
void set_safe_mode(SafeModeComponent *safe_mode_component) { this->safe_mode_component_ = safe_mode_component; }
|
||||
|
||||
protected:
|
||||
SafeModeComponent *safe_mode_component_;
|
||||
|
||||
@@ -7,10 +7,6 @@ namespace esphome::safe_mode {
|
||||
|
||||
static const char *const TAG = "safe_mode.switch";
|
||||
|
||||
void SafeModeSwitch::set_safe_mode(SafeModeComponent *safe_mode_component) {
|
||||
this->safe_mode_component_ = safe_mode_component;
|
||||
}
|
||||
|
||||
void SafeModeSwitch::write_state(bool state) {
|
||||
// Acknowledge
|
||||
this->publish_state(false);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace esphome::safe_mode {
|
||||
class SafeModeSwitch final : public switch_::Switch, public Component {
|
||||
public:
|
||||
void dump_config() override;
|
||||
void set_safe_mode(SafeModeComponent *safe_mode_component);
|
||||
void set_safe_mode(SafeModeComponent *safe_mode_component) { this->safe_mode_component_ = safe_mode_component; }
|
||||
|
||||
protected:
|
||||
SafeModeComponent *safe_mode_component_;
|
||||
|
||||
@@ -8,8 +8,6 @@ namespace esphome::select {
|
||||
|
||||
static const char *const TAG = "select";
|
||||
|
||||
void Select::publish_state(const std::string &state) { this->publish_state(state.c_str()); }
|
||||
|
||||
void Select::publish_state(const char *state) {
|
||||
auto index = this->index_of(state);
|
||||
if (index.has_value()) {
|
||||
@@ -34,21 +32,6 @@ void Select::publish_state(size_t index) {
|
||||
#endif
|
||||
}
|
||||
|
||||
StringRef Select::current_option() const {
|
||||
return this->has_state() ? StringRef(this->option_at(this->active_index_)) : StringRef();
|
||||
}
|
||||
|
||||
bool Select::has_option(const std::string &option) const { return this->index_of(option.c_str()).has_value(); }
|
||||
|
||||
bool Select::has_option(const char *option) const { return this->index_of(option).has_value(); }
|
||||
|
||||
bool Select::has_index(size_t index) const { return index < this->size(); }
|
||||
|
||||
size_t Select::size() const {
|
||||
const auto &options = traits.get_options();
|
||||
return options.size();
|
||||
}
|
||||
|
||||
optional<size_t> Select::index_of(const char *option, size_t len) const {
|
||||
const auto &options = traits.get_options();
|
||||
for (size_t i = 0; i < options.size(); i++) {
|
||||
|
||||
@@ -33,27 +33,29 @@ class Select : public EntityBase {
|
||||
Select() = default;
|
||||
~Select() = default;
|
||||
|
||||
void publish_state(const std::string &state);
|
||||
void publish_state(const std::string &state) { this->publish_state(state.c_str()); }
|
||||
void publish_state(const char *state);
|
||||
void publish_state(size_t index);
|
||||
|
||||
/// Return the currently selected option, or empty StringRef if no state.
|
||||
/// The returned StringRef points to string literals from codegen (static storage).
|
||||
/// Traits are set once at startup and valid for the lifetime of the program.
|
||||
StringRef current_option() const;
|
||||
StringRef current_option() const {
|
||||
return this->has_state() ? StringRef(this->option_at(this->active_index_)) : StringRef();
|
||||
}
|
||||
|
||||
/// Instantiate a SelectCall object to modify this select component's state.
|
||||
SelectCall make_call() { return SelectCall(this); }
|
||||
|
||||
/// Return whether this select component contains the provided option.
|
||||
bool has_option(const std::string &option) const;
|
||||
bool has_option(const char *option) const;
|
||||
bool has_option(const std::string &option) const { return this->index_of(option).has_value(); }
|
||||
bool has_option(const char *option) const { return this->index_of(option).has_value(); }
|
||||
|
||||
/// Return whether this select component contains the provided index offset.
|
||||
bool has_index(size_t index) const;
|
||||
bool has_index(size_t index) const { return index < this->size(); }
|
||||
|
||||
/// Return the number of options in this select component.
|
||||
size_t size() const;
|
||||
size_t size() const { return this->traits.get_options().size(); }
|
||||
|
||||
/// Find the (optional) index offset of the provided option value.
|
||||
optional<size_t> index_of(const char *option, size_t len) const;
|
||||
|
||||
@@ -11,6 +11,4 @@ void SelectTraits::set_options(const FixedVector<const char *> &options) {
|
||||
}
|
||||
}
|
||||
|
||||
const FixedVector<const char *> &SelectTraits::get_options() const { return this->options_; }
|
||||
|
||||
} // namespace esphome::select
|
||||
|
||||
@@ -9,7 +9,7 @@ class SelectTraits {
|
||||
public:
|
||||
void set_options(const std::initializer_list<const char *> &options);
|
||||
void set_options(const FixedVector<const char *> &options);
|
||||
const FixedVector<const char *> &get_options() const;
|
||||
const FixedVector<const char *> &get_options() const { return this->options_; }
|
||||
|
||||
protected:
|
||||
FixedVector<const char *> options_;
|
||||
|
||||
@@ -164,8 +164,6 @@ optional<float> ExponentialMovingAverageFilter::new_value(float value) {
|
||||
}
|
||||
return {};
|
||||
}
|
||||
void ExponentialMovingAverageFilter::set_send_every(uint16_t send_every) { this->send_every_ = send_every; }
|
||||
void ExponentialMovingAverageFilter::set_alpha(float alpha) { this->alpha_ = alpha; }
|
||||
|
||||
// ThrottleAverageFilter
|
||||
ThrottleAverageFilter::ThrottleAverageFilter(uint32_t time_period) : time_period_(time_period) {}
|
||||
|
||||
@@ -239,8 +239,8 @@ class ExponentialMovingAverageFilter : public Filter {
|
||||
|
||||
optional<float> new_value(float value) override;
|
||||
|
||||
void set_send_every(uint16_t send_every);
|
||||
void set_alpha(float alpha);
|
||||
void set_send_every(uint16_t send_every) { this->send_every_ = send_every; }
|
||||
void set_alpha(float alpha) { this->alpha_ = alpha; }
|
||||
|
||||
protected:
|
||||
float accumulator_{NAN};
|
||||
|
||||
@@ -211,8 +211,6 @@ uint32_t SprinklerValveOperator::time_remaining() {
|
||||
return 0; // run completed
|
||||
}
|
||||
|
||||
SprinklerState SprinklerValveOperator::state() { return this->state_; }
|
||||
|
||||
switch_::Switch *SprinklerValveOperator::pump_switch() {
|
||||
if ((this->controller_ == nullptr) || (this->valve_ == nullptr)) {
|
||||
return nullptr;
|
||||
@@ -288,11 +286,8 @@ SprinklerValveRunRequest::SprinklerValveRunRequest(size_t valve_number, uint32_t
|
||||
SprinklerValveOperator *valve_op)
|
||||
: valve_number_(valve_number), run_duration_(run_duration), valve_op_(valve_op) {}
|
||||
|
||||
bool SprinklerValveRunRequest::has_request() { return this->has_valve_; }
|
||||
bool SprinklerValveRunRequest::has_valve_operator() { return !(this->valve_op_ == nullptr); }
|
||||
|
||||
void SprinklerValveRunRequest::set_request_from(SprinklerValveRunRequestOrigin origin) { this->origin_ = origin; }
|
||||
|
||||
void SprinklerValveRunRequest::set_run_duration(uint32_t run_duration) { this->run_duration_ = run_duration; }
|
||||
|
||||
void SprinklerValveRunRequest::set_valve(size_t valve_number) {
|
||||
@@ -317,8 +312,6 @@ void SprinklerValveRunRequest::reset() {
|
||||
|
||||
uint32_t SprinklerValveRunRequest::run_duration() { return this->run_duration_; }
|
||||
|
||||
size_t SprinklerValveRunRequest::valve() { return this->valve_number_; }
|
||||
|
||||
optional<size_t> SprinklerValveRunRequest::valve_as_opt() {
|
||||
if (this->has_valve_) {
|
||||
return this->valve_number_;
|
||||
@@ -328,8 +321,6 @@ optional<size_t> SprinklerValveRunRequest::valve_as_opt() {
|
||||
|
||||
SprinklerValveOperator *SprinklerValveRunRequest::valve_operator() { return this->valve_op_; }
|
||||
|
||||
SprinklerValveRunRequestOrigin SprinklerValveRunRequest::request_is_from() { return this->origin_; }
|
||||
|
||||
Sprinkler::Sprinkler() : Sprinkler("") {}
|
||||
Sprinkler::Sprinkler(const char *name) : name_(name) {
|
||||
// The `name` is stored for dump_config logging
|
||||
@@ -414,18 +405,6 @@ void Sprinkler::set_controller_main_switch(SprinklerControllerSwitch *controller
|
||||
this->sprinkler_turn_on_automation_->add_actions({sprinkler_resumeorstart_action_.get()});
|
||||
}
|
||||
|
||||
void Sprinkler::set_controller_auto_adv_switch(SprinklerControllerSwitch *auto_adv_switch) {
|
||||
this->auto_adv_sw_ = auto_adv_switch;
|
||||
}
|
||||
|
||||
void Sprinkler::set_controller_queue_enable_switch(SprinklerControllerSwitch *queue_enable_switch) {
|
||||
this->queue_enable_sw_ = queue_enable_switch;
|
||||
}
|
||||
|
||||
void Sprinkler::set_controller_reverse_switch(SprinklerControllerSwitch *reverse_switch) {
|
||||
this->reverse_sw_ = reverse_switch;
|
||||
}
|
||||
|
||||
void Sprinkler::set_controller_standby_switch(SprinklerControllerSwitch *standby_switch) {
|
||||
this->standby_sw_ = standby_switch;
|
||||
|
||||
@@ -434,14 +413,6 @@ void Sprinkler::set_controller_standby_switch(SprinklerControllerSwitch *standby
|
||||
this->sprinkler_standby_turn_on_automation_->add_actions({sprinkler_standby_shutdown_action_.get()});
|
||||
}
|
||||
|
||||
void Sprinkler::set_controller_multiplier_number(SprinklerControllerNumber *multiplier_number) {
|
||||
this->multiplier_number_ = multiplier_number;
|
||||
}
|
||||
|
||||
void Sprinkler::set_controller_repeat_number(SprinklerControllerNumber *repeat_number) {
|
||||
this->repeat_number_ = repeat_number;
|
||||
}
|
||||
|
||||
void Sprinkler::configure_valve_switch(size_t valve_number, switch_::Switch *valve_switch, uint32_t run_duration) {
|
||||
if (this->is_a_valid_valve(valve_number)) {
|
||||
this->valve_[valve_number].valve_switch = valve_switch;
|
||||
@@ -498,10 +469,6 @@ void Sprinkler::set_multiplier(const optional<float> multiplier) {
|
||||
call.perform();
|
||||
}
|
||||
|
||||
void Sprinkler::set_next_prev_ignore_disabled_valves(bool ignore_disabled) {
|
||||
this->next_prev_ignore_disabled_ = ignore_disabled;
|
||||
}
|
||||
|
||||
void Sprinkler::set_pump_start_delay(uint32_t start_delay) {
|
||||
this->start_delay_is_valve_delay_ = false;
|
||||
this->start_delay_ = start_delay;
|
||||
@@ -522,10 +489,6 @@ void Sprinkler::set_valve_stop_delay(uint32_t stop_delay) {
|
||||
this->stop_delay_ = stop_delay;
|
||||
}
|
||||
|
||||
void Sprinkler::set_pump_switch_off_during_valve_open_delay(bool pump_switch_off_during_valve_open_delay) {
|
||||
this->pump_switch_off_during_valve_open_delay_ = pump_switch_off_during_valve_open_delay;
|
||||
}
|
||||
|
||||
void Sprinkler::set_valve_open_delay(const uint32_t valve_open_delay) {
|
||||
if (valve_open_delay > 0) {
|
||||
this->valve_overlap_ = false;
|
||||
@@ -945,8 +908,6 @@ optional<size_t> Sprinkler::active_valve() {
|
||||
return this->active_req_.valve_as_opt();
|
||||
}
|
||||
|
||||
optional<size_t> Sprinkler::paused_valve() { return this->paused_valve_; }
|
||||
|
||||
optional<size_t> Sprinkler::queued_valve() {
|
||||
if (!this->queued_valves_.empty()) {
|
||||
return this->queued_valves_.back().valve_number;
|
||||
@@ -954,10 +915,6 @@ optional<size_t> Sprinkler::queued_valve() {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
optional<size_t> Sprinkler::manual_valve() { return this->manual_valve_; }
|
||||
|
||||
size_t Sprinkler::number_of_valves() { return this->valve_.size(); }
|
||||
|
||||
bool Sprinkler::is_a_valid_valve(const size_t valve_number) { return (valve_number < this->number_of_valves()); }
|
||||
|
||||
bool Sprinkler::pump_in_use(switch_::Switch *pump_switch) {
|
||||
|
||||
@@ -124,9 +124,9 @@ class SprinklerValveOperator {
|
||||
void set_stop_delay(uint32_t stop_delay, bool stop_delay_is_valve_delay);
|
||||
void start();
|
||||
void stop();
|
||||
uint32_t run_duration(); // returns the desired run duration in seconds
|
||||
uint32_t time_remaining(); // returns seconds remaining (does not include stop_delay_)
|
||||
SprinklerState state(); // returns the valve's state/status
|
||||
uint32_t run_duration(); // returns the desired run duration in seconds
|
||||
uint32_t time_remaining(); // returns seconds remaining (does not include stop_delay_)
|
||||
SprinklerState state() { return this->state_; }
|
||||
switch_::Switch *pump_switch(); // returns this SprinklerValveOperator's pump switch
|
||||
|
||||
protected:
|
||||
@@ -152,18 +152,18 @@ class SprinklerValveRunRequest {
|
||||
public:
|
||||
SprinklerValveRunRequest();
|
||||
SprinklerValveRunRequest(size_t valve_number, uint32_t run_duration, SprinklerValveOperator *valve_op);
|
||||
bool has_request();
|
||||
bool has_request() { return this->has_valve_; }
|
||||
bool has_valve_operator();
|
||||
void set_request_from(SprinklerValveRunRequestOrigin origin);
|
||||
void set_request_from(SprinklerValveRunRequestOrigin origin) { this->origin_ = origin; }
|
||||
void set_run_duration(uint32_t run_duration);
|
||||
void set_valve(size_t valve_number);
|
||||
void set_valve_operator(SprinklerValveOperator *valve_op);
|
||||
void reset();
|
||||
uint32_t run_duration();
|
||||
size_t valve();
|
||||
size_t valve() { return this->valve_number_; }
|
||||
optional<size_t> valve_as_opt();
|
||||
SprinklerValveOperator *valve_operator();
|
||||
SprinklerValveRunRequestOrigin request_is_from();
|
||||
SprinklerValveRunRequestOrigin request_is_from() { return this->origin_; }
|
||||
|
||||
protected:
|
||||
bool has_valve_{false};
|
||||
@@ -189,14 +189,20 @@ class Sprinkler final : public Component {
|
||||
|
||||
/// configure important controller switches
|
||||
void set_controller_main_switch(SprinklerControllerSwitch *controller_switch);
|
||||
void set_controller_auto_adv_switch(SprinklerControllerSwitch *auto_adv_switch);
|
||||
void set_controller_queue_enable_switch(SprinklerControllerSwitch *queue_enable_switch);
|
||||
void set_controller_reverse_switch(SprinklerControllerSwitch *reverse_switch);
|
||||
void set_controller_auto_adv_switch(SprinklerControllerSwitch *auto_adv_switch) {
|
||||
this->auto_adv_sw_ = auto_adv_switch;
|
||||
}
|
||||
void set_controller_queue_enable_switch(SprinklerControllerSwitch *queue_enable_switch) {
|
||||
this->queue_enable_sw_ = queue_enable_switch;
|
||||
}
|
||||
void set_controller_reverse_switch(SprinklerControllerSwitch *reverse_switch) { this->reverse_sw_ = reverse_switch; }
|
||||
void set_controller_standby_switch(SprinklerControllerSwitch *standby_switch);
|
||||
|
||||
/// configure important controller number components
|
||||
void set_controller_multiplier_number(SprinklerControllerNumber *multiplier_number);
|
||||
void set_controller_repeat_number(SprinklerControllerNumber *repeat_number);
|
||||
void set_controller_multiplier_number(SprinklerControllerNumber *multiplier_number) {
|
||||
this->multiplier_number_ = multiplier_number;
|
||||
}
|
||||
void set_controller_repeat_number(SprinklerControllerNumber *repeat_number) { this->repeat_number_ = repeat_number; }
|
||||
|
||||
/// configure a valve's switch object and run duration. run_duration is time in seconds.
|
||||
void configure_valve_switch(size_t valve_number, switch_::Switch *valve_switch, uint32_t run_duration);
|
||||
@@ -214,7 +220,9 @@ class Sprinkler final : public Component {
|
||||
void set_multiplier(optional<float> multiplier);
|
||||
|
||||
/// enable/disable skipping of disabled valves by the next and previous actions
|
||||
void set_next_prev_ignore_disabled_valves(bool ignore_disabled);
|
||||
void set_next_prev_ignore_disabled_valves(bool ignore_disabled) {
|
||||
this->next_prev_ignore_disabled_ = ignore_disabled;
|
||||
}
|
||||
|
||||
/// set how long the pump should start after the valve (when the pump is starting)
|
||||
void set_pump_start_delay(uint32_t start_delay);
|
||||
@@ -230,7 +238,9 @@ class Sprinkler final : public Component {
|
||||
|
||||
/// if pump_switch_off_during_valve_open_delay is true, the controller will switch off the pump during the
|
||||
/// valve_open_delay interval
|
||||
void set_pump_switch_off_during_valve_open_delay(bool pump_switch_off_during_valve_open_delay);
|
||||
void set_pump_switch_off_during_valve_open_delay(bool pump_switch_off_during_valve_open_delay) {
|
||||
this->pump_switch_off_during_valve_open_delay_ = pump_switch_off_during_valve_open_delay;
|
||||
}
|
||||
|
||||
/// set how long the controller should wait to open/switch on the valve after it becomes active
|
||||
void set_valve_open_delay(uint32_t valve_open_delay);
|
||||
@@ -335,17 +345,17 @@ class Sprinkler final : public Component {
|
||||
optional<size_t> active_valve();
|
||||
|
||||
/// returns the number of the valve that is paused, if any. check with 'has_value()'
|
||||
optional<size_t> paused_valve();
|
||||
optional<size_t> paused_valve() { return this->paused_valve_; }
|
||||
|
||||
/// returns the number of the next valve in the queue, if any. check with 'has_value()'
|
||||
optional<size_t> queued_valve();
|
||||
|
||||
/// returns the number of the valve that is manually selected, if any. check with 'has_value()'
|
||||
/// this is set by next_valve() and previous_valve() when manual_selection_delay_ > 0
|
||||
optional<size_t> manual_valve();
|
||||
optional<size_t> manual_valve() { return this->manual_valve_; }
|
||||
|
||||
/// returns the number of valves the controller is configured with
|
||||
size_t number_of_valves();
|
||||
size_t number_of_valves() { return this->valve_.size(); }
|
||||
|
||||
/// returns true if valve number is valid
|
||||
bool is_a_valid_valve(size_t valve_number);
|
||||
|
||||
@@ -69,9 +69,6 @@ void Switch::publish_state(bool state) {
|
||||
}
|
||||
bool Switch::assumed_state() { return false; }
|
||||
|
||||
void Switch::set_inverted(bool inverted) { this->inverted_ = inverted; }
|
||||
bool Switch::is_inverted() const { return this->inverted_; }
|
||||
|
||||
void log_switch(const char *tag, const char *prefix, const char *type, Switch *obj) {
|
||||
if (obj != nullptr) {
|
||||
// Prepare restore mode string
|
||||
|
||||
@@ -87,7 +87,7 @@ class Switch : public EntityBase {
|
||||
*
|
||||
* @param inverted Whether to invert this switch.
|
||||
*/
|
||||
void set_inverted(bool inverted);
|
||||
void set_inverted(bool inverted) { this->inverted_ = inverted; }
|
||||
|
||||
/** Set callback for state changes.
|
||||
*
|
||||
@@ -117,7 +117,7 @@ class Switch : public EntityBase {
|
||||
*/
|
||||
virtual bool assumed_state();
|
||||
|
||||
bool is_inverted() const;
|
||||
bool is_inverted() const { return this->inverted_; }
|
||||
|
||||
void set_restore_mode(SwitchRestoreMode restore_mode) { this->restore_mode = restore_mode; }
|
||||
|
||||
|
||||
@@ -8,10 +8,6 @@ namespace esphome::text {
|
||||
|
||||
static const char *const TAG = "text";
|
||||
|
||||
void Text::publish_state(const std::string &state) { this->publish_state(state.data(), state.size()); }
|
||||
|
||||
void Text::publish_state(const char *state) { this->publish_state(state, strlen(state)); }
|
||||
|
||||
void Text::publish_state(const char *state, size_t len) {
|
||||
this->set_has_state(true);
|
||||
// Only assign if changed to avoid heap allocation
|
||||
|
||||
@@ -23,8 +23,8 @@ class Text : public EntityBase {
|
||||
std::string state;
|
||||
TextTraits traits;
|
||||
|
||||
void publish_state(const std::string &state);
|
||||
void publish_state(const char *state);
|
||||
void publish_state(const std::string &state) { this->publish_state(state.data(), state.size()); }
|
||||
void publish_state(const char *state) { this->publish_state(state, strlen(state)); }
|
||||
void publish_state(const char *state, size_t len);
|
||||
|
||||
/// Instantiate a TextCall object to modify this text component's state.
|
||||
|
||||
@@ -18,10 +18,6 @@ void log_text_sensor(const char *tag, const char *prefix, const char *type, Text
|
||||
LOG_ENTITY_ICON(tag, prefix, *obj);
|
||||
}
|
||||
|
||||
void TextSensor::publish_state(const std::string &state) { this->publish_state(state.data(), state.size()); }
|
||||
|
||||
void TextSensor::publish_state(const char *state) { this->publish_state(state, strlen(state)); }
|
||||
|
||||
void TextSensor::publish_state(const char *state, size_t len) {
|
||||
#ifdef USE_TEXT_SENSOR_FILTER
|
||||
if (this->filter_list_ == nullptr) {
|
||||
@@ -91,10 +87,6 @@ const std::string &TextSensor::get_raw_state() const {
|
||||
#endif
|
||||
return this->state; // No filters, raw == filtered
|
||||
}
|
||||
void TextSensor::internal_send_state_to_frontend(const std::string &state) {
|
||||
this->internal_send_state_to_frontend(state.data(), state.size());
|
||||
}
|
||||
|
||||
void TextSensor::internal_send_state_to_frontend(const char *state, size_t len) {
|
||||
// Only assign if changed to avoid heap allocation
|
||||
if (len != this->state.size() || memcmp(state, this->state.data(), len) != 0) {
|
||||
|
||||
@@ -37,8 +37,8 @@ class TextSensor : public EntityBase {
|
||||
/// Returns the raw (pre-filter) state.
|
||||
const std::string &get_raw_state() const;
|
||||
|
||||
void publish_state(const std::string &state);
|
||||
void publish_state(const char *state);
|
||||
void publish_state(const std::string &state) { this->publish_state(state.data(), state.size()); }
|
||||
void publish_state(const char *state) { this->publish_state(state, strlen(state)); }
|
||||
void publish_state(const char *state, size_t len);
|
||||
|
||||
#ifdef USE_TEXT_SENSOR_FILTER
|
||||
@@ -70,7 +70,9 @@ class TextSensor : public EntityBase {
|
||||
// ========== INTERNAL METHODS ==========
|
||||
// (In most use cases you won't need these)
|
||||
|
||||
void internal_send_state_to_frontend(const std::string &state);
|
||||
void internal_send_state_to_frontend(const std::string &state) {
|
||||
this->internal_send_state_to_frontend(state.data(), state.size());
|
||||
}
|
||||
void internal_send_state_to_frontend(const char *state, size_t len);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -76,11 +76,6 @@ void ThermostatClimate::loop() {
|
||||
}
|
||||
}
|
||||
|
||||
float ThermostatClimate::cool_deadband() { return this->cooling_deadband_; }
|
||||
float ThermostatClimate::cool_overrun() { return this->cooling_overrun_; }
|
||||
float ThermostatClimate::heat_deadband() { return this->heating_deadband_; }
|
||||
float ThermostatClimate::heat_overrun() { return this->heating_overrun_; }
|
||||
|
||||
void ThermostatClimate::refresh() {
|
||||
this->switch_to_mode_(this->mode, false);
|
||||
this->switch_to_action_(this->compute_action_(), false);
|
||||
@@ -121,8 +116,6 @@ bool ThermostatClimate::fan_mode_change_delayed() {
|
||||
|
||||
climate::ClimateAction ThermostatClimate::delayed_climate_action() { return this->compute_action_(true); }
|
||||
|
||||
climate::ClimateFanMode ThermostatClimate::locked_fan_mode() { return this->prev_fan_mode_; }
|
||||
|
||||
bool ThermostatClimate::hysteresis_valid() {
|
||||
if ((this->supports_cool_ || (this->supports_fan_only_ && this->supports_fan_only_cooling_)) &&
|
||||
(std::isnan(this->cooling_deadband_) || std::isnan(this->cooling_overrun_)))
|
||||
@@ -1286,10 +1279,6 @@ bool ThermostatClimate::change_preset_internal_(const ThermostatClimateTargetTem
|
||||
return something_changed;
|
||||
}
|
||||
|
||||
void ThermostatClimate::set_preset_config(std::initializer_list<PresetEntry> presets) {
|
||||
this->preset_config_ = presets;
|
||||
}
|
||||
|
||||
void ThermostatClimate::set_custom_preset_config(std::initializer_list<CustomPresetEntry> presets) {
|
||||
this->custom_preset_config_ = presets;
|
||||
// Populate Climate base class custom presets vector
|
||||
@@ -1317,19 +1306,6 @@ void ThermostatClimate::set_default_preset(const char *custom_preset) {
|
||||
|
||||
void ThermostatClimate::set_default_preset(climate::ClimatePreset preset) { this->default_preset_ = preset; }
|
||||
|
||||
void ThermostatClimate::set_on_boot_restore_from(thermostat::OnBootRestoreFrom on_boot_restore_from) {
|
||||
this->on_boot_restore_from_ = on_boot_restore_from;
|
||||
}
|
||||
void ThermostatClimate::set_set_point_minimum_differential(float differential) {
|
||||
this->set_point_minimum_differential_ = differential;
|
||||
}
|
||||
void ThermostatClimate::set_cool_deadband(float deadband) { this->cooling_deadband_ = deadband; }
|
||||
void ThermostatClimate::set_cool_overrun(float overrun) { this->cooling_overrun_ = overrun; }
|
||||
void ThermostatClimate::set_heat_deadband(float deadband) { this->heating_deadband_ = deadband; }
|
||||
void ThermostatClimate::set_heat_overrun(float overrun) { this->heating_overrun_ = overrun; }
|
||||
void ThermostatClimate::set_supplemental_cool_delta(float delta) { this->supplemental_cool_delta_ = delta; }
|
||||
void ThermostatClimate::set_supplemental_heat_delta(float delta) { this->supplemental_heat_delta_ = delta; }
|
||||
|
||||
void ThermostatClimate::set_timer_duration_in_sec_(ThermostatClimateTimerIndex timer_index, uint32_t time) {
|
||||
uint32_t new_duration_ms = 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
|
||||
|
||||
@@ -1389,80 +1365,9 @@ void ThermostatClimate::set_heating_minimum_run_time_in_sec(uint32_t time) {
|
||||
void ThermostatClimate::set_idle_minimum_time_in_sec(uint32_t time) {
|
||||
this->set_timer_duration_in_sec_(thermostat::THERMOSTAT_TIMER_IDLE_ON, time);
|
||||
}
|
||||
void ThermostatClimate::set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
|
||||
void ThermostatClimate::set_humidity_sensor(sensor::Sensor *humidity_sensor) {
|
||||
this->humidity_sensor_ = humidity_sensor;
|
||||
}
|
||||
void ThermostatClimate::set_humidity_hysteresis(float humidity_hysteresis) {
|
||||
this->humidity_hysteresis_ = std::clamp<float>(humidity_hysteresis, 0.0f, 100.0f);
|
||||
}
|
||||
void ThermostatClimate::set_use_startup_delay(bool use_startup_delay) { this->use_startup_delay_ = use_startup_delay; }
|
||||
void ThermostatClimate::set_supports_heat_cool(bool supports_heat_cool) {
|
||||
this->supports_heat_cool_ = supports_heat_cool;
|
||||
}
|
||||
void ThermostatClimate::set_supports_auto(bool supports_auto) { this->supports_auto_ = supports_auto; }
|
||||
void ThermostatClimate::set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
|
||||
void ThermostatClimate::set_supports_dry(bool supports_dry) { this->supports_dry_ = supports_dry; }
|
||||
void ThermostatClimate::set_supports_fan_only(bool supports_fan_only) { this->supports_fan_only_ = supports_fan_only; }
|
||||
void ThermostatClimate::set_supports_fan_only_action_uses_fan_mode_timer(
|
||||
bool supports_fan_only_action_uses_fan_mode_timer) {
|
||||
this->supports_fan_only_action_uses_fan_mode_timer_ = supports_fan_only_action_uses_fan_mode_timer;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_only_cooling(bool supports_fan_only_cooling) {
|
||||
this->supports_fan_only_cooling_ = supports_fan_only_cooling;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_with_cooling(bool supports_fan_with_cooling) {
|
||||
this->supports_fan_with_cooling_ = supports_fan_with_cooling;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_with_heating(bool supports_fan_with_heating) {
|
||||
this->supports_fan_with_heating_ = supports_fan_with_heating;
|
||||
}
|
||||
void ThermostatClimate::set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
|
||||
void ThermostatClimate::set_supports_fan_mode_on(bool supports_fan_mode_on) {
|
||||
this->supports_fan_mode_on_ = supports_fan_mode_on;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_mode_off(bool supports_fan_mode_off) {
|
||||
this->supports_fan_mode_off_ = supports_fan_mode_off;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_mode_auto(bool supports_fan_mode_auto) {
|
||||
this->supports_fan_mode_auto_ = supports_fan_mode_auto;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_mode_low(bool supports_fan_mode_low) {
|
||||
this->supports_fan_mode_low_ = supports_fan_mode_low;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_mode_medium(bool supports_fan_mode_medium) {
|
||||
this->supports_fan_mode_medium_ = supports_fan_mode_medium;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_mode_high(bool supports_fan_mode_high) {
|
||||
this->supports_fan_mode_high_ = supports_fan_mode_high;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_mode_middle(bool supports_fan_mode_middle) {
|
||||
this->supports_fan_mode_middle_ = supports_fan_mode_middle;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_mode_focus(bool supports_fan_mode_focus) {
|
||||
this->supports_fan_mode_focus_ = supports_fan_mode_focus;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_mode_diffuse(bool supports_fan_mode_diffuse) {
|
||||
this->supports_fan_mode_diffuse_ = supports_fan_mode_diffuse;
|
||||
}
|
||||
void ThermostatClimate::set_supports_fan_mode_quiet(bool supports_fan_mode_quiet) {
|
||||
this->supports_fan_mode_quiet_ = supports_fan_mode_quiet;
|
||||
}
|
||||
void ThermostatClimate::set_supports_swing_mode_both(bool supports_swing_mode_both) {
|
||||
this->supports_swing_mode_both_ = supports_swing_mode_both;
|
||||
}
|
||||
void ThermostatClimate::set_supports_swing_mode_off(bool supports_swing_mode_off) {
|
||||
this->supports_swing_mode_off_ = supports_swing_mode_off;
|
||||
}
|
||||
void ThermostatClimate::set_supports_swing_mode_horizontal(bool supports_swing_mode_horizontal) {
|
||||
this->supports_swing_mode_horizontal_ = supports_swing_mode_horizontal;
|
||||
}
|
||||
void ThermostatClimate::set_supports_swing_mode_vertical(bool supports_swing_mode_vertical) {
|
||||
this->supports_swing_mode_vertical_ = supports_swing_mode_vertical;
|
||||
}
|
||||
void ThermostatClimate::set_supports_two_points(bool supports_two_points) {
|
||||
this->supports_two_points_ = supports_two_points;
|
||||
}
|
||||
void ThermostatClimate::set_supports_dehumidification(bool supports_dehumidification) {
|
||||
this->supports_dehumidification_ = supports_dehumidification;
|
||||
if (supports_dehumidification) {
|
||||
|
||||
@@ -93,14 +93,16 @@ class ThermostatClimate final : public climate::Climate, public Component {
|
||||
|
||||
void set_default_preset(const char *custom_preset);
|
||||
void set_default_preset(climate::ClimatePreset preset);
|
||||
void set_on_boot_restore_from(OnBootRestoreFrom on_boot_restore_from);
|
||||
void set_set_point_minimum_differential(float differential);
|
||||
void set_cool_deadband(float deadband);
|
||||
void set_cool_overrun(float overrun);
|
||||
void set_heat_deadband(float deadband);
|
||||
void set_heat_overrun(float overrun);
|
||||
void set_supplemental_cool_delta(float delta);
|
||||
void set_supplemental_heat_delta(float delta);
|
||||
void set_on_boot_restore_from(thermostat::OnBootRestoreFrom on_boot_restore_from) {
|
||||
this->on_boot_restore_from_ = on_boot_restore_from;
|
||||
}
|
||||
void set_set_point_minimum_differential(float differential) { this->set_point_minimum_differential_ = differential; }
|
||||
void set_cool_deadband(float deadband) { this->cooling_deadband_ = deadband; }
|
||||
void set_cool_overrun(float overrun) { this->cooling_overrun_ = overrun; }
|
||||
void set_heat_deadband(float deadband) { this->heating_deadband_ = deadband; }
|
||||
void set_heat_overrun(float overrun) { this->heating_overrun_ = overrun; }
|
||||
void set_supplemental_cool_delta(float delta) { this->supplemental_cool_delta_ = delta; }
|
||||
void set_supplemental_heat_delta(float delta) { this->supplemental_heat_delta_ = delta; }
|
||||
void set_cooling_maximum_run_time_in_sec(uint32_t time);
|
||||
void set_heating_maximum_run_time_in_sec(uint32_t time);
|
||||
void set_cooling_minimum_off_time_in_sec(uint32_t time);
|
||||
@@ -111,39 +113,69 @@ class ThermostatClimate final : public climate::Climate, public Component {
|
||||
void set_heating_minimum_off_time_in_sec(uint32_t time);
|
||||
void set_heating_minimum_run_time_in_sec(uint32_t time);
|
||||
void set_idle_minimum_time_in_sec(uint32_t time);
|
||||
void set_sensor(sensor::Sensor *sensor);
|
||||
void set_humidity_sensor(sensor::Sensor *humidity_sensor);
|
||||
void set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
|
||||
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; }
|
||||
void set_humidity_hysteresis(float humidity_hysteresis);
|
||||
void set_use_startup_delay(bool use_startup_delay);
|
||||
void set_supports_auto(bool supports_auto);
|
||||
void set_supports_heat_cool(bool supports_heat_cool);
|
||||
void set_supports_cool(bool supports_cool);
|
||||
void set_supports_dry(bool supports_dry);
|
||||
void set_supports_fan_only(bool supports_fan_only);
|
||||
void set_supports_fan_only_action_uses_fan_mode_timer(bool fan_only_action_uses_fan_mode_timer);
|
||||
void set_supports_fan_only_cooling(bool supports_fan_only_cooling);
|
||||
void set_supports_fan_with_cooling(bool supports_fan_with_cooling);
|
||||
void set_supports_fan_with_heating(bool supports_fan_with_heating);
|
||||
void set_supports_heat(bool supports_heat);
|
||||
void set_supports_fan_mode_on(bool supports_fan_mode_on);
|
||||
void set_supports_fan_mode_off(bool supports_fan_mode_off);
|
||||
void set_supports_fan_mode_auto(bool supports_fan_mode_auto);
|
||||
void set_supports_fan_mode_low(bool supports_fan_mode_low);
|
||||
void set_supports_fan_mode_medium(bool supports_fan_mode_medium);
|
||||
void set_supports_fan_mode_high(bool supports_fan_mode_high);
|
||||
void set_supports_fan_mode_middle(bool supports_fan_mode_middle);
|
||||
void set_supports_fan_mode_focus(bool supports_fan_mode_focus);
|
||||
void set_supports_fan_mode_diffuse(bool supports_fan_mode_diffuse);
|
||||
void set_supports_fan_mode_quiet(bool supports_fan_mode_quiet);
|
||||
void set_supports_swing_mode_both(bool supports_swing_mode_both);
|
||||
void set_supports_swing_mode_horizontal(bool supports_swing_mode_horizontal);
|
||||
void set_supports_swing_mode_off(bool supports_swing_mode_off);
|
||||
void set_supports_swing_mode_vertical(bool supports_swing_mode_vertical);
|
||||
void set_use_startup_delay(bool use_startup_delay) { this->use_startup_delay_ = use_startup_delay; }
|
||||
void set_supports_auto(bool supports_auto) { this->supports_auto_ = supports_auto; }
|
||||
void set_supports_heat_cool(bool supports_heat_cool) { this->supports_heat_cool_ = supports_heat_cool; }
|
||||
void set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
|
||||
void set_supports_dry(bool supports_dry) { this->supports_dry_ = supports_dry; }
|
||||
void set_supports_fan_only(bool supports_fan_only) { this->supports_fan_only_ = supports_fan_only; }
|
||||
void set_supports_fan_only_action_uses_fan_mode_timer(bool supports_fan_only_action_uses_fan_mode_timer) {
|
||||
this->supports_fan_only_action_uses_fan_mode_timer_ = supports_fan_only_action_uses_fan_mode_timer;
|
||||
}
|
||||
void set_supports_fan_only_cooling(bool supports_fan_only_cooling) {
|
||||
this->supports_fan_only_cooling_ = supports_fan_only_cooling;
|
||||
}
|
||||
void set_supports_fan_with_cooling(bool supports_fan_with_cooling) {
|
||||
this->supports_fan_with_cooling_ = supports_fan_with_cooling;
|
||||
}
|
||||
void set_supports_fan_with_heating(bool supports_fan_with_heating) {
|
||||
this->supports_fan_with_heating_ = supports_fan_with_heating;
|
||||
}
|
||||
void set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
|
||||
void set_supports_fan_mode_on(bool supports_fan_mode_on) { this->supports_fan_mode_on_ = supports_fan_mode_on; }
|
||||
void set_supports_fan_mode_off(bool supports_fan_mode_off) { this->supports_fan_mode_off_ = supports_fan_mode_off; }
|
||||
void set_supports_fan_mode_auto(bool supports_fan_mode_auto) {
|
||||
this->supports_fan_mode_auto_ = supports_fan_mode_auto;
|
||||
}
|
||||
void set_supports_fan_mode_low(bool supports_fan_mode_low) { this->supports_fan_mode_low_ = supports_fan_mode_low; }
|
||||
void set_supports_fan_mode_medium(bool supports_fan_mode_medium) {
|
||||
this->supports_fan_mode_medium_ = supports_fan_mode_medium;
|
||||
}
|
||||
void set_supports_fan_mode_high(bool supports_fan_mode_high) {
|
||||
this->supports_fan_mode_high_ = supports_fan_mode_high;
|
||||
}
|
||||
void set_supports_fan_mode_middle(bool supports_fan_mode_middle) {
|
||||
this->supports_fan_mode_middle_ = supports_fan_mode_middle;
|
||||
}
|
||||
void set_supports_fan_mode_focus(bool supports_fan_mode_focus) {
|
||||
this->supports_fan_mode_focus_ = supports_fan_mode_focus;
|
||||
}
|
||||
void set_supports_fan_mode_diffuse(bool supports_fan_mode_diffuse) {
|
||||
this->supports_fan_mode_diffuse_ = supports_fan_mode_diffuse;
|
||||
}
|
||||
void set_supports_fan_mode_quiet(bool supports_fan_mode_quiet) {
|
||||
this->supports_fan_mode_quiet_ = supports_fan_mode_quiet;
|
||||
}
|
||||
void set_supports_swing_mode_both(bool supports_swing_mode_both) {
|
||||
this->supports_swing_mode_both_ = supports_swing_mode_both;
|
||||
}
|
||||
void set_supports_swing_mode_horizontal(bool supports_swing_mode_horizontal) {
|
||||
this->supports_swing_mode_horizontal_ = supports_swing_mode_horizontal;
|
||||
}
|
||||
void set_supports_swing_mode_off(bool supports_swing_mode_off) {
|
||||
this->supports_swing_mode_off_ = supports_swing_mode_off;
|
||||
}
|
||||
void set_supports_swing_mode_vertical(bool supports_swing_mode_vertical) {
|
||||
this->supports_swing_mode_vertical_ = supports_swing_mode_vertical;
|
||||
}
|
||||
void set_supports_dehumidification(bool supports_dehumidification);
|
||||
void set_supports_humidification(bool supports_humidification);
|
||||
void set_supports_two_points(bool supports_two_points);
|
||||
void set_supports_two_points(bool supports_two_points) { this->supports_two_points_ = supports_two_points; }
|
||||
|
||||
void set_preset_config(std::initializer_list<PresetEntry> presets);
|
||||
void set_preset_config(std::initializer_list<PresetEntry> presets) { this->preset_config_ = presets; }
|
||||
void set_custom_preset_config(std::initializer_list<CustomPresetEntry> presets);
|
||||
|
||||
Trigger<> *get_cool_action_trigger();
|
||||
@@ -181,10 +213,10 @@ class ThermostatClimate final : public climate::Climate, public Component {
|
||||
Trigger<> *get_humidity_control_humidify_action_trigger();
|
||||
Trigger<> *get_humidity_control_off_action_trigger();
|
||||
/// Get current hysteresis values
|
||||
float cool_deadband();
|
||||
float cool_overrun();
|
||||
float heat_deadband();
|
||||
float heat_overrun();
|
||||
float cool_deadband() { return this->cooling_deadband_; }
|
||||
float cool_overrun() { return this->cooling_overrun_; }
|
||||
float heat_deadband() { return this->heating_deadband_; }
|
||||
float heat_overrun() { return this->heating_overrun_; }
|
||||
/// Call triggers based on updated climate states (modes/actions)
|
||||
void refresh();
|
||||
/// Returns true if a climate action/fan mode transition is being delayed
|
||||
@@ -193,7 +225,7 @@ class ThermostatClimate final : public climate::Climate, public Component {
|
||||
/// Returns the climate action that is being delayed (check climate_action_change_delayed(), first!)
|
||||
climate::ClimateAction delayed_climate_action();
|
||||
/// Returns the fan mode that is locked in (check fan_mode_change_delayed(), first!)
|
||||
climate::ClimateFanMode locked_fan_mode();
|
||||
climate::ClimateFanMode locked_fan_mode() { return this->prev_fan_mode_; }
|
||||
/// Set point and hysteresis validation
|
||||
bool hysteresis_valid(); // returns true if valid
|
||||
bool humidity_hysteresis_valid(); // returns true if valid
|
||||
|
||||
@@ -120,10 +120,6 @@ ValveCall &ValveCall::set_stop(bool stop) {
|
||||
this->stop_ = stop;
|
||||
return *this;
|
||||
}
|
||||
bool ValveCall::get_stop() const { return this->stop_; }
|
||||
|
||||
ValveCall Valve::make_call() { return {this}; }
|
||||
|
||||
void Valve::publish_state(bool save) {
|
||||
this->position = clamp(this->position, 0.0f, 1.0f);
|
||||
|
||||
@@ -162,9 +158,6 @@ optional<ValveRestoreState> Valve::restore_state_() {
|
||||
return recovered;
|
||||
}
|
||||
|
||||
bool Valve::is_fully_open() const { return this->position == VALVE_OPEN; }
|
||||
bool Valve::is_fully_closed() const { return this->position == VALVE_CLOSED; }
|
||||
|
||||
ValveCall ValveRestoreState::to_call(Valve *valve) {
|
||||
auto call = valve->make_call();
|
||||
call.set_position(this->position);
|
||||
|
||||
@@ -47,7 +47,7 @@ class ValveCall {
|
||||
void perform();
|
||||
|
||||
const optional<float> &get_position() const;
|
||||
bool get_stop() const;
|
||||
bool get_stop() const { return this->stop_; }
|
||||
const optional<bool> &get_toggle() const;
|
||||
|
||||
protected:
|
||||
@@ -114,7 +114,7 @@ class Valve : public EntityBase {
|
||||
float position;
|
||||
|
||||
/// Construct a new valve call used to control the valve.
|
||||
ValveCall make_call();
|
||||
ValveCall make_call() { return {this}; }
|
||||
|
||||
template<typename F> void add_on_state_callback(F &&f) { this->state_callback_.add(std::forward<F>(f)); }
|
||||
|
||||
@@ -130,9 +130,9 @@ class Valve : public EntityBase {
|
||||
virtual ValveTraits get_traits() = 0;
|
||||
|
||||
/// Helper method to check if the valve is fully open. Equivalent to comparing .position against 1.0
|
||||
bool is_fully_open() const;
|
||||
bool is_fully_open() const { return this->position == VALVE_OPEN; }
|
||||
/// Helper method to check if the valve is fully closed. Equivalent to comparing .position against 0.0
|
||||
bool is_fully_closed() const;
|
||||
bool is_fully_closed() const { return this->position == VALVE_CLOSED; }
|
||||
|
||||
protected:
|
||||
friend ValveCall;
|
||||
|
||||
@@ -48,8 +48,6 @@ void VersionTextSensor::setup() {
|
||||
version_str[sizeof(version_str) - 1] = '\0';
|
||||
this->publish_state(version_str);
|
||||
}
|
||||
void VersionTextSensor::set_hide_hash(bool hide_hash) { this->hide_hash_ = hide_hash; }
|
||||
void VersionTextSensor::set_hide_timestamp(bool hide_timestamp) { this->hide_timestamp_ = hide_timestamp; }
|
||||
void VersionTextSensor::dump_config() { LOG_TEXT_SENSOR("", "Version Text Sensor", this); }
|
||||
|
||||
} // namespace esphome::version
|
||||
|
||||
@@ -7,8 +7,8 @@ namespace esphome::version {
|
||||
|
||||
class VersionTextSensor final : public text_sensor::TextSensor, public Component {
|
||||
public:
|
||||
void set_hide_hash(bool hide_hash);
|
||||
void set_hide_timestamp(bool hide_timestamp);
|
||||
void set_hide_hash(bool hide_hash) { this->hide_hash_ = hide_hash; }
|
||||
void set_hide_timestamp(bool hide_timestamp) { this->hide_timestamp_ = hide_timestamp; }
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
|
||||
|
||||
@@ -233,18 +233,6 @@ WaterHeaterTraits WaterHeater::get_traits() {
|
||||
return traits;
|
||||
}
|
||||
|
||||
#ifdef USE_WATER_HEATER_VISUAL_OVERRIDES
|
||||
void WaterHeater::set_visual_min_temperature_override(float min_temperature_override) {
|
||||
this->visual_min_temperature_override_ = min_temperature_override;
|
||||
}
|
||||
void WaterHeater::set_visual_max_temperature_override(float max_temperature_override) {
|
||||
this->visual_max_temperature_override_ = max_temperature_override;
|
||||
}
|
||||
void WaterHeater::set_visual_target_temperature_step_override(float visual_target_temperature_step_override) {
|
||||
this->visual_target_temperature_step_override_ = visual_target_temperature_step_override;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Water heater mode strings indexed by WaterHeaterMode enum (0-6): OFF, ECO, ELECTRIC, PERFORMANCE, HIGH_DEMAND,
|
||||
// HEAT_PUMP, GAS
|
||||
PROGMEM_STRING_TABLE(WaterHeaterModeStrings, "OFF", "ECO", "ELECTRIC", "PERFORMANCE", "HIGH_DEMAND", "HEAT_PUMP", "GAS",
|
||||
|
||||
@@ -217,9 +217,15 @@ class WaterHeater : public EntityBase {
|
||||
virtual WaterHeaterCallInternal make_call() = 0;
|
||||
|
||||
#ifdef USE_WATER_HEATER_VISUAL_OVERRIDES
|
||||
void set_visual_min_temperature_override(float min_temperature_override);
|
||||
void set_visual_max_temperature_override(float max_temperature_override);
|
||||
void set_visual_target_temperature_step_override(float visual_target_temperature_step_override);
|
||||
void set_visual_min_temperature_override(float min_temperature_override) {
|
||||
this->visual_min_temperature_override_ = min_temperature_override;
|
||||
}
|
||||
void set_visual_max_temperature_override(float max_temperature_override) {
|
||||
this->visual_max_temperature_override_ = max_temperature_override;
|
||||
}
|
||||
void set_visual_target_temperature_step_override(float visual_target_temperature_step_override) {
|
||||
this->visual_target_temperature_step_override_ = visual_target_temperature_step_override;
|
||||
}
|
||||
#endif
|
||||
virtual void control(const WaterHeaterCall &call) = 0;
|
||||
|
||||
|
||||
@@ -178,25 +178,6 @@ time_t Wireguard::get_latest_handshake() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
void Wireguard::set_keepalive(const uint16_t seconds) { this->keepalive_ = seconds; }
|
||||
void Wireguard::set_reboot_timeout(const uint32_t seconds) { this->reboot_timeout_ = seconds; }
|
||||
void Wireguard::set_srctime(time::RealTimeClock *srctime) { this->srctime_ = srctime; }
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
void Wireguard::set_status_sensor(binary_sensor::BinarySensor *sensor) { this->status_sensor_ = sensor; }
|
||||
void Wireguard::set_enabled_sensor(binary_sensor::BinarySensor *sensor) { this->enabled_sensor_ = sensor; }
|
||||
#endif
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
void Wireguard::set_handshake_sensor(sensor::Sensor *sensor) { this->handshake_sensor_ = sensor; }
|
||||
#endif
|
||||
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
void Wireguard::set_address_sensor(text_sensor::TextSensor *sensor) { this->address_sensor_ = sensor; }
|
||||
#endif
|
||||
|
||||
void Wireguard::disable_auto_proceed() { this->proceed_allowed_ = false; }
|
||||
|
||||
void Wireguard::enable() {
|
||||
this->enabled_ = true;
|
||||
ESP_LOGI(TAG, "Enabled");
|
||||
@@ -218,8 +199,6 @@ void Wireguard::publish_enabled_state() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Wireguard::is_enabled() { return this->enabled_; }
|
||||
|
||||
void Wireguard::start_connection_() {
|
||||
if (!this->enabled_) {
|
||||
ESP_LOGV(TAG, "Disabled, cannot start connection");
|
||||
|
||||
@@ -63,25 +63,25 @@ class Wireguard final : public PollingComponent {
|
||||
/// Prevent accidental use of std::string which would dangle
|
||||
void set_allowed_ips(std::initializer_list<std::tuple<std::string, std::string>> ips) = delete;
|
||||
|
||||
void set_keepalive(uint16_t seconds);
|
||||
void set_reboot_timeout(uint32_t seconds);
|
||||
void set_srctime(time::RealTimeClock *srctime);
|
||||
void set_keepalive(const uint16_t seconds) { this->keepalive_ = seconds; }
|
||||
void set_reboot_timeout(const uint32_t seconds) { this->reboot_timeout_ = seconds; }
|
||||
void set_srctime(time::RealTimeClock *srctime) { this->srctime_ = srctime; }
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
void set_status_sensor(binary_sensor::BinarySensor *sensor);
|
||||
void set_enabled_sensor(binary_sensor::BinarySensor *sensor);
|
||||
void set_status_sensor(binary_sensor::BinarySensor *sensor) { this->status_sensor_ = sensor; }
|
||||
void set_enabled_sensor(binary_sensor::BinarySensor *sensor) { this->enabled_sensor_ = sensor; }
|
||||
#endif
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
void set_handshake_sensor(sensor::Sensor *sensor);
|
||||
void set_handshake_sensor(sensor::Sensor *sensor) { this->handshake_sensor_ = sensor; }
|
||||
#endif
|
||||
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
void set_address_sensor(text_sensor::TextSensor *sensor);
|
||||
void set_address_sensor(text_sensor::TextSensor *sensor) { this->address_sensor_ = sensor; }
|
||||
#endif
|
||||
|
||||
/// Block the setup step until peer is connected.
|
||||
void disable_auto_proceed();
|
||||
void disable_auto_proceed() { this->proceed_allowed_ = false; }
|
||||
|
||||
/// Enable the WireGuard component.
|
||||
void enable();
|
||||
@@ -93,7 +93,7 @@ class Wireguard final : public PollingComponent {
|
||||
void publish_enabled_state();
|
||||
|
||||
/// Return if the WireGuard component is or is not enabled.
|
||||
bool is_enabled();
|
||||
bool is_enabled() { return this->enabled_; }
|
||||
|
||||
bool is_peer_up() const;
|
||||
time_t get_latest_handshake() const;
|
||||
|
||||
@@ -114,8 +114,6 @@ std::string ESPTime::strftime(const char *format) {
|
||||
return std::string(buf, len);
|
||||
}
|
||||
|
||||
std::string ESPTime::strftime(const std::string &format) { return this->strftime(format.c_str()); }
|
||||
|
||||
// Helper to parse exactly N digits, returns false if not enough digits
|
||||
static bool parse_digits(const char *&p, const char *end, int count, uint16_t &value) {
|
||||
value = 0;
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ struct ESPTime {
|
||||
* @warning This method can return "ERROR" when the underlying strftime() call fails or when the
|
||||
* output exceeds STRFTIME_BUFFER_SIZE bytes.
|
||||
*/
|
||||
std::string strftime(const std::string &format);
|
||||
std::string strftime(const std::string &format) { return this->strftime(format.c_str()); }
|
||||
|
||||
/// @copydoc strftime(const std::string &format)
|
||||
std::string strftime(const char *format);
|
||||
|
||||
@@ -460,8 +460,14 @@ def perform_ota(
|
||||
(upload_size >> 8) & 0xFF,
|
||||
(upload_size >> 0) & 0xFF,
|
||||
]
|
||||
# The device erases flash between receiving the size and acking the
|
||||
# prepare, so this window shows the erase cost (near zero when the
|
||||
# device erases lazily during the upload)
|
||||
prepare_start = time.perf_counter()
|
||||
send_check(sock, upload_size_encoded, "binary size")
|
||||
receive_exactly(sock, 1, "update prepare result", RESPONSE_UPDATE_PREPARE_OK)
|
||||
prepare_duration = time.perf_counter() - prepare_start
|
||||
_LOGGER.info("Preparing for upload took %.2f seconds", prepare_duration)
|
||||
|
||||
upload_md5 = hashlib.md5(upload_contents).hexdigest()
|
||||
_LOGGER.debug("MD5 of upload is %s", upload_md5)
|
||||
@@ -528,11 +534,23 @@ def perform_ota(
|
||||
# reboots on its own; the exact commit point is not observable from
|
||||
# here, so treat everything past the data phase as non-retryable. A
|
||||
# re-upload could flash a device that already updated successfully.
|
||||
commit_start = time.perf_counter()
|
||||
try:
|
||||
receive_exactly(sock, 1, "update receive result", RESPONSE_RECEIVE_OK)
|
||||
receive_exactly(sock, 1, "update end result", RESPONSE_UPDATE_END_OK)
|
||||
except OTANetworkError as err:
|
||||
raise _committed_error(err) from err
|
||||
commit_duration = time.perf_counter() - commit_start
|
||||
|
||||
# Sum of the named windows so the breakdown is self consistent; connect,
|
||||
# handshake, auth, and the one MD5 round trip are not included
|
||||
_LOGGER.info(
|
||||
"Update took %.2f seconds (prepare %.2f, upload %.2f, commit %.2f)",
|
||||
prepare_duration + duration + commit_duration,
|
||||
prepare_duration,
|
||||
duration,
|
||||
commit_duration,
|
||||
)
|
||||
|
||||
try:
|
||||
send_check(sock, RESPONSE_OK, "end acknowledgement")
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
esphome:
|
||||
name: bk-family-gate-7238
|
||||
|
||||
bk72xx:
|
||||
board: generic-bk7238
|
||||
|
||||
bk72xx_ble:
|
||||
@@ -16,6 +16,7 @@ from esphome.core import EsphomeError
|
||||
("test_bk7231t.yaml", "BK7231T.*BLE 4.2"),
|
||||
("test_bk7252.yaml", "BK7251.*BLE 4.2"),
|
||||
("test_bk7231q.yaml", "BK7231Q.*no BLE"),
|
||||
("test_bk7238.yaml", "BK7238.*bootloader"),
|
||||
],
|
||||
)
|
||||
def test_unsupported_family_rejected(
|
||||
|
||||
@@ -6,6 +6,8 @@ from collections.abc import Generator
|
||||
import gzip
|
||||
import hashlib
|
||||
import io
|
||||
import itertools
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import socket
|
||||
import struct
|
||||
@@ -53,8 +55,9 @@ def mock_sleep() -> Generator[Mock]:
|
||||
@pytest.fixture
|
||||
def mock_time(mock_sleep: Mock) -> Generator[None]:
|
||||
"""Mock time-related functions for consistent testing."""
|
||||
# Provide enough values for multiple calls (tests may call perform_ota multiple times)
|
||||
with patch("time.perf_counter", side_effect=[0, 1, 0, 1, 0, 1]):
|
||||
# Monotonically increasing, never exhausted regardless of how many timing
|
||||
# windows perform_ota measures or how many times a test calls it
|
||||
with patch("time.perf_counter", side_effect=itertools.count()):
|
||||
yield
|
||||
|
||||
|
||||
@@ -372,7 +375,9 @@ def test_perform_ota_successful_md5_auth(
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_time")
|
||||
def test_perform_ota_no_auth(mock_socket: Mock, mock_file: io.BytesIO) -> None:
|
||||
def test_perform_ota_no_auth(
|
||||
mock_socket: Mock, mock_file: io.BytesIO, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test OTA without authentication."""
|
||||
recv_responses = [
|
||||
bytes([espota2.RESPONSE_OK]), # First byte of version response
|
||||
@@ -387,7 +392,14 @@ def test_perform_ota_no_auth(mock_socket: Mock, mock_file: io.BytesIO) -> None:
|
||||
|
||||
mock_socket.recv.side_effect = recv_responses
|
||||
|
||||
espota2.perform_ota(mock_socket, None, mock_file, "test.bin")
|
||||
# Distinct window lengths pin each duration to its label; exactly the 6
|
||||
# expected perf_counter calls, so an unaccounted timing window raises
|
||||
timings = [0.0, 2.0, 10.0, 15.0, 20.0, 27.0]
|
||||
with (
|
||||
patch("time.perf_counter", side_effect=timings),
|
||||
caplog.at_level(logging.INFO),
|
||||
):
|
||||
espota2.perform_ota(mock_socket, None, mock_file, "test.bin")
|
||||
|
||||
# Should not send any auth-related data
|
||||
auth_calls = [
|
||||
@@ -397,6 +409,14 @@ def test_perform_ota_no_auth(mock_socket: Mock, mock_file: io.BytesIO) -> None:
|
||||
]
|
||||
assert len(auth_calls) == 0
|
||||
|
||||
# The timing summary is the observable output of the upload; exact strings
|
||||
# pin each duration to its label
|
||||
assert "Preparing for upload took 2.00 seconds" in caplog.text
|
||||
assert (
|
||||
"Update took 14.00 seconds (prepare 2.00, upload 5.00, commit 7.00)"
|
||||
in caplog.text
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_time")
|
||||
def test_perform_ota_with_compression(mock_socket: Mock) -> None:
|
||||
|
||||
Reference in New Issue
Block a user