diff --git a/esphome/__main__.py b/esphome/__main__.py index 0d5c331276..13a26309df 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -476,7 +476,7 @@ def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int from esphome.components.api.client import run_logs return run_logs(config, addresses_to_use) - if get_port_type(port) == "MQTT" and "mqtt" in config: + if get_port_type(port) in ("NETWORK", "MQTT") and "mqtt" in config: from esphome import mqtt return mqtt.show_logs( diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index 5a62604269..97c5393502 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -15,11 +15,11 @@ namespace safe_mode { static const char *const TAG = "safe_mode"; void SafeModeComponent::dump_config() { - ESP_LOGCONFIG(TAG, "Safe Mode:"); ESP_LOGCONFIG(TAG, - " Boot considered successful after %" PRIu32 " seconds\n" - " Invoke after %u boot attempts\n" - " Remain for %" PRIu32 " seconds", + "Safe Mode:\n" + " Successful after: %" PRIu32 "s\n" + " Attempts: %u\n" + " Duration: %" PRIu32 "s", this->safe_mode_boot_is_good_after_ / 1000, // because milliseconds this->safe_mode_num_attempts_, this->safe_mode_enable_time_ / 1000); // because milliseconds @@ -27,7 +27,7 @@ void SafeModeComponent::dump_config() { if (this->safe_mode_rtc_value_ > 1 && this->safe_mode_rtc_value_ != SafeModeComponent::ENTER_SAFE_MODE_MAGIC) { auto remaining_restarts = this->safe_mode_num_attempts_ - this->safe_mode_rtc_value_; if (remaining_restarts) { - ESP_LOGW(TAG, "Last reset occurred too quickly; will be invoked in %" PRIu32 " restarts", remaining_restarts); + ESP_LOGW(TAG, "Last reset too quick; invoke in %" PRIu32 " restarts", remaining_restarts); } else { ESP_LOGW(TAG, "SAFE MODE IS ACTIVE"); } @@ -72,43 +72,45 @@ bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t en this->safe_mode_boot_is_good_after_ = boot_is_good_after; this->safe_mode_num_attempts_ = num_attempts; this->rtc_ = global_preferences->make_preference(233825507UL, false); - this->safe_mode_rtc_value_ = this->read_rtc_(); - bool is_manual_safe_mode = this->safe_mode_rtc_value_ == SafeModeComponent::ENTER_SAFE_MODE_MAGIC; + uint32_t rtc_val = this->read_rtc_(); + this->safe_mode_rtc_value_ = rtc_val; - if (is_manual_safe_mode) { - ESP_LOGI(TAG, "Safe mode invoked manually"); + bool is_manual = rtc_val == SafeModeComponent::ENTER_SAFE_MODE_MAGIC; + + if (is_manual) { + ESP_LOGI(TAG, "Manual mode"); } else { - ESP_LOGCONFIG(TAG, "There have been %" PRIu32 " suspected unsuccessful boot attempts", this->safe_mode_rtc_value_); + ESP_LOGCONFIG(TAG, "Unsuccessful boot attempts: %" PRIu32, rtc_val); } - if (this->safe_mode_rtc_value_ >= num_attempts || is_manual_safe_mode) { - this->clean_rtc(); - - if (!is_manual_safe_mode) { - ESP_LOGE(TAG, "Boot loop detected. Proceeding"); - } - - this->status_set_error(); - this->set_timeout(enable_time, []() { - ESP_LOGW(TAG, "Safe mode enable time has elapsed -- restarting"); - App.reboot(); - }); - - // Delay here to allow power to stabilize before Wi-Fi/Ethernet is initialised - delay(300); // NOLINT - App.setup(); - - ESP_LOGW(TAG, "SAFE MODE IS ACTIVE"); - - this->safe_mode_callback_.call(); - - return true; - } else { + if (rtc_val < num_attempts && !is_manual) { // increment counter - this->write_rtc_(this->safe_mode_rtc_value_ + 1); + this->write_rtc_(rtc_val + 1); return false; } + + this->clean_rtc(); + + if (!is_manual) { + ESP_LOGE(TAG, "Boot loop detected"); + } + + this->status_set_error(); + this->set_timeout(enable_time, []() { + ESP_LOGW(TAG, "Timeout, restarting"); + App.reboot(); + }); + + // Delay here to allow power to stabilize before Wi-Fi/Ethernet is initialised + delay(300); // NOLINT + App.setup(); + + ESP_LOGW(TAG, "SAFE MODE IS ACTIVE"); + + this->safe_mode_callback_.call(); + + return true; } void SafeModeComponent::write_rtc_(uint32_t val) { diff --git a/esphome/components/senseair/senseair.cpp b/esphome/components/senseair/senseair.cpp index e58ee157f7..84520d407d 100644 --- a/esphome/components/senseair/senseair.cpp +++ b/esphome/components/senseair/senseair.cpp @@ -53,10 +53,14 @@ void SenseAirComponent::update() { this->status_clear_warning(); const uint8_t length = response[2]; - const uint16_t status = (uint16_t(response[3]) << 8) | response[4]; - const int16_t ppm = int16_t((response[length + 1] << 8) | response[length + 2]); + const uint16_t status = encode_uint16(response[3], response[4]); + const uint16_t ppm = encode_uint16(response[length + 1], response[length + 2]); - ESP_LOGD(TAG, "SenseAir Received CO₂=%dppm Status=0x%02X", ppm, status); + ESP_LOGD(TAG, "SenseAir Received CO₂=%uppm Status=0x%02X", ppm, status); + if (ppm == 0 && (status & SenseAirStatus::OUT_OF_RANGE_ERROR) != 0) { + ESP_LOGD(TAG, "Discarding 0 ppm reading with out-of-range status."); + return; + } if (this->co2_sensor_ != nullptr) this->co2_sensor_->publish_state(ppm); } diff --git a/esphome/components/senseair/senseair.h b/esphome/components/senseair/senseair.h index 9f939d5b07..5b66860f1a 100644 --- a/esphome/components/senseair/senseair.h +++ b/esphome/components/senseair/senseair.h @@ -8,6 +8,17 @@ namespace esphome { namespace senseair { +enum SenseAirStatus : uint8_t { + FATAL_ERROR = 1 << 0, + OFFSET_ERROR = 1 << 1, + ALGORITHM_ERROR = 1 << 2, + OUTPUT_ERROR = 1 << 3, + SELF_DIAGNOSTIC_ERROR = 1 << 4, + OUT_OF_RANGE_ERROR = 1 << 5, + MEMORY_ERROR = 1 << 6, + RESERVED = 1 << 7 +}; + class SenseAirComponent : public PollingComponent, public uart::UARTDevice { public: void set_co2_sensor(sensor::Sensor *co2_sensor) { co2_sensor_ = co2_sensor; }