mirror of
https://github.com/esphome/esphome.git
synced 2026-10-26 16:02:13 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fcb52d286c | ||
|
|
cb943c4492 |
No files matched your search
@@ -1,7 +1,7 @@
|
||||
#include "bme680_bsec.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
#include <string>
|
||||
|
||||
namespace esphome::bme680_bsec {
|
||||
#ifdef USE_BSEC
|
||||
@@ -9,7 +9,7 @@ ESPHOME_LOG_TAG(TAG, "bme680_bsec.sensor");
|
||||
|
||||
static constexpr uint32_t READ_TIMEOUT_ID = 0;
|
||||
|
||||
PROGMEM_STRING_TABLE(IaqAccuracyStrings, "Stabilizing", "Uncertain", "Calibrating", "Calibrated");
|
||||
static const std::string IAQ_ACCURACY_STATES[4] = {"Stabilizing", "Uncertain", "Calibrating", "Calibrated"};
|
||||
|
||||
std::vector<BME680BSECComponent *>
|
||||
BME680BSECComponent::instances; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
@@ -386,11 +386,10 @@ void BME680BSECComponent::publish_(const bsec_output_t *outputs, uint8_t num_out
|
||||
switch (outputs[i].sensor_id) {
|
||||
case BSEC_OUTPUT_IAQ:
|
||||
case BSEC_OUTPUT_STATIC_IAQ: {
|
||||
uint8_t accuracy = std::min<uint8_t>(outputs[i].accuracy, IaqAccuracyStrings::LAST_INDEX);
|
||||
uint8_t accuracy = std::min<uint8_t>(outputs[i].accuracy, std::size(IAQ_ACCURACY_STATES) - 1);
|
||||
this->queue_push_([this, signal]() { this->publish_sensor_(this->iaq_sensor_, signal); });
|
||||
this->queue_push_([this, accuracy]() {
|
||||
this->publish_sensor_(this->iaq_accuracy_text_sensor_,
|
||||
IaqAccuracyStrings::get_progmem_str(accuracy, IaqAccuracyStrings::LAST_INDEX));
|
||||
this->publish_sensor_(this->iaq_accuracy_text_sensor_, IAQ_ACCURACY_STATES[accuracy]);
|
||||
});
|
||||
this->queue_push_([this, accuracy]() { this->publish_sensor_(this->iaq_accuracy_sensor_, accuracy, true); });
|
||||
|
||||
@@ -436,9 +435,8 @@ void BME680BSECComponent::publish_sensor_(sensor::Sensor *sensor, float value, b
|
||||
sensor->publish_state(value);
|
||||
}
|
||||
|
||||
void BME680BSECComponent::publish_sensor_(text_sensor::TextSensor *sensor, ProgmemStr value) {
|
||||
if (!sensor ||
|
||||
(sensor->has_state() && ESPHOME_strcmp_P(sensor->state.c_str(), reinterpret_cast<ESPHOME_PGM_P>(value)) == 0)) {
|
||||
void BME680BSECComponent::publish_sensor_(text_sensor::TextSensor *sensor, const std::string &value) {
|
||||
if (!sensor || (sensor->has_state() && sensor->state == value)) {
|
||||
return;
|
||||
}
|
||||
sensor->publish_state(value);
|
||||
|
||||
@@ -77,7 +77,7 @@ class BME680BSECComponent final : public Component, public i2c::I2CDevice {
|
||||
int64_t get_time_ns_();
|
||||
|
||||
void publish_sensor_(sensor::Sensor *sensor, float value, bool change_only = false);
|
||||
void publish_sensor_(text_sensor::TextSensor *sensor, ProgmemStr value);
|
||||
void publish_sensor_(text_sensor::TextSensor *sensor, const std::string &value);
|
||||
|
||||
void snapshot_state_(); // Fetch the current BSEC library state and save it in the bsec_state_data_ member (volatile
|
||||
// memory)
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "cc1101pa.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
@@ -15,9 +14,6 @@ namespace esphome::cc1101 {
|
||||
ESPHOME_LOG_TAG(TAG, "cc1101");
|
||||
static constexpr size_t TX_FIFO_SIZE = 64;
|
||||
|
||||
// MDMCFG2 MOD_FORMAT values
|
||||
PROGMEM_STRING_TABLE(ModulationStrings, "2-FSK", "GFSK", "UNUSED", "ASK/OOK", "4-FSK", "UNUSED", "UNUSED", "MSK");
|
||||
|
||||
static void split_float(float value, int mbits, uint8_t &e, uint32_t &m) {
|
||||
int e_tmp;
|
||||
float m_tmp = std::frexp(value, &e_tmp);
|
||||
@@ -242,6 +238,8 @@ void CC1101Component::loop() {
|
||||
}
|
||||
|
||||
void CC1101Component::dump_config() {
|
||||
static const char *const MODULATION_NAMES[] = {"2-FSK", "GFSK", "UNUSED", "ASK/OOK",
|
||||
"4-FSK", "UNUSED", "UNUSED", "MSK"};
|
||||
int32_t freq = static_cast<int32_t>(this->state_.FREQ2 << 16 | this->state_.FREQ1 << 8 | this->state_.FREQ0) *
|
||||
XTAL_FREQUENCY / (1 << 16);
|
||||
float symbol_rate = (((256.0f + this->state_.DRATE_M) * (1 << this->state_.DRATE_E)) / (1 << 28)) * XTAL_FREQUENCY;
|
||||
@@ -255,9 +253,8 @@ void CC1101Component::dump_config() {
|
||||
" Symbol Rate: %.0f baud\n"
|
||||
" Filter Bandwidth: %.1f Hz\n"
|
||||
" Output Power: %.1f dBm",
|
||||
this->chip_id_, freq, this->state_.CHANNR,
|
||||
LOG_STR_ARG(ModulationStrings::get_log_str(this->state_.MOD_FORMAT & 0x07, 0)), symbol_rate, bw,
|
||||
this->output_power_effective_);
|
||||
this->chip_id_, freq, this->state_.CHANNR, MODULATION_NAMES[this->state_.MOD_FORMAT & 0x07],
|
||||
symbol_rate, bw, this->output_power_effective_);
|
||||
LOG_PIN(" CS Pin: ", this->cs_);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,18 +4,21 @@
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
|
||||
namespace esphome::epaper_spi {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "epaper_spi");
|
||||
static constexpr size_t EPAPER_MAX_CMD_LOG_BYTES = 128;
|
||||
|
||||
PROGMEM_STRING_TABLE(EPaperStateStrings, "IDLE", "UPDATE", "RESET", "RESET_END", "SHOULD_WAIT", "INITIALISE",
|
||||
"TRANSFER_DATA", "POWER_ON", "REFRESH_SCREEN", "POWER_OFF", "DEEP_SLEEP", "Unknown");
|
||||
static constexpr const char *const EPAPER_STATE_STRINGS[] = {
|
||||
"IDLE", "UPDATE", "RESET", "RESET_END", "SHOULD_WAIT", "INITIALISE",
|
||||
"TRANSFER_DATA", "POWER_ON", "REFRESH_SCREEN", "POWER_OFF", "DEEP_SLEEP",
|
||||
};
|
||||
|
||||
const LogString *EPaperBase::epaper_state_to_string_() {
|
||||
return EPaperStateStrings::get_log_str(static_cast<uint8_t>(this->state_), EPaperStateStrings::LAST_INDEX);
|
||||
const char *EPaperBase::epaper_state_to_string_() {
|
||||
if (auto idx = static_cast<unsigned>(this->state_); idx < std::size(EPAPER_STATE_STRINGS))
|
||||
return EPAPER_STATE_STRINGS[idx];
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
void EPaperBase::setup() {
|
||||
@@ -156,7 +159,7 @@ void EPaperBase::update_effective_transform_() {
|
||||
|
||||
void EPaperBase::update() {
|
||||
if (this->state_ != EPaperState::IDLE) {
|
||||
ESP_LOGE(TAG, "Display already in state %s", LOG_STR_ARG(epaper_state_to_string_()));
|
||||
ESP_LOGE(TAG, "Display already in state %s", epaper_state_to_string_());
|
||||
return;
|
||||
}
|
||||
this->set_state_(EPaperState::UPDATE);
|
||||
@@ -209,7 +212,7 @@ void EPaperBase::loop() {
|
||||
this->high_frequency_loop_.stop();
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||
if (now - this->waiting_for_idle_last_print_ >= 1000) {
|
||||
ESP_LOGV(TAG, "Waiting for idle in state %s", LOG_STR_ARG(this->epaper_state_to_string_()));
|
||||
ESP_LOGV(TAG, "Waiting for idle in state %s", this->epaper_state_to_string_());
|
||||
this->waiting_for_idle_last_print_ = millis();
|
||||
}
|
||||
#endif
|
||||
@@ -224,7 +227,7 @@ void EPaperBase::loop() {
|
||||
// The busy pin never cleared: give up on this update so later ones are not refused, and make the next one full
|
||||
void EPaperBase::abandon_update_() {
|
||||
ESP_LOGE(TAG, "Display stayed busy for %u s in state %s; check the busy pin", (unsigned) this->busy_timeout_seconds_,
|
||||
LOG_STR_ARG(this->epaper_state_to_string_()));
|
||||
this->epaper_state_to_string_());
|
||||
this->status_set_warning(LOG_STR("Busy pin timeout"));
|
||||
if (this->state_ == EPaperState::TRANSFER_DATA)
|
||||
this->abort_transfer();
|
||||
@@ -244,10 +247,10 @@ void EPaperBase::abandon_update_() {
|
||||
* Should a subclassed class need to override this, the method will need to be made virtual.
|
||||
*/
|
||||
void EPaperBase::process_state_() {
|
||||
ESP_LOGV(TAG, "Process state entered in state %s", LOG_STR_ARG(epaper_state_to_string_()));
|
||||
ESP_LOGV(TAG, "Process state entered in state %s", epaper_state_to_string_());
|
||||
switch (this->state_) {
|
||||
default:
|
||||
ESP_LOGE(TAG, "Display is in unhandled state %s", LOG_STR_ARG(epaper_state_to_string_()));
|
||||
ESP_LOGE(TAG, "Display is in unhandled state %s", epaper_state_to_string_());
|
||||
this->set_state_(EPaperState::IDLE);
|
||||
break;
|
||||
case EPaperState::IDLE:
|
||||
@@ -339,7 +342,7 @@ void EPaperBase::process_state_() {
|
||||
}
|
||||
|
||||
void EPaperBase::set_state_(EPaperState state, uint16_t delay) {
|
||||
ESP_LOGV(TAG, "Exit state %s", LOG_STR_ARG(this->epaper_state_to_string_()));
|
||||
ESP_LOGV(TAG, "Exit state %s", this->epaper_state_to_string_());
|
||||
this->state_ = state;
|
||||
// allow subclasses to nominate delays
|
||||
if (delay == 0)
|
||||
@@ -347,7 +350,7 @@ void EPaperBase::set_state_(EPaperState state, uint16_t delay) {
|
||||
this->next_delay_ = 0;
|
||||
this->delay_until_ = millis() + delay;
|
||||
this->wait_for_idle_(state > EPaperState::SHOULD_WAIT);
|
||||
ESP_LOGV(TAG, "Enter state %s, delay %u, wait_for_idle=%s", LOG_STR_ARG(this->epaper_state_to_string_()), delay,
|
||||
ESP_LOGV(TAG, "Enter state %s, delay %u, wait_for_idle=%s", this->epaper_state_to_string_(), delay,
|
||||
TRUEFALSE(this->waiting_for_idle_));
|
||||
// Each step of an update otherwise waits for the next loop iteration; loop() slows down again for long waits
|
||||
if (state == EPaperState::IDLE) {
|
||||
|
||||
@@ -125,7 +125,7 @@ class EPaperBase : public Display,
|
||||
bool is_using_partial_update_() const { return this->full_update_every_ > 1; }
|
||||
void process_state_();
|
||||
|
||||
const LogString *epaper_state_to_string_();
|
||||
const char *epaper_state_to_string_();
|
||||
bool is_idle_() const;
|
||||
void setup_pins_() const;
|
||||
virtual bool reset();
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#include "ezo.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
|
||||
namespace esphome::ezo {
|
||||
|
||||
PROGMEM_STRING_TABLE(EzoCommandTypeStrings, "EZO_READ", "EZO_LED", "EZO_DEVICE_INFORMATION", "EZO_SLOPE",
|
||||
"EZO_CALIBRATION", "EZO_SLEEP", "EZO_I2C", "EZO_T", "EZO_CUSTOM");
|
||||
static const char *const EZO_COMMAND_TYPE_STRINGS[] = {"EZO_READ", "EZO_LED", "EZO_DEVICE_INFORMATION",
|
||||
"EZO_SLOPE", "EZO_CALIBRATION", "EZO_SLEEP",
|
||||
"EZO_I2C", "EZO_T", "EZO_CUSTOM"};
|
||||
|
||||
PROGMEM_STRING_TABLE(EzoCalibrationTypeStrings, "LOW", "MID", "HIGH");
|
||||
static const char *const EZO_CALIBRATION_TYPE_STRINGS[] = {"LOW", "MID", "HIGH"};
|
||||
|
||||
void EZOSensor::dump_config() {
|
||||
LOG_SENSOR("", "EZO", this);
|
||||
@@ -103,8 +103,7 @@ void EZOSensor::loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Received buffer \"%s\" for command type %s", &buf[1],
|
||||
LOG_STR_ARG(EzoCommandTypeStrings::get_log_str(to_run->command_type, EzoCommandTypeStrings::LAST_INDEX)));
|
||||
ESP_LOGV(TAG, "Received buffer \"%s\" for command type %s", &buf[1], EZO_COMMAND_TYPE_STRINGS[to_run->command_type]);
|
||||
|
||||
if (buf[0] == 1) {
|
||||
std::string payload = reinterpret_cast<char *>(&buf[1]);
|
||||
@@ -169,9 +168,7 @@ void EZOSensor::add_command_(const char *command, EzoCommandType command_type, u
|
||||
void EZOSensor::set_calibration_point_(EzoCalibrationType type, float value) {
|
||||
// max 21: "Cal,"(4) + type(4) + ","(1) + float(11) + null; use 24 for safety
|
||||
char payload[24];
|
||||
ESPHOME_snprintf_P(payload, sizeof(payload), ESPHOME_PSTR("Cal,%s,%0.2f"),
|
||||
LOG_STR_ARG(EzoCalibrationTypeStrings::get_log_str(type, EzoCalibrationTypeStrings::LAST_INDEX)),
|
||||
value);
|
||||
snprintf(payload, sizeof(payload), "Cal,%s,%0.2f", EZO_CALIBRATION_TYPE_STRINGS[type], value);
|
||||
this->add_command_(payload, EzoCommandType::EZO_CALIBRATION, 900);
|
||||
}
|
||||
|
||||
@@ -179,7 +176,7 @@ void EZOSensor::set_address(uint8_t address) {
|
||||
if (address > 0 && address < 128) {
|
||||
// max 8: "I2C,"(4) + uint8(3) + null
|
||||
char payload[8];
|
||||
ESPHOME_snprintf_P(payload, sizeof(payload), ESPHOME_PSTR("I2C,%u"), address);
|
||||
snprintf(payload, sizeof(payload), "I2C,%u", address);
|
||||
this->new_address_ = address;
|
||||
this->add_command_(payload, EzoCommandType::EZO_I2C);
|
||||
} else {
|
||||
@@ -200,7 +197,7 @@ void EZOSensor::get_t() { this->add_command_("T,?", EzoCommandType::EZO_T); }
|
||||
void EZOSensor::set_t(float value) {
|
||||
// max 14 bytes: "T,"(2) + float with "%0.2f" (up to 11 chars) + null(1); use 16 for alignment
|
||||
char payload[16];
|
||||
ESPHOME_snprintf_P(payload, sizeof(payload), ESPHOME_PSTR("T,%0.2f"), value);
|
||||
snprintf(payload, sizeof(payload), "T,%0.2f", value);
|
||||
this->add_command_(payload, EzoCommandType::EZO_T);
|
||||
}
|
||||
|
||||
@@ -223,7 +220,7 @@ void EZOSensor::set_calibration_point_high(float value) {
|
||||
void EZOSensor::set_calibration_generic(float value) {
|
||||
// exact 16 bytes: "Cal," (4) + float with "%0.2f" (up to 11 chars, e.g. "-9999999.99") + null (1) = 16
|
||||
char payload[16];
|
||||
ESPHOME_snprintf_P(payload, sizeof(payload), ESPHOME_PSTR("Cal,%0.2f"), value);
|
||||
snprintf(payload, sizeof(payload), "Cal,%0.2f", value);
|
||||
this->add_command_(payload, EzoCommandType::EZO_CALIBRATION, 900);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "esphome/components/wifi/wifi_component.h"
|
||||
#endif
|
||||
#include "haier_base.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
|
||||
using namespace esphome::climate;
|
||||
using namespace esphome::uart;
|
||||
@@ -20,16 +19,28 @@ constexpr size_t PROTOCOL_INITIALIZATION_INTERVAL = 10000;
|
||||
constexpr size_t DEFAULT_MESSAGES_INTERVAL_MS = 2000;
|
||||
constexpr size_t CONTROL_MESSAGES_INTERVAL_MS = 400;
|
||||
|
||||
PROGMEM_STRING_TABLE(ProtocolPhaseStrings, "SENDING_INIT_1", "SENDING_INIT_2", "SENDING_FIRST_STATUS_REQUEST",
|
||||
"SENDING_FIRST_ALARM_STATUS_REQUEST", "IDLE", "SENDING_STATUS_REQUEST",
|
||||
"SENDING_UPDATE_SIGNAL_REQUEST", "SENDING_SIGNAL_LEVEL", "SENDING_CONTROL",
|
||||
"SENDING_ACTION_COMMAND", "SENDING_ALARM_STATUS_REQUEST", "UNKNOWN");
|
||||
|
||||
const LogString *HaierClimateBase::phase_to_string_(ProtocolPhases phase) {
|
||||
static_assert(ProtocolPhaseStrings::COUNT == ((int) ProtocolPhases::NUM_PROTOCOL_PHASES) + 1,
|
||||
"ProtocolPhaseStrings must match the enum ProtocolPhases, with UNKNOWN last");
|
||||
// UNKNOWN (-1) wraps past the table and reads as the last entry, "UNKNOWN"
|
||||
return ProtocolPhaseStrings::get_log_str(static_cast<uint8_t>(phase), ProtocolPhaseStrings::LAST_INDEX);
|
||||
const char *HaierClimateBase::phase_to_string_(ProtocolPhases phase) {
|
||||
static const char *phase_names[] = {
|
||||
"SENDING_INIT_1",
|
||||
"SENDING_INIT_2",
|
||||
"SENDING_FIRST_STATUS_REQUEST",
|
||||
"SENDING_FIRST_ALARM_STATUS_REQUEST",
|
||||
"IDLE",
|
||||
"SENDING_STATUS_REQUEST",
|
||||
"SENDING_UPDATE_SIGNAL_REQUEST",
|
||||
"SENDING_SIGNAL_LEVEL",
|
||||
"SENDING_CONTROL",
|
||||
"SENDING_ACTION_COMMAND",
|
||||
"SENDING_ALARM_STATUS_REQUEST",
|
||||
"UNKNOWN" // Should be the last!
|
||||
};
|
||||
static_assert(
|
||||
(sizeof(phase_names) / sizeof(char *)) == (((int) ProtocolPhases::NUM_PROTOCOL_PHASES) + 1),
|
||||
"Wrong phase_names array size. Please, make sure that this array is aligned with the enum ProtocolPhases");
|
||||
int phase_index = (int) phase;
|
||||
if ((phase_index > (int) ProtocolPhases::NUM_PROTOCOL_PHASES) || (phase_index < 0))
|
||||
phase_index = (int) ProtocolPhases::NUM_PROTOCOL_PHASES;
|
||||
return phase_names[phase_index];
|
||||
}
|
||||
|
||||
bool check_timeout(std::chrono::steady_clock::time_point now, std::chrono::steady_clock::time_point tpoint,
|
||||
@@ -60,8 +71,7 @@ HaierClimateBase::~HaierClimateBase() {}
|
||||
|
||||
void HaierClimateBase::set_phase(ProtocolPhases phase) {
|
||||
if (this->protocol_phase_ != phase) {
|
||||
ESP_LOGV(TAG, "Phase transition: %s => %s", LOG_STR_ARG(phase_to_string_(this->protocol_phase_)),
|
||||
LOG_STR_ARG(phase_to_string_(phase)));
|
||||
ESP_LOGV(TAG, "Phase transition: %s => %s", phase_to_string_(this->protocol_phase_), phase_to_string_(phase));
|
||||
this->protocol_phase_ = phase;
|
||||
}
|
||||
}
|
||||
@@ -215,7 +225,7 @@ haier_protocol::HandlerError HaierClimateBase::report_network_status_answer_hand
|
||||
|
||||
haier_protocol::HandlerError HaierClimateBase::timeout_default_handler_(haier_protocol::FrameType request_type) {
|
||||
ESP_LOGW(TAG, "Answer timeout for command %02X, phase %s", (uint8_t) request_type,
|
||||
LOG_STR_ARG(phase_to_string_(this->protocol_phase_)));
|
||||
phase_to_string_(this->protocol_phase_));
|
||||
if (this->protocol_phase_ > ProtocolPhases::IDLE) {
|
||||
this->set_phase(ProtocolPhases::IDLE);
|
||||
} else {
|
||||
|
||||
@@ -95,7 +95,7 @@ class HaierClimateBase : public esphome::Component,
|
||||
SENDING_ALARM_STATUS_REQUEST,
|
||||
NUM_PROTOCOL_PHASES
|
||||
};
|
||||
const LogString *phase_to_string_(ProtocolPhases phase);
|
||||
const char *phase_to_string_(ProtocolPhases phase);
|
||||
virtual void set_handlers() = 0;
|
||||
virtual void process_phase(std::chrono::steady_clock::time_point now) = 0;
|
||||
virtual haier_protocol::HaierMessage get_control_message() = 0; // NOLINT(readability-identifier-naming)
|
||||
|
||||
@@ -564,7 +564,7 @@ void HonClimate::process_phase(std::chrono::steady_clock::time_point now) {
|
||||
default:
|
||||
// Shouldn't get here
|
||||
ESP_LOGE(TAG, "Wrong protocol handler state: %s (%d), resetting communication",
|
||||
LOG_STR_ARG(phase_to_string_(this->protocol_phase_)), (int) this->protocol_phase_);
|
||||
phase_to_string_(this->protocol_phase_), (int) this->protocol_phase_);
|
||||
this->set_phase(ProtocolPhases::SENDING_INIT_1);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ haier_protocol::HandlerError Smartair2Climate::messages_timeout_handler_with_cyc
|
||||
if (this->protocol_phase_ >= ProtocolPhases::IDLE)
|
||||
return HaierClimateBase::timeout_default_handler_(message_type);
|
||||
ESP_LOGI(TAG, "Answer timeout for command %02X, phase %s", (uint8_t) message_type,
|
||||
LOG_STR_ARG(phase_to_string_(this->protocol_phase_)));
|
||||
phase_to_string_(this->protocol_phase_));
|
||||
ProtocolPhases new_phase = (ProtocolPhases) ((int) this->protocol_phase_ + 1);
|
||||
if (new_phase >= ProtocolPhases::SENDING_FIRST_ALARM_STATUS_REQUEST)
|
||||
new_phase = ProtocolPhases::SENDING_INIT_1;
|
||||
@@ -217,7 +217,7 @@ void Smartair2Climate::process_phase(std::chrono::steady_clock::time_point now)
|
||||
default:
|
||||
// Shouldn't get here
|
||||
ESP_LOGE(TAG, "Wrong protocol handler state: %s (%d), resetting communication",
|
||||
LOG_STR_ARG(phase_to_string_(this->protocol_phase_)), (int) this->protocol_phase_);
|
||||
phase_to_string_(this->protocol_phase_), (int) this->protocol_phase_);
|
||||
this->set_phase(ProtocolPhases::SENDING_INIT_1);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2,20 +2,11 @@
|
||||
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
|
||||
namespace esphome::kamstrup_kmp {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "kamstrup_kmp");
|
||||
|
||||
// KMP units indexed by unit code; the empty first entry doubles as the fallback for unknown codes
|
||||
PROGMEM_STRING_TABLE(KmpUnits, "", "Wh", "kWh", "MWh", "GWh", "J", "kJ", "MJ", "GJ", "Cal", "kCal", "Mcal", "Gcal",
|
||||
"varh", "kvarh", "Mvarh", "Gvarh", "VAh", "kVAh", "MVAh", "GVAh", "kW", "kW", "MW", "GW", "kvar",
|
||||
"kvar", "Mvar", "Gvar", "VA", "kVA", "MVA", "GVA", "V", "A", "kV", "kA", "C", "K", "l", "m3",
|
||||
"l/h", "m3/h", "m3xC", "ton", "ton/h", "h", "hh:mm:ss", "yy:mm:dd", "yyyy:mm:dd", "mm:dd", "",
|
||||
"bar", "RTC", "ASCII", "m3 x 10", "ton x 10", "GJ x 10", "minutes", "Bitfield", "s", "ms", "days",
|
||||
"RTC-Q", "Datetime");
|
||||
|
||||
void KamstrupKMPComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "kamstrup_kmp:");
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
@@ -246,6 +237,8 @@ void KamstrupKMPComponent::parse_command_message_(uint16_t command, const uint8_
|
||||
}
|
||||
|
||||
void KamstrupKMPComponent::set_sensor_value_(uint16_t command, float value, uint8_t unit_idx) {
|
||||
const char *unit = unit_idx < sizeof(UNITS) / sizeof(UNITS[0]) ? UNITS[unit_idx] : "";
|
||||
|
||||
// Standard sensors
|
||||
if (command == CMD_HEAT_ENERGY && this->heat_energy_sensor_ != nullptr) {
|
||||
this->heat_energy_sensor_->publish_state(value);
|
||||
@@ -270,8 +263,7 @@ void KamstrupKMPComponent::set_sensor_value_(uint16_t command, float value, uint
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Received value for command 0x%04X: %.3f [%s]", command, value,
|
||||
LOG_STR_ARG(KmpUnits::get_log_str(unit_idx, 0)));
|
||||
ESP_LOGD(TAG, "Received value for command 0x%04X: %.3f [%s]", command, value, unit);
|
||||
}
|
||||
|
||||
} // namespace esphome::kamstrup_kmp
|
||||
@@ -63,6 +63,16 @@ static const uint16_t CMD_TEMP_DIFF = 0x0059;
|
||||
static const uint16_t CMD_FLOW = 0x004A;
|
||||
static const uint16_t CMD_VOLUME = 0x0044;
|
||||
|
||||
// KMP units
|
||||
static const char *const UNITS[] = {
|
||||
"", "Wh", "kWh", "MWh", "GWh", "J", "kJ", "MJ", "GJ", "Cal",
|
||||
"kCal", "Mcal", "Gcal", "varh", "kvarh", "Mvarh", "Gvarh", "VAh", "kVAh", "MVAh",
|
||||
"GVAh", "kW", "kW", "MW", "GW", "kvar", "kvar", "Mvar", "Gvar", "VA",
|
||||
"kVA", "MVA", "GVA", "V", "A", "kV", "kA", "C", "K", "l",
|
||||
"m3", "l/h", "m3/h", "m3xC", "ton", "ton/h", "h", "hh:mm:ss", "yy:mm:dd", "yyyy:mm:dd",
|
||||
"mm:dd", "", "bar", "RTC", "ASCII", "m3 x 10", "ton x 10", "GJ x 10", "minutes", "Bitfield",
|
||||
"s", "ms", "days", "RTC-Q", "Datetime"};
|
||||
|
||||
class KamstrupKMPComponent final : public PollingComponent, public uart::UARTDevice {
|
||||
public:
|
||||
void set_heat_energy_sensor(sensor::Sensor *sensor) { this->heat_energy_sensor_ = sensor; }
|
||||
|
||||
@@ -45,6 +45,7 @@ from .const import (
|
||||
FAMILY_COMPONENT,
|
||||
FAMILY_FRIENDLY,
|
||||
FAMILY_RTL8710B,
|
||||
FAMILY_RTL8720C,
|
||||
KEY_BOARD,
|
||||
KEY_COMPONENT,
|
||||
KEY_COMPONENT_DATA,
|
||||
@@ -59,6 +60,8 @@ from .const import (
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
# Fault handlers the crash handler wraps (BK7238, BK7231N)
|
||||
BK_TRAP_HANDLERS = ("bk_trap_udef", "bk_trap_pabt", "bk_trap_dabt")
|
||||
# Families with a crash handler; the RTL8720C installs it at run time (no wraps).
|
||||
CRASH_HANDLER_FAMILIES = (FAMILY_BK7231N, FAMILY_BK7238, FAMILY_RTL8720C)
|
||||
|
||||
CODEOWNERS = ["@kuba2k2"]
|
||||
AUTO_LOAD = ["preferences"]
|
||||
@@ -554,10 +557,11 @@ async def component_to_code(config):
|
||||
# RAM-executable output section and prints a post-link placement summary.
|
||||
if FAMILY_COMPONENT[config[CONF_FAMILY]] != COMPONENT_BK72XX:
|
||||
cg.add_platformio_option("extra_scripts", ["pre:patch_linker.py"])
|
||||
if config[CONF_FAMILY] in (FAMILY_BK7231N, FAMILY_BK7238):
|
||||
# Crash handler (crash_handler.cpp, patch_noinit.py.script)
|
||||
if config[CONF_FAMILY] in CRASH_HANDLER_FAMILIES:
|
||||
# Crash handler (crash_handler.cpp)
|
||||
cg.add_define("USE_LIBRETINY_CRASH_HANDLER")
|
||||
cg.add_define("USE_CRASH_HANDLER")
|
||||
if config[CONF_FAMILY] in (FAMILY_BK7231N, FAMILY_BK7238):
|
||||
for trap in BK_TRAP_HANDLERS:
|
||||
cg.add_build_flag(f"-Wl,--wrap={trap}")
|
||||
cg.add_platformio_option("extra_scripts", ["pre:patch_noinit.py"])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifdef USE_BK72XX
|
||||
#ifdef USE_LIBRETINY
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_LIBRETINY_CRASH_HANDLER
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef USE_BK72XX
|
||||
extern "C" {
|
||||
#include <arm_mcu_pub.h> // MCU_REG_BACKUP_SP_*
|
||||
#include <intc.h> // struct arm_registers
|
||||
@@ -39,6 +40,19 @@ extern char _itcmcode_ram_begin[];
|
||||
extern char _itcmcode_ram_end[];
|
||||
}
|
||||
// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming)
|
||||
#endif // USE_BK72XX
|
||||
|
||||
#ifdef USE_RTL87XX
|
||||
// NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming)
|
||||
extern "C" {
|
||||
// Bounds of the code in flash (XIP) and in RAM (linker symbols, rtl8710c_ram.ld).
|
||||
extern char __xip_code_text_start__[];
|
||||
extern char __xip_code_text_end__[];
|
||||
extern char __ram_entry_text_start__[];
|
||||
extern char __ram_code_text_end__[];
|
||||
}
|
||||
// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming)
|
||||
#endif // USE_RTL87XX
|
||||
|
||||
namespace esphome::libretiny {
|
||||
|
||||
@@ -47,50 +61,39 @@ ESPHOME_LOG_TAG(TAG, "libretiny.crash");
|
||||
// 0xDEAD sentinel, then the record layout version.
|
||||
static constexpr uint32_t CRASH_MAGIC_V1 = 0xDEAD0001;
|
||||
|
||||
// BK72xx: the ARM9 exception taken.
|
||||
static constexpr uint32_t CRASH_REASON_UNDEFINED = 1;
|
||||
static constexpr uint32_t CRASH_REASON_PREFETCH_ABORT = 2;
|
||||
static constexpr uint32_t CRASH_REASON_DATA_ABORT = 3;
|
||||
PROGMEM_STRING_TABLE(CrashReasonStrings, "Unknown", "Undefined instruction", "Prefetch abort", "Data abort");
|
||||
|
||||
// With Wi-Fi up the boot-time watchdog no longer fires: any interrupts-off spin hangs until power is
|
||||
// cycled (BK7238 and BK7231N; cause not in the open SDK). Re-armed here, long enough for the SDK's
|
||||
// register dump when sdk_silent is off.
|
||||
static constexpr uint32_t CRASH_REBOOT_WDT_MS = 500;
|
||||
// RTL87xx: the Cortex-M exception number (3 to 7) plus this offset.
|
||||
static constexpr uint32_t CRASH_REASON_CORTEX_M_OFFSET = 1;
|
||||
PROGMEM_STRING_TABLE(CrashReasonStrings, "Unknown", "Undefined instruction", "Prefetch abort", "Data abort",
|
||||
"Hard fault", "MemManage fault", "Bus fault", "Usage fault", "Secure fault");
|
||||
|
||||
static constexpr size_t MAX_BACKTRACE = 8;
|
||||
// Words scanned above sp for return addresses.
|
||||
static constexpr size_t STACK_SCAN_WORDS = 64;
|
||||
|
||||
// SRAM: 192 KB on the BK7231N, 256 KB on the BK7238.
|
||||
static constexpr uint32_t SRAM_START = 0x00400000;
|
||||
#ifdef USE_LIBRETINY_VARIANT_BK7231N
|
||||
static constexpr uint32_t SRAM_END = 0x00430000;
|
||||
#else
|
||||
static constexpr uint32_t SRAM_END = 0x00440000;
|
||||
#endif
|
||||
|
||||
static constexpr uint32_t CPSR_MODE_MASK = 0x1F;
|
||||
static constexpr uint32_t CPSR_MODE_USR = 0x10;
|
||||
static constexpr uint32_t CPSR_MODE_FIQ = 0x11;
|
||||
static constexpr uint32_t CPSR_MODE_IRQ = 0x12;
|
||||
static constexpr uint32_t CPSR_MODE_SVC = 0x13;
|
||||
static constexpr uint32_t CPSR_MODE_ABT = 0x17;
|
||||
static constexpr uint32_t CPSR_MODE_UND = 0x1B;
|
||||
static constexpr uint32_t CPSR_MODE_SYS = 0x1F;
|
||||
static constexpr uint32_t CPSR_THUMB = 1u << 5;
|
||||
|
||||
struct CrashRecord {
|
||||
uint32_t magic;
|
||||
uint32_t reason;
|
||||
uint32_t pc;
|
||||
uint32_t lr;
|
||||
uint32_t sp;
|
||||
uint32_t fault_status; // Cortex-M CFSR, 0 on BK72xx
|
||||
uint32_t fault_address; // Cortex-M BFAR or MMFAR when valid, else 0
|
||||
uint32_t backtrace[MAX_BACKTRACE];
|
||||
};
|
||||
|
||||
#ifdef USE_BK72XX
|
||||
// Kept in ITCM, see patch_noinit.py.script.
|
||||
#define CRASH_RECORD_SECTION ".noinit"
|
||||
#else
|
||||
// rtl8710c_ram.ld keeps .ram.bss.noinit* out of the startup zeroing.
|
||||
#define CRASH_RECORD_SECTION ".ram.bss.noinit.esphome_crash"
|
||||
#endif
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
__attribute__((section(".noinit"))) static CrashRecord s_record;
|
||||
__attribute__((section(CRASH_RECORD_SECTION))) static CrashRecord s_record;
|
||||
|
||||
static bool s_record_read = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static bool s_record_valid = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
@@ -112,6 +115,9 @@ void crash_handler_log() {
|
||||
|
||||
ESP_LOGE(TAG, "*** CRASH DETECTED ON PREVIOUS BOOT ***");
|
||||
ESP_LOGE(TAG, " Reason: %s", LOG_STR_ARG(CrashReasonStrings::get_log_str(s_record.reason, 0)));
|
||||
if (s_record.fault_status != 0) {
|
||||
ESP_LOGE(TAG, " CFSR: 0x%08" PRIX32 " Address: 0x%08" PRIX32, s_record.fault_status, s_record.fault_address);
|
||||
}
|
||||
ESP_LOGE(TAG, " PC: 0x%08" PRIX32 " (fault location)", s_record.pc);
|
||||
ESP_LOGE(TAG, " LR: 0x%08" PRIX32 " (return address)", s_record.lr);
|
||||
ESP_LOGE(TAG, " SP: 0x%08" PRIX32, s_record.sp);
|
||||
@@ -129,15 +135,61 @@ void crash_handler_log() {
|
||||
ESP_LOGE(TAG, "%s", hint);
|
||||
}
|
||||
|
||||
// --- Crash time: exception mode, interrupts masked, a few dozen bytes of stack: no printing, no
|
||||
// large locals.
|
||||
// --- Crash time: exception mode, a few dozen bytes of stack: no printing, no large locals.
|
||||
|
||||
static inline bool is_code_addr(uint32_t val) {
|
||||
uint32_t addr = val & ~1u; // clear the Thumb bit of a return address
|
||||
#ifdef USE_BK72XX
|
||||
return (addr >= (uint32_t) _vector_start && addr < (uint32_t) _data_flash_begin) ||
|
||||
(addr >= (uint32_t) _itcmcode_ram_begin && addr < (uint32_t) _itcmcode_ram_end);
|
||||
#else
|
||||
return (addr >= (uint32_t) __xip_code_text_start__ && addr < (uint32_t) __xip_code_text_end__) ||
|
||||
(addr >= (uint32_t) __ram_entry_text_start__ && addr < (uint32_t) __ram_code_text_end__);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Return addresses above sp give the backtrace; then the magic marks the record complete.
|
||||
static void finish_record(uint32_t sp, uint32_t sram_start, uint32_t sram_end) {
|
||||
uint32_t count = 0;
|
||||
if (sp >= sram_start && sp < sram_end && (sp & 3) == 0) {
|
||||
auto *scan = (const uint32_t *) sp; // NOLINT(performance-no-int-to-ptr)
|
||||
auto *end = (const uint32_t *) sram_end; // NOLINT(performance-no-int-to-ptr)
|
||||
for (size_t i = 0; i < STACK_SCAN_WORDS && scan < end && count < MAX_BACKTRACE; i++, scan++) {
|
||||
uint32_t val = *scan;
|
||||
if (is_code_addr(val) && val != s_record.lr && (val & ~1u) != s_record.pc)
|
||||
s_record.backtrace[count++] = val;
|
||||
}
|
||||
}
|
||||
if (count < MAX_BACKTRACE)
|
||||
s_record.backtrace[count] = 0; // terminator, the reader stops at the first 0
|
||||
s_record.magic = CRASH_MAGIC_V1;
|
||||
}
|
||||
|
||||
#ifdef USE_BK72XX
|
||||
|
||||
// With Wi-Fi up the boot-time watchdog no longer fires: any interrupts-off spin hangs until power is
|
||||
// cycled (BK7238 and BK7231N; cause not in the open SDK). Re-armed here, long enough for the SDK's
|
||||
// register dump when sdk_silent is off.
|
||||
static constexpr uint32_t CRASH_REBOOT_WDT_MS = 500;
|
||||
|
||||
// SRAM: 192 KB on the BK7231N, 256 KB on the BK7238.
|
||||
static constexpr uint32_t SRAM_START = 0x00400000;
|
||||
#ifdef USE_LIBRETINY_VARIANT_BK7231N
|
||||
static constexpr uint32_t SRAM_END = 0x00430000;
|
||||
#else
|
||||
static constexpr uint32_t SRAM_END = 0x00440000;
|
||||
#endif
|
||||
|
||||
static constexpr uint32_t CPSR_MODE_MASK = 0x1F;
|
||||
static constexpr uint32_t CPSR_MODE_USR = 0x10;
|
||||
static constexpr uint32_t CPSR_MODE_FIQ = 0x11;
|
||||
static constexpr uint32_t CPSR_MODE_IRQ = 0x12;
|
||||
static constexpr uint32_t CPSR_MODE_SVC = 0x13;
|
||||
static constexpr uint32_t CPSR_MODE_ABT = 0x17;
|
||||
static constexpr uint32_t CPSR_MODE_UND = 0x1B;
|
||||
static constexpr uint32_t CPSR_MODE_SYS = 0x1F;
|
||||
static constexpr uint32_t CPSR_THUMB = 1u << 5;
|
||||
|
||||
// PUSH_ALL_ARM_REG (boot_handlers.S) saves every mode's registers at the arm_mcu_pub.h addresses
|
||||
// before bk_trap_*; lr (r14) follows sp (r13).
|
||||
struct SavedBank {
|
||||
@@ -174,21 +226,9 @@ static void record_crash(arm_registers *regs, uint32_t reason, uint32_t pc_offse
|
||||
s_record.pc = regs->pc - pc_offset;
|
||||
s_record.lr = lr;
|
||||
s_record.sp = sp;
|
||||
|
||||
// Return addresses above sp give the backtrace.
|
||||
uint32_t count = 0;
|
||||
if (sp >= SRAM_START && sp < SRAM_END && (sp & 3) == 0) {
|
||||
auto *scan = (const uint32_t *) sp; // NOLINT(performance-no-int-to-ptr)
|
||||
auto *end = (const uint32_t *) SRAM_END; // NOLINT(performance-no-int-to-ptr)
|
||||
for (size_t i = 0; i < STACK_SCAN_WORDS && scan < end && count < MAX_BACKTRACE; i++, scan++) {
|
||||
uint32_t val = *scan;
|
||||
if (is_code_addr(val) && val != lr && (val & ~1u) != s_record.pc)
|
||||
s_record.backtrace[count++] = val;
|
||||
}
|
||||
}
|
||||
if (count < MAX_BACKTRACE)
|
||||
s_record.backtrace[count] = 0; // terminator, the reader stops at the first 0
|
||||
s_record.magic = CRASH_MAGIC_V1;
|
||||
s_record.fault_status = 0;
|
||||
s_record.fault_address = 0;
|
||||
finish_record(sp, SRAM_START, SRAM_END);
|
||||
|
||||
lt_wdt_enable(CRASH_REBOOT_WDT_MS);
|
||||
}
|
||||
@@ -211,7 +251,105 @@ extern "C" void __wrap_bk_trap_dabt(arm_registers *regs) {
|
||||
}
|
||||
// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming)
|
||||
|
||||
#endif // USE_BK72XX
|
||||
|
||||
#ifdef USE_RTL87XX
|
||||
|
||||
// The SDK points the fault vectors (3 HardFault to 7 SecureFault) of its RAM vector table (VTOR) at a
|
||||
// ROM handler that prints a register dump and then spins. crash_handler_install() puts
|
||||
// esphome_fault_entry() in front of it, as the SDK's own CONFIG_MIIO patch (app_start.c) does.
|
||||
static_assert(LT_HW_WATCHDOG, "the crash reboot relies on the hardware watchdog");
|
||||
// The ROM dump takes about 0.4 s at 115200 baud; without the re-arm the reset waits for the 10 s
|
||||
// watchdog from arch_init().
|
||||
static constexpr uint32_t CRASH_REBOOT_WDT_MS = 1000;
|
||||
static constexpr uint32_t FIRST_FAULT_VECTOR = 3;
|
||||
static constexpr uint32_t FAULT_VECTOR_COUNT = 5;
|
||||
|
||||
// Architectural System Control Block registers (ARMv8-M).
|
||||
static constexpr uintptr_t SCB_VTOR = 0xE000ED08;
|
||||
static constexpr uintptr_t SCB_CFSR = 0xE000ED28;
|
||||
static constexpr uintptr_t SCB_MMFAR = 0xE000ED34;
|
||||
static constexpr uintptr_t SCB_BFAR = 0xE000ED38;
|
||||
static constexpr uint32_t CFSR_MMARVALID = 1u << 7;
|
||||
static constexpr uint32_t CFSR_BFARVALID = 1u << 15;
|
||||
|
||||
// DTCM, where the app's stacks and heap live (rtl8710c_ram.ld).
|
||||
static constexpr uint32_t SRAM_START = 0x10000000;
|
||||
static constexpr uint32_t SRAM_END = 0x1003FA00;
|
||||
|
||||
// Exception frame: r0-r3, r12, lr, pc, xPSR (the RTL8720C has no FPU, so never the extended frame).
|
||||
static constexpr uint32_t FRAME_LR = 5;
|
||||
static constexpr uint32_t FRAME_PC = 6;
|
||||
static constexpr uint32_t FRAME_XPSR = 7;
|
||||
static constexpr uint32_t FRAME_WORDS = 8;
|
||||
static constexpr uint32_t XPSR_STACK_ALIGNED = 1u << 9;
|
||||
|
||||
// The ROM handlers fault_entry() continues into, by vector.
|
||||
static uint32_t s_rom_fault_vectors[FAULT_VECTOR_COUNT]; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
static inline uint32_t read_reg(uintptr_t addr) {
|
||||
return *(const volatile uint32_t *) addr; // NOLINT(performance-no-int-to-ptr)
|
||||
}
|
||||
|
||||
// Returns the ROM handler to continue into. pc, lr and sp stay 0 when the frame is outside DTCM.
|
||||
extern "C" __attribute__((used)) uint32_t esphome_record_fault(const uint32_t *frame, uint32_t vector) {
|
||||
uint32_t cfsr = read_reg(SCB_CFSR);
|
||||
uint32_t address = 0;
|
||||
if (cfsr & CFSR_BFARVALID) {
|
||||
address = read_reg(SCB_BFAR);
|
||||
} else if (cfsr & CFSR_MMARVALID) {
|
||||
address = read_reg(SCB_MMFAR);
|
||||
}
|
||||
s_record.reason = vector + CRASH_REASON_CORTEX_M_OFFSET;
|
||||
s_record.fault_status = cfsr;
|
||||
s_record.fault_address = address;
|
||||
|
||||
auto frame_addr = (uint32_t) frame;
|
||||
uint32_t sp = 0;
|
||||
if (frame_addr >= SRAM_START && frame_addr + FRAME_WORDS * 4 <= SRAM_END && (frame_addr & 3) == 0) {
|
||||
s_record.pc = frame[FRAME_PC];
|
||||
s_record.lr = frame[FRAME_LR];
|
||||
sp = frame_addr + FRAME_WORDS * 4 + ((frame[FRAME_XPSR] & XPSR_STACK_ALIGNED) ? 4 : 0);
|
||||
} else {
|
||||
s_record.pc = 0;
|
||||
s_record.lr = 0;
|
||||
}
|
||||
s_record.sp = sp;
|
||||
finish_record(sp, SRAM_START, SRAM_END);
|
||||
|
||||
lt_wdt_enable(CRASH_REBOOT_WDT_MS);
|
||||
return s_rom_fault_vectors[vector - FIRST_FAULT_VECTOR];
|
||||
}
|
||||
|
||||
// Passes the faulting stack's frame and the vector number to esphome_record_fault, then
|
||||
// branches to the ROM handler with r0-r3 and lr as they were on entry.
|
||||
extern "C" __attribute__((naked, used)) void esphome_fault_entry() {
|
||||
__asm volatile("push {r0-r3, r4, lr} \n"
|
||||
"tst lr, #4 \n"
|
||||
"ite eq \n"
|
||||
"mrseq r0, msp \n"
|
||||
"mrsne r0, psp \n"
|
||||
"it eq \n"
|
||||
"addeq r0, r0, #24 \n" // MSP: skip the six words pushed above
|
||||
"mrs r1, ipsr \n"
|
||||
"ubfx r1, r1, #0, #9 \n"
|
||||
"bl esphome_record_fault \n"
|
||||
"mov r12, r0 \n"
|
||||
"pop {r0-r3, r4, lr} \n"
|
||||
"bx r12 \n");
|
||||
}
|
||||
|
||||
void crash_handler_install() {
|
||||
auto *vectors = (uint32_t *) read_reg(SCB_VTOR); // NOLINT(performance-no-int-to-ptr)
|
||||
for (uint32_t i = 0; i < FAULT_VECTOR_COUNT; i++) {
|
||||
s_rom_fault_vectors[i] = vectors[FIRST_FAULT_VECTOR + i];
|
||||
vectors[FIRST_FAULT_VECTOR + i] = (uint32_t) &esphome_fault_entry;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_RTL87XX
|
||||
|
||||
} // namespace esphome::libretiny
|
||||
|
||||
#endif // USE_LIBRETINY_CRASH_HANDLER
|
||||
#endif // USE_BK72XX
|
||||
#endif // USE_LIBRETINY
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_BK72XX
|
||||
#ifdef USE_LIBRETINY
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
|
||||
@@ -14,7 +14,12 @@ void crash_handler_log();
|
||||
/// Returns true if crash data was found this boot, reading it first if needed.
|
||||
bool crash_handler_has_data();
|
||||
|
||||
#ifdef USE_RTL87XX
|
||||
/// Put the crash recorder in front of the SDK's fault handlers.
|
||||
void crash_handler_install();
|
||||
#endif
|
||||
|
||||
} // namespace esphome::libretiny
|
||||
|
||||
#endif // USE_LIBRETINY_CRASH_HANDLER
|
||||
#endif // USE_BK72XX
|
||||
#endif // USE_LIBRETINY
|
||||
@@ -152,6 +152,7 @@ COMPONENT_CODEOWNERS = {
|
||||
# Extra imports per component; the CLI looks up process_stacktrace on the platform package.
|
||||
COMPONENT_EXTRA_IMPORTS = {
|
||||
"bk72xx": "from esphome.stacktrace import process_crash_handler_line as process_stacktrace # noqa: F401",
|
||||
"rtl87xx": "from esphome.stacktrace import process_crash_handler_line as process_stacktrace # noqa: F401",
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifdef USE_LIBRETINY
|
||||
|
||||
#include "core.h"
|
||||
#include "crash_handler.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "preferences.h"
|
||||
|
||||
@@ -27,6 +28,9 @@ namespace esphome {
|
||||
void arch_init() {
|
||||
libretiny::setup_preferences();
|
||||
lt_wdt_enable(10000L);
|
||||
#if defined(USE_LIBRETINY_CRASH_HANDLER) && defined(USE_RTL87XX)
|
||||
libretiny::crash_handler_install();
|
||||
#endif
|
||||
#ifdef USE_BK72XX
|
||||
// BK72xx SDK creates the main Arduino task at priority 3, which is lower than
|
||||
// all WiFi (4-5), LwIP (4), and TCP/IP (7) tasks. This causes ~100ms loop
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
#include "micronova_text_sensor.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
|
||||
namespace esphome::micronova {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "micronova.text_sensor");
|
||||
|
||||
PROGMEM_STRING_TABLE(StoveStateStrings, "Off", "Start", "Pellets loading", "Ignition", "Working", "Brazier Cleaning",
|
||||
"Final Cleaning", "Standby", "No pellets alarm", "No ignition alarm", "Undefined alarm");
|
||||
|
||||
void MicroNovaTextSensor::dump_config() {
|
||||
LOG_TEXT_SENSOR("", "Micronova text sensor", this);
|
||||
this->dump_base_config();
|
||||
@@ -19,9 +15,7 @@ void MicroNovaTextSensor::process_value_from_stove(int value_from_stove) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Values past the table read as "Undefined alarm"
|
||||
this->publish_state(
|
||||
StoveStateStrings::get_progmem_str(static_cast<uint8_t>(value_from_stove), StoveStateStrings::LAST_INDEX));
|
||||
this->publish_state(STOVE_STATES[value_from_stove]);
|
||||
}
|
||||
|
||||
} // namespace esphome::micronova
|
||||
@@ -5,6 +5,18 @@
|
||||
|
||||
namespace esphome::micronova {
|
||||
|
||||
static const char *const STOVE_STATES[11] = {"Off",
|
||||
"Start",
|
||||
"Pellets loading",
|
||||
"Ignition",
|
||||
"Working",
|
||||
"Brazier Cleaning",
|
||||
"Final Cleaning",
|
||||
"Standby",
|
||||
"No pellets alarm",
|
||||
"No ignition alarm",
|
||||
"Undefined alarm"};
|
||||
|
||||
class MicroNovaTextSensor final : public text_sensor::TextSensor, public MicroNovaListener {
|
||||
public:
|
||||
MicroNovaTextSensor(MicroNova *m) : MicroNovaListener(m) {}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "pulse_counter_sensor.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
|
||||
#ifdef HAS_PCNT
|
||||
#include <driver/gpio.h>
|
||||
@@ -12,7 +11,7 @@ namespace esphome::pulse_counter {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "pulse_counter");
|
||||
|
||||
PROGMEM_STRING_TABLE(EdgeModeStrings, "DISABLE", "INCREMENT", "DECREMENT");
|
||||
const char *const EDGE_MODE_TO_STRING[] = {"DISABLE", "INCREMENT", "DECREMENT"};
|
||||
|
||||
#ifdef HAS_PCNT
|
||||
PulseCounterStorageBase *get_storage(bool hw_pcnt) {
|
||||
@@ -228,9 +227,8 @@ void PulseCounterSensor::dump_config() {
|
||||
" Rising Edge: %s\n"
|
||||
" Falling Edge: %s\n"
|
||||
" Filtering pulses shorter than %" PRIu32 " µs",
|
||||
LOG_STR_ARG(EdgeModeStrings::get_log_str(this->storage_.rising_edge_mode, 0)),
|
||||
LOG_STR_ARG(EdgeModeStrings::get_log_str(this->storage_.falling_edge_mode, 0)),
|
||||
this->storage_.filter_us);
|
||||
EDGE_MODE_TO_STRING[this->storage_.rising_edge_mode],
|
||||
EDGE_MODE_TO_STRING[this->storage_.falling_edge_mode], this->storage_.filter_us);
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ from esphome.components.libretiny.const import (
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.cpp_generator import MockObj
|
||||
from esphome.stacktrace import process_crash_handler_line as process_stacktrace # noqa: F401
|
||||
from esphome.types import ConfigType
|
||||
|
||||
from .boards import RTL87XX_BOARD_PINS, RTL87XX_BOARDS
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
@@ -12,11 +11,6 @@ ESPHOME_LOG_TAG(TAG, "seeed_mr24hpc1");
|
||||
|
||||
static constexpr uint32_t STARTUP_DELAY_MS = 1000;
|
||||
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
PROGMEM_STRING_TABLE(MotionStatusStrings, "None", "Motionless", "Active");
|
||||
PROGMEM_STRING_TABLE(KeepAwayStrings, "None", "Close", "Away");
|
||||
#endif
|
||||
|
||||
// Prints the component's configuration data. dump_config() prints all of the component's configuration
|
||||
// items in an easy-to-read format, including the configuration key-value pairs.
|
||||
void MR24HPC1Component::dump_config() {
|
||||
@@ -440,9 +434,10 @@ void MR24HPC1Component::r24_frame_parse_open_underlying_information_(uint8_t *da
|
||||
}
|
||||
break;
|
||||
case 0x83:
|
||||
// 0 to 3 m in steps of 0.5 m
|
||||
if (this->custom_presence_of_detection_sensor_ != nullptr && data[FRAME_DATA_INDEX] <= 6) {
|
||||
this->custom_presence_of_detection_sensor_->publish_state(data[FRAME_DATA_INDEX] * 0.5f);
|
||||
if (this->custom_presence_of_detection_sensor_ != nullptr &&
|
||||
data[FRAME_DATA_INDEX] < std::size(S_PRESENCE_OF_DETECTION_RANGE_STR)) {
|
||||
this->custom_presence_of_detection_sensor_->publish_state(
|
||||
S_PRESENCE_OF_DETECTION_RANGE_STR[data[FRAME_DATA_INDEX]]);
|
||||
}
|
||||
break;
|
||||
case 0x84:
|
||||
@@ -460,9 +455,8 @@ void MR24HPC1Component::r24_frame_parse_open_underlying_information_(uint8_t *da
|
||||
case 0x06:
|
||||
case 0x86:
|
||||
// none:0x00 close_to:0x01 far_away:0x02
|
||||
if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < KeepAwayStrings::COUNT)) {
|
||||
this->keep_away_text_sensor_->publish_state(
|
||||
KeepAwayStrings::get_progmem_str(data[FRAME_DATA_INDEX], KeepAwayStrings::LAST_INDEX));
|
||||
if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) {
|
||||
this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -635,8 +629,8 @@ void MR24HPC1Component::r24_frame_parse_human_information_(uint8_t *data) {
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
case 0x01:
|
||||
case 0x81:
|
||||
if (this->has_target_binary_sensor_ != nullptr && data[FRAME_DATA_INDEX] <= 1) {
|
||||
this->has_target_binary_sensor_->publish_state(data[FRAME_DATA_INDEX] == 1);
|
||||
if (this->has_target_binary_sensor_ != nullptr && data[FRAME_DATA_INDEX] < std::size(S_SOMEONE_EXISTS_STR)) {
|
||||
this->has_target_binary_sensor_->publish_state(S_SOMEONE_EXISTS_STR[data[FRAME_DATA_INDEX]]);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -651,17 +645,15 @@ void MR24HPC1Component::r24_frame_parse_human_information_(uint8_t *data) {
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
case 0x02:
|
||||
case 0x82:
|
||||
if ((this->motion_status_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < MotionStatusStrings::COUNT)) {
|
||||
this->motion_status_text_sensor_->publish_state(
|
||||
MotionStatusStrings::get_progmem_str(data[FRAME_DATA_INDEX], MotionStatusStrings::LAST_INDEX));
|
||||
if ((this->motion_status_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) {
|
||||
this->motion_status_text_sensor_->publish_state(S_MOTION_STATUS_STR[data[FRAME_DATA_INDEX]]);
|
||||
}
|
||||
break;
|
||||
case 0x0B:
|
||||
case 0x8B:
|
||||
// none:0x00 close_to:0x01 far_away:0x02
|
||||
if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < KeepAwayStrings::COUNT)) {
|
||||
this->keep_away_text_sensor_->publish_state(
|
||||
KeepAwayStrings::get_progmem_str(data[FRAME_DATA_INDEX], KeepAwayStrings::LAST_INDEX));
|
||||
if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) {
|
||||
this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -82,6 +82,16 @@ enum OutputSwitch {
|
||||
OUTPUT_SWTICH_OFF,
|
||||
};
|
||||
|
||||
static const char *const S_SCENE_STR[5] = {"None", "Living Room", "Bedroom", "Washroom", "Area Detection"};
|
||||
static const bool S_SOMEONE_EXISTS_STR[2] = {false, true};
|
||||
static const char *const S_MOTION_STATUS_STR[3] = {"None", "Motionless", "Active"};
|
||||
static const char *const S_KEEP_AWAY_STR[3] = {"None", "Close", "Away"};
|
||||
static const char *const S_UNMANNED_TIME_STR[9] = {"None", "10s", "30s", "1min", "2min",
|
||||
"5min", "10min", "30min", "60min"};
|
||||
static const char *const S_BOUNDARY_STR[10] = {"0.5m", "1.0m", "1.5m", "2.0m", "2.5m",
|
||||
"3.0m", "3.5m", "4.0m", "4.5m", "5.0m"}; // uint: m
|
||||
static const float S_PRESENCE_OF_DETECTION_RANGE_STR[7] = {0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f}; // uint: m
|
||||
|
||||
class MR24HPC1Component final : public Component,
|
||||
public uart::UARTDevice { // The class name must be the name defined by text_sensor.py
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
|
||||
@@ -774,7 +774,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIBRETINY
|
||||
#ifdef USE_BK72XX
|
||||
#if defined(USE_BK72XX) || defined(USE_RTL87XX)
|
||||
#define USE_LIBRETINY_CRASH_HANDLER
|
||||
#endif
|
||||
#define USE_BK72XX_BLE
|
||||
|
||||
@@ -28,6 +28,7 @@ from esphome.const import (
|
||||
PLATFORM_ESP8266,
|
||||
PLATFORM_NRF52,
|
||||
PLATFORM_RP2,
|
||||
PLATFORM_RTL87XX,
|
||||
Platform,
|
||||
)
|
||||
|
||||
@@ -64,6 +65,7 @@ STACKTRACE_GATES: Final[dict[str, str]] = {
|
||||
),
|
||||
PLATFORM_RP2: _CRASH_HANDLER_GATE,
|
||||
PLATFORM_BK72XX: _CRASH_HANDLER_GATE,
|
||||
PLATFORM_RTL87XX: _CRASH_HANDLER_GATE,
|
||||
PLATFORM_NRF52: r"0x[0-9a-fA-F]{3,}\b|Last crash:",
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ def _addr2line(tool: str, elf: Path, addr: str) -> str:
|
||||
def process_crash_handler_line(
|
||||
config: ConfigType, line: str, backtrace_state: bool
|
||||
) -> bool:
|
||||
"""Decode a crash handler report with addr2line; the process_stacktrace hook of rp2 and bk72xx."""
|
||||
"""Decode a crash handler report with addr2line; the process_stacktrace hook of rp2, bk72xx and rtl87xx."""
|
||||
if CRASH_HANDLER_RE.search(line):
|
||||
_LOGGER.error("Crash detected - decoding addresses")
|
||||
return True
|
||||
|
||||
@@ -57,6 +57,7 @@ PLATFORM_BUILD_SECONDS = {
|
||||
"esp32-idf": 55,
|
||||
"esp32-p4-idf": 55,
|
||||
"ln882x-ard": 55,
|
||||
"rtl8720c-ard": 55,
|
||||
"esp32-s3-idf": 60,
|
||||
"bk72xx-ard": 70,
|
||||
"bk7238-ard": 70,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
rtl87xx:
|
||||
board: generic-rtl8710bn-2mb-788k
|
||||
@@ -0,0 +1,5 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
rtl87xx:
|
||||
board: bw15
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Only BK7238 and BK7231N, the BK chips with an ITCM linker region, get the crash handler."""
|
||||
"""The crash handler is built for BK7238, BK7231N (both with an ITCM linker region) and RTL8720C."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -12,12 +12,14 @@ from esphome.core import CORE
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("config", "enabled"),
|
||||
("config", "enabled", "bk_hooks"),
|
||||
[
|
||||
("bk7238.yaml", True),
|
||||
("bk72xx.yaml", True), # BK7231N
|
||||
("bk7231t.yaml", False),
|
||||
("ln882x.yaml", False),
|
||||
("bk7238.yaml", True, True),
|
||||
("bk72xx.yaml", True, True), # BK7231N
|
||||
("bk7231t.yaml", False, False),
|
||||
("rtl8720c.yaml", True, False), # installed at run time
|
||||
("rtl8710b.yaml", False, False),
|
||||
("ln882x.yaml", False, False),
|
||||
],
|
||||
)
|
||||
def test_crash_handler_family_gate(
|
||||
@@ -25,13 +27,14 @@ def test_crash_handler_family_gate(
|
||||
component_config_path: Callable[[str], Path],
|
||||
config: str,
|
||||
enabled: bool,
|
||||
bk_hooks: bool,
|
||||
) -> None:
|
||||
generate_main(component_config_path(config))
|
||||
defines = {define.name for define in CORE.defines}
|
||||
assert ("USE_LIBRETINY_CRASH_HANDLER" in defines) is enabled
|
||||
assert ("USE_CRASH_HANDLER" in defines) is enabled
|
||||
for trap in BK_TRAP_HANDLERS:
|
||||
assert (f"-Wl,--wrap={trap}" in CORE.build_flags) is enabled
|
||||
assert (f"-Wl,--wrap={trap}" in CORE.build_flags) is bk_hooks
|
||||
assert (
|
||||
"pre:patch_noinit.py" in CORE.platformio_options["extra_scripts"]
|
||||
) is enabled
|
||||
) is bk_hooks
|
||||
@@ -0,0 +1,13 @@
|
||||
logger:
|
||||
level: VERBOSE
|
||||
|
||||
esphome:
|
||||
on_boot:
|
||||
- lambda: |-
|
||||
int x = 100;
|
||||
x = clamp(x, 50, 90);
|
||||
assert(x == 90);
|
||||
x = clamp_at_least(x, 95);
|
||||
assert(x == 95);
|
||||
x = clamp_at_most(x, 40);
|
||||
assert(x == 40);
|
||||
@@ -0,0 +1,15 @@
|
||||
esphome:
|
||||
name: componenttestesprtl8720c
|
||||
friendly_name: $component_name
|
||||
|
||||
rtl87xx:
|
||||
board: bw15
|
||||
|
||||
logger:
|
||||
level: VERY_VERBOSE
|
||||
|
||||
packages:
|
||||
component_under_test: !include
|
||||
file: $component_test_file
|
||||
vars:
|
||||
component_test_file: $component_test_file
|
||||
@@ -117,9 +117,9 @@ from esphome.const import (
|
||||
PLATFORM_ESP32,
|
||||
PLATFORM_ESP8266,
|
||||
PLATFORM_HOST,
|
||||
PLATFORM_LN882X,
|
||||
PLATFORM_NRF52,
|
||||
PLATFORM_RP2,
|
||||
PLATFORM_RTL87XX,
|
||||
ErrorFormat,
|
||||
Toolchain,
|
||||
)
|
||||
@@ -6192,7 +6192,7 @@ def test_run_miniterm_no_stacktrace_analyzer(
|
||||
"""Platforms without a stacktrace analyzer log an info and stream anyway."""
|
||||
mock_serial = MockSerial([b"[I][app:100]: Line 1\r\n", MOCK_SERIAL_END])
|
||||
|
||||
CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: PLATFORM_RTL87XX}
|
||||
CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: PLATFORM_LN882X}
|
||||
config = {
|
||||
CONF_LOGGER: {
|
||||
CONF_BAUD_RATE: 115200,
|
||||
|
||||
@@ -15,7 +15,7 @@ from unittest.mock import Mock
|
||||
import pytest
|
||||
|
||||
from esphome import platform_hooks
|
||||
from esphome.const import PLATFORM_ESP32, PLATFORM_RTL87XX, Platform
|
||||
from esphome.const import PLATFORM_ESP32, PLATFORM_LN882X, Platform
|
||||
|
||||
|
||||
def test_no_unregistered_platform_exposes_a_hook() -> None:
|
||||
@@ -165,7 +165,7 @@ def test_get_stacktrace_handler_reports_missing_analyzer(
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
caplog.set_level("INFO", logger="esphome.platform_hooks")
|
||||
assert platform_hooks.get_stacktrace_handler(PLATFORM_RTL87XX) is None
|
||||
assert platform_hooks.get_stacktrace_handler(PLATFORM_LN882X) is None
|
||||
assert "no compatible analyzer" in caplog.text
|
||||
# A capability gap is ordinary; it must not warn.
|
||||
assert not any(r.levelno >= logging.WARNING for r in caplog.records)
|
||||
|
||||
@@ -18,6 +18,7 @@ from esphome.const import (
|
||||
PLATFORM_BK72XX,
|
||||
PLATFORM_ESP32,
|
||||
PLATFORM_ESP8266,
|
||||
PLATFORM_LN882X,
|
||||
PLATFORM_NRF52,
|
||||
PLATFORM_RP2,
|
||||
PLATFORM_RTL87XX,
|
||||
@@ -66,6 +67,10 @@ CRASH_SAMPLES: dict[str, dict[str, list[str]]] = {
|
||||
"state_markers": ["CRASH DETECTED ON PREVIOUS BOOT"],
|
||||
"addresses": ["PC: 0x0001614A (fault location)"],
|
||||
},
|
||||
PLATFORM_RTL87XX: {
|
||||
"state_markers": ["CRASH DETECTED ON PREVIOUS BOOT"],
|
||||
"addresses": ["PC: 0x9B0073A4 (fault location)"],
|
||||
},
|
||||
PLATFORM_NRF52: {
|
||||
"state_markers": ["Last crash:"],
|
||||
"addresses": [
|
||||
@@ -231,6 +236,7 @@ DECODER_PATTERNS: dict[str, list[str]] = {
|
||||
],
|
||||
PLATFORM_RP2: ["CRASH_HANDLER_RE", "CRASH_HANDLER_ADDR_RE"],
|
||||
PLATFORM_BK72XX: ["CRASH_HANDLER_RE", "CRASH_HANDLER_ADDR_RE"],
|
||||
PLATFORM_RTL87XX: ["CRASH_HANDLER_RE", "CRASH_HANDLER_ADDR_RE"],
|
||||
PLATFORM_NRF52: ["STACKTRACE_NRF52_PC_LR_RE"],
|
||||
}
|
||||
|
||||
@@ -548,7 +554,7 @@ def test_processor_registry_miss_disables_at_construction(
|
||||
caplog.set_level("INFO", logger="esphome.platform_hooks")
|
||||
|
||||
with patch.object(stacktrace.platform_hooks, "import_module") as mock_import:
|
||||
processor = stacktrace.LogLineProcessor(CONFIG, PLATFORM_RTL87XX)
|
||||
processor = stacktrace.LogLineProcessor(CONFIG, PLATFORM_LN882X)
|
||||
processor.process_line("PC: 0x40104960")
|
||||
|
||||
mock_import.assert_not_called()
|
||||
|
||||
Reference in new issue
Block a user