mirror of
https://github.com/esphome/esphome.git
synced 2025-09-03 20:02:22 +01:00
Merge branch 'api_reduce_2' into integration
This commit is contained in:
@@ -281,23 +281,34 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess
|
||||
const uint8_t header_padding = conn->helper_->frame_header_padding();
|
||||
const uint8_t footer_size = conn->helper_->frame_footer_size();
|
||||
|
||||
// Calculate total size with padding for buffer allocation
|
||||
size_t total_calculated_size = calculated_size + header_padding + footer_size;
|
||||
// Calculate total size with padding
|
||||
size_t total_size = calculated_size + header_padding + footer_size;
|
||||
|
||||
// Check if it fits
|
||||
if (total_calculated_size > remaining_size) {
|
||||
if (total_size > remaining_size) {
|
||||
return 0; // Doesn't fit
|
||||
}
|
||||
|
||||
// Allocate buffer space - pass payload size, allocation functions add header/footer space
|
||||
ProtoWriteBuffer buffer = is_single ? conn->allocate_single_message_buffer(calculated_size)
|
||||
: conn->allocate_batch_message_buffer(calculated_size);
|
||||
|
||||
// Get buffer size after allocation (which includes header padding)
|
||||
// Get buffer and prepare it inline
|
||||
std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref();
|
||||
size_t size_before_encode = shared_buf.size();
|
||||
|
||||
if (is_single || conn->flags_.batch_first_message) {
|
||||
// Single message or first batch message
|
||||
conn->prepare_first_message_buffer(shared_buf, header_padding, total_size);
|
||||
if (conn->flags_.batch_first_message) {
|
||||
conn->flags_.batch_first_message = false;
|
||||
}
|
||||
} else {
|
||||
// Batch message second or later
|
||||
// Add padding for previous message footer + this message header
|
||||
size_t current_size = shared_buf.size();
|
||||
shared_buf.reserve(current_size + total_size);
|
||||
shared_buf.resize(current_size + footer_size + header_padding);
|
||||
}
|
||||
|
||||
// Encode directly into buffer
|
||||
ProtoWriteBuffer buffer{&shared_buf};
|
||||
size_t size_before_encode = shared_buf.size();
|
||||
msg.encode(buffer);
|
||||
|
||||
// Calculate actual encoded size (not including header that was already added)
|
||||
@@ -1620,14 +1631,6 @@ bool APIConnection::schedule_batch_() {
|
||||
return true;
|
||||
}
|
||||
|
||||
ProtoWriteBuffer APIConnection::allocate_single_message_buffer(uint16_t size) { return this->create_buffer(size); }
|
||||
|
||||
ProtoWriteBuffer APIConnection::allocate_batch_message_buffer(uint16_t size) {
|
||||
ProtoWriteBuffer result = this->prepare_message_buffer(size, this->flags_.batch_first_message);
|
||||
this->flags_.batch_first_message = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
void APIConnection::process_batch_() {
|
||||
// Ensure PacketInfo remains trivially destructible for our placement new approach
|
||||
static_assert(std::is_trivially_destructible<PacketInfo>::value,
|
||||
@@ -1735,7 +1738,7 @@ void APIConnection::process_batch_() {
|
||||
}
|
||||
remaining_size -= payload_size;
|
||||
// Calculate where the next message's header padding will start
|
||||
// Current buffer size + footer space (that prepare_message_buffer will add for this message)
|
||||
// Current buffer size + footer space for this message
|
||||
current_offset = shared_buf.size() + footer_size;
|
||||
}
|
||||
|
||||
|
@@ -252,44 +252,21 @@ class APIConnection : public APIServerConnection {
|
||||
|
||||
// Get header padding size - used for both reserve and insert
|
||||
uint8_t header_padding = this->helper_->frame_header_padding();
|
||||
|
||||
// Get shared buffer from parent server
|
||||
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
|
||||
this->prepare_first_message_buffer(shared_buf, header_padding,
|
||||
reserve_size + header_padding + this->helper_->frame_footer_size());
|
||||
return {&shared_buf};
|
||||
}
|
||||
|
||||
void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t header_padding, size_t total_size) {
|
||||
shared_buf.clear();
|
||||
// Reserve space for header padding + message + footer
|
||||
// - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext)
|
||||
// - Footer: space for MAC (16 bytes for Noise, 0 for Plaintext)
|
||||
shared_buf.reserve(reserve_size + header_padding + this->helper_->frame_footer_size());
|
||||
shared_buf.reserve(total_size);
|
||||
// Resize to add header padding so message encoding starts at the correct position
|
||||
shared_buf.resize(header_padding);
|
||||
return {&shared_buf};
|
||||
}
|
||||
|
||||
// Prepare buffer for next message in batch
|
||||
ProtoWriteBuffer prepare_message_buffer(uint16_t message_size, bool is_first_message) {
|
||||
// Get reference to shared buffer (it maintains state between batch messages)
|
||||
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
|
||||
|
||||
if (is_first_message) {
|
||||
shared_buf.clear();
|
||||
}
|
||||
|
||||
size_t current_size = shared_buf.size();
|
||||
|
||||
// Calculate padding to add:
|
||||
// - First message: just header padding
|
||||
// - Subsequent messages: footer for previous message + header padding for this message
|
||||
size_t padding_to_add = is_first_message
|
||||
? this->helper_->frame_header_padding()
|
||||
: this->helper_->frame_header_padding() + this->helper_->frame_footer_size();
|
||||
|
||||
// Reserve space for padding + message
|
||||
shared_buf.reserve(current_size + padding_to_add + message_size);
|
||||
|
||||
// Resize to add the padding bytes
|
||||
shared_buf.resize(current_size + padding_to_add);
|
||||
|
||||
return {&shared_buf};
|
||||
}
|
||||
|
||||
bool try_to_clear_buffer(bool log_out_of_space);
|
||||
@@ -297,10 +274,6 @@ class APIConnection : public APIServerConnection {
|
||||
|
||||
std::string get_client_combined_info() const { return this->client_info_.get_combined_info(); }
|
||||
|
||||
// Buffer allocator methods for batch processing
|
||||
ProtoWriteBuffer allocate_single_message_buffer(uint16_t size);
|
||||
ProtoWriteBuffer allocate_batch_message_buffer(uint16_t size);
|
||||
|
||||
protected:
|
||||
// Helper function to handle authentication completion
|
||||
void complete_authentication_();
|
||||
|
@@ -208,11 +208,11 @@ void ESPNowComponent::enable_() {
|
||||
esp_wifi_connectionless_module_set_wake_interval(CONFIG_ESPNOW_WAKE_INTERVAL);
|
||||
#endif
|
||||
|
||||
this->state_ = ESPNOW_STATE_ENABLED;
|
||||
|
||||
for (auto peer : this->peers_) {
|
||||
this->add_peer(peer.address);
|
||||
}
|
||||
|
||||
this->state_ = ESPNOW_STATE_ENABLED;
|
||||
}
|
||||
|
||||
void ESPNowComponent::disable() {
|
||||
@@ -407,7 +407,7 @@ esp_err_t ESPNowComponent::add_peer(const uint8_t *peer) {
|
||||
}
|
||||
|
||||
if (memcmp(peer, this->own_address_, ESP_NOW_ETH_ALEN) == 0) {
|
||||
this->mark_failed();
|
||||
this->status_momentary_warning("peer-add-failed");
|
||||
return ESP_ERR_INVALID_MAC;
|
||||
}
|
||||
|
||||
|
@@ -16,6 +16,7 @@ from esphome.components.esp32.const import (
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_ADVANCED,
|
||||
CONF_DISABLED,
|
||||
CONF_FRAMEWORK,
|
||||
CONF_ID,
|
||||
CONF_MODE,
|
||||
@@ -102,6 +103,7 @@ def get_config_schema(config):
|
||||
cv.Optional(CONF_MODE, default=modes[0]): cv.one_of(*modes, lower=True),
|
||||
cv.Optional(CONF_ENABLE_ECC, default=False): cv.boolean,
|
||||
cv.Optional(CONF_SPEED, default=speeds[0]): cv.one_of(*speeds, upper=True),
|
||||
cv.Optional(CONF_DISABLED, default=False): cv.boolean,
|
||||
}
|
||||
)(config)
|
||||
|
||||
@@ -112,6 +114,8 @@ FINAL_VALIDATE_SCHEMA = validate_psram_mode
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
if config[CONF_DISABLED]:
|
||||
return
|
||||
if CORE.using_arduino:
|
||||
cg.add_build_flag("-DBOARD_HAS_PSRAM")
|
||||
if config[CONF_MODE] == TYPE_OCTAL:
|
||||
|
@@ -18,14 +18,6 @@ static const uint8_t QMP6988_TEMPERATURE_MSB_REG = 0xFA; /* Temperature MSB Reg
|
||||
static const uint8_t QMP6988_CALIBRATION_DATA_START = 0xA0; /* QMP6988 compensation coefficients */
|
||||
static const uint8_t QMP6988_CALIBRATION_DATA_LENGTH = 25;
|
||||
|
||||
static const uint8_t SHIFT_RIGHT_4_POSITION = 4;
|
||||
static const uint8_t SHIFT_LEFT_2_POSITION = 2;
|
||||
static const uint8_t SHIFT_LEFT_4_POSITION = 4;
|
||||
static const uint8_t SHIFT_LEFT_5_POSITION = 5;
|
||||
static const uint8_t SHIFT_LEFT_8_POSITION = 8;
|
||||
static const uint8_t SHIFT_LEFT_12_POSITION = 12;
|
||||
static const uint8_t SHIFT_LEFT_16_POSITION = 16;
|
||||
|
||||
/* power mode */
|
||||
static const uint8_t QMP6988_SLEEP_MODE = 0x00;
|
||||
static const uint8_t QMP6988_FORCED_MODE = 0x01;
|
||||
@@ -95,64 +87,45 @@ static const char *iir_filter_to_str(QMP6988IIRFilter filter) {
|
||||
}
|
||||
|
||||
bool QMP6988Component::device_check_() {
|
||||
uint8_t ret = 0;
|
||||
|
||||
ret = this->read_register(QMP6988_CHIP_ID_REG, &(qmp6988_data_.chip_id), 1);
|
||||
if (ret != i2c::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "%s: read chip ID (0xD1) failed", __func__);
|
||||
if (this->read_register(QMP6988_CHIP_ID_REG, &(qmp6988_data_.chip_id), 1) != i2c::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "Read chip ID (0xD1) failed");
|
||||
return false;
|
||||
}
|
||||
ESP_LOGD(TAG, "qmp6988 read chip id = 0x%x", qmp6988_data_.chip_id);
|
||||
ESP_LOGV(TAG, "Read chip ID = 0x%x", qmp6988_data_.chip_id);
|
||||
|
||||
return qmp6988_data_.chip_id == QMP6988_CHIP_ID;
|
||||
}
|
||||
|
||||
bool QMP6988Component::get_calibration_data_() {
|
||||
uint8_t status = 0;
|
||||
// BITFIELDS temp_COE;
|
||||
uint8_t a_data_uint8_tr[QMP6988_CALIBRATION_DATA_LENGTH] = {0};
|
||||
int len;
|
||||
|
||||
for (len = 0; len < QMP6988_CALIBRATION_DATA_LENGTH; len += 1) {
|
||||
status = this->read_register(QMP6988_CALIBRATION_DATA_START + len, &a_data_uint8_tr[len], 1);
|
||||
if (status != i2c::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "qmp6988 read calibration data (0xA0) error!");
|
||||
for (uint8_t len = 0; len < QMP6988_CALIBRATION_DATA_LENGTH; len += 1) {
|
||||
if (this->read_register(QMP6988_CALIBRATION_DATA_START + len, &a_data_uint8_tr[len], 1) != i2c::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "Read calibration data (0xA0) error");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
qmp6988_data_.qmp6988_cali.COE_a0 =
|
||||
(QMP6988_S32_t) (((a_data_uint8_tr[18] << SHIFT_LEFT_12_POSITION) |
|
||||
(a_data_uint8_tr[19] << SHIFT_LEFT_4_POSITION) | (a_data_uint8_tr[24] & 0x0f))
|
||||
<< 12);
|
||||
(int32_t) encode_uint32(a_data_uint8_tr[18], a_data_uint8_tr[19], (a_data_uint8_tr[24] & 0x0f) << 4, 0);
|
||||
qmp6988_data_.qmp6988_cali.COE_a0 = qmp6988_data_.qmp6988_cali.COE_a0 >> 12;
|
||||
|
||||
qmp6988_data_.qmp6988_cali.COE_a1 =
|
||||
(QMP6988_S16_t) (((a_data_uint8_tr[20]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[21]);
|
||||
qmp6988_data_.qmp6988_cali.COE_a2 =
|
||||
(QMP6988_S16_t) (((a_data_uint8_tr[22]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[23]);
|
||||
qmp6988_data_.qmp6988_cali.COE_a1 = (int16_t) encode_uint16(a_data_uint8_tr[20], a_data_uint8_tr[21]);
|
||||
qmp6988_data_.qmp6988_cali.COE_a2 = (int16_t) encode_uint16(a_data_uint8_tr[22], a_data_uint8_tr[23]);
|
||||
|
||||
qmp6988_data_.qmp6988_cali.COE_b00 =
|
||||
(QMP6988_S32_t) (((a_data_uint8_tr[0] << SHIFT_LEFT_12_POSITION) | (a_data_uint8_tr[1] << SHIFT_LEFT_4_POSITION) |
|
||||
((a_data_uint8_tr[24] & 0xf0) >> SHIFT_RIGHT_4_POSITION))
|
||||
<< 12);
|
||||
(int32_t) encode_uint32(a_data_uint8_tr[0], a_data_uint8_tr[1], a_data_uint8_tr[24] & 0xf0, 0);
|
||||
qmp6988_data_.qmp6988_cali.COE_b00 = qmp6988_data_.qmp6988_cali.COE_b00 >> 12;
|
||||
|
||||
qmp6988_data_.qmp6988_cali.COE_bt1 =
|
||||
(QMP6988_S16_t) (((a_data_uint8_tr[2]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[3]);
|
||||
qmp6988_data_.qmp6988_cali.COE_bt2 =
|
||||
(QMP6988_S16_t) (((a_data_uint8_tr[4]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[5]);
|
||||
qmp6988_data_.qmp6988_cali.COE_bp1 =
|
||||
(QMP6988_S16_t) (((a_data_uint8_tr[6]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[7]);
|
||||
qmp6988_data_.qmp6988_cali.COE_b11 =
|
||||
(QMP6988_S16_t) (((a_data_uint8_tr[8]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[9]);
|
||||
qmp6988_data_.qmp6988_cali.COE_bp2 =
|
||||
(QMP6988_S16_t) (((a_data_uint8_tr[10]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[11]);
|
||||
qmp6988_data_.qmp6988_cali.COE_b12 =
|
||||
(QMP6988_S16_t) (((a_data_uint8_tr[12]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[13]);
|
||||
qmp6988_data_.qmp6988_cali.COE_b21 =
|
||||
(QMP6988_S16_t) (((a_data_uint8_tr[14]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[15]);
|
||||
qmp6988_data_.qmp6988_cali.COE_bp3 =
|
||||
(QMP6988_S16_t) (((a_data_uint8_tr[16]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[17]);
|
||||
qmp6988_data_.qmp6988_cali.COE_bt1 = (int16_t) encode_uint16(a_data_uint8_tr[2], a_data_uint8_tr[3]);
|
||||
qmp6988_data_.qmp6988_cali.COE_bt2 = (int16_t) encode_uint16(a_data_uint8_tr[4], a_data_uint8_tr[5]);
|
||||
qmp6988_data_.qmp6988_cali.COE_bp1 = (int16_t) encode_uint16(a_data_uint8_tr[6], a_data_uint8_tr[7]);
|
||||
qmp6988_data_.qmp6988_cali.COE_b11 = (int16_t) encode_uint16(a_data_uint8_tr[8], a_data_uint8_tr[9]);
|
||||
qmp6988_data_.qmp6988_cali.COE_bp2 = (int16_t) encode_uint16(a_data_uint8_tr[10], a_data_uint8_tr[11]);
|
||||
qmp6988_data_.qmp6988_cali.COE_b12 = (int16_t) encode_uint16(a_data_uint8_tr[12], a_data_uint8_tr[13]);
|
||||
qmp6988_data_.qmp6988_cali.COE_b21 = (int16_t) encode_uint16(a_data_uint8_tr[14], a_data_uint8_tr[15]);
|
||||
qmp6988_data_.qmp6988_cali.COE_bp3 = (int16_t) encode_uint16(a_data_uint8_tr[16], a_data_uint8_tr[17]);
|
||||
|
||||
ESP_LOGV(TAG, "<-----------calibration data-------------->\r\n");
|
||||
ESP_LOGV(TAG, "COE_a0[%d] COE_a1[%d] COE_a2[%d] COE_b00[%d]\r\n", qmp6988_data_.qmp6988_cali.COE_a0,
|
||||
@@ -166,17 +139,17 @@ bool QMP6988Component::get_calibration_data_() {
|
||||
qmp6988_data_.ik.a0 = qmp6988_data_.qmp6988_cali.COE_a0; // 20Q4
|
||||
qmp6988_data_.ik.b00 = qmp6988_data_.qmp6988_cali.COE_b00; // 20Q4
|
||||
|
||||
qmp6988_data_.ik.a1 = 3608L * (QMP6988_S32_t) qmp6988_data_.qmp6988_cali.COE_a1 - 1731677965L; // 31Q23
|
||||
qmp6988_data_.ik.a2 = 16889L * (QMP6988_S32_t) qmp6988_data_.qmp6988_cali.COE_a2 - 87619360L; // 30Q47
|
||||
qmp6988_data_.ik.a1 = 3608L * (int32_t) qmp6988_data_.qmp6988_cali.COE_a1 - 1731677965L; // 31Q23
|
||||
qmp6988_data_.ik.a2 = 16889L * (int32_t) qmp6988_data_.qmp6988_cali.COE_a2 - 87619360L; // 30Q47
|
||||
|
||||
qmp6988_data_.ik.bt1 = 2982L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_bt1 + 107370906L; // 28Q15
|
||||
qmp6988_data_.ik.bt2 = 329854L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_bt2 + 108083093L; // 34Q38
|
||||
qmp6988_data_.ik.bp1 = 19923L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_bp1 + 1133836764L; // 31Q20
|
||||
qmp6988_data_.ik.b11 = 2406L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_b11 + 118215883L; // 28Q34
|
||||
qmp6988_data_.ik.bp2 = 3079L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_bp2 - 181579595L; // 29Q43
|
||||
qmp6988_data_.ik.b12 = 6846L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_b12 + 85590281L; // 29Q53
|
||||
qmp6988_data_.ik.b21 = 13836L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_b21 + 79333336L; // 29Q60
|
||||
qmp6988_data_.ik.bp3 = 2915L * (QMP6988_S64_t) qmp6988_data_.qmp6988_cali.COE_bp3 + 157155561L; // 28Q65
|
||||
qmp6988_data_.ik.bt1 = 2982L * (int64_t) qmp6988_data_.qmp6988_cali.COE_bt1 + 107370906L; // 28Q15
|
||||
qmp6988_data_.ik.bt2 = 329854L * (int64_t) qmp6988_data_.qmp6988_cali.COE_bt2 + 108083093L; // 34Q38
|
||||
qmp6988_data_.ik.bp1 = 19923L * (int64_t) qmp6988_data_.qmp6988_cali.COE_bp1 + 1133836764L; // 31Q20
|
||||
qmp6988_data_.ik.b11 = 2406L * (int64_t) qmp6988_data_.qmp6988_cali.COE_b11 + 118215883L; // 28Q34
|
||||
qmp6988_data_.ik.bp2 = 3079L * (int64_t) qmp6988_data_.qmp6988_cali.COE_bp2 - 181579595L; // 29Q43
|
||||
qmp6988_data_.ik.b12 = 6846L * (int64_t) qmp6988_data_.qmp6988_cali.COE_b12 + 85590281L; // 29Q53
|
||||
qmp6988_data_.ik.b21 = 13836L * (int64_t) qmp6988_data_.qmp6988_cali.COE_b21 + 79333336L; // 29Q60
|
||||
qmp6988_data_.ik.bp3 = 2915L * (int64_t) qmp6988_data_.qmp6988_cali.COE_bp3 + 157155561L; // 28Q65
|
||||
ESP_LOGV(TAG, "<----------- int calibration data -------------->\r\n");
|
||||
ESP_LOGV(TAG, "a0[%d] a1[%d] a2[%d] b00[%d]\r\n", qmp6988_data_.ik.a0, qmp6988_data_.ik.a1, qmp6988_data_.ik.a2,
|
||||
qmp6988_data_.ik.b00);
|
||||
@@ -188,55 +161,55 @@ bool QMP6988Component::get_calibration_data_() {
|
||||
return true;
|
||||
}
|
||||
|
||||
QMP6988_S16_t QMP6988Component::get_compensated_temperature_(qmp6988_ik_data_t *ik, QMP6988_S32_t dt) {
|
||||
QMP6988_S16_t ret;
|
||||
QMP6988_S64_t wk1, wk2;
|
||||
int16_t QMP6988Component::get_compensated_temperature_(qmp6988_ik_data_t *ik, int32_t dt) {
|
||||
int16_t ret;
|
||||
int64_t wk1, wk2;
|
||||
|
||||
// wk1: 60Q4 // bit size
|
||||
wk1 = ((QMP6988_S64_t) ik->a1 * (QMP6988_S64_t) dt); // 31Q23+24-1=54 (54Q23)
|
||||
wk2 = ((QMP6988_S64_t) ik->a2 * (QMP6988_S64_t) dt) >> 14; // 30Q47+24-1=53 (39Q33)
|
||||
wk2 = (wk2 * (QMP6988_S64_t) dt) >> 10; // 39Q33+24-1=62 (52Q23)
|
||||
wk2 = ((wk1 + wk2) / 32767) >> 19; // 54,52->55Q23 (20Q04)
|
||||
ret = (QMP6988_S16_t) ((ik->a0 + wk2) >> 4); // 21Q4 -> 17Q0
|
||||
wk1 = ((int64_t) ik->a1 * (int64_t) dt); // 31Q23+24-1=54 (54Q23)
|
||||
wk2 = ((int64_t) ik->a2 * (int64_t) dt) >> 14; // 30Q47+24-1=53 (39Q33)
|
||||
wk2 = (wk2 * (int64_t) dt) >> 10; // 39Q33+24-1=62 (52Q23)
|
||||
wk2 = ((wk1 + wk2) / 32767) >> 19; // 54,52->55Q23 (20Q04)
|
||||
ret = (int16_t) ((ik->a0 + wk2) >> 4); // 21Q4 -> 17Q0
|
||||
return ret;
|
||||
}
|
||||
|
||||
QMP6988_S32_t QMP6988Component::get_compensated_pressure_(qmp6988_ik_data_t *ik, QMP6988_S32_t dp, QMP6988_S16_t tx) {
|
||||
QMP6988_S32_t ret;
|
||||
QMP6988_S64_t wk1, wk2, wk3;
|
||||
int32_t QMP6988Component::get_compensated_pressure_(qmp6988_ik_data_t *ik, int32_t dp, int16_t tx) {
|
||||
int32_t ret;
|
||||
int64_t wk1, wk2, wk3;
|
||||
|
||||
// wk1 = 48Q16 // bit size
|
||||
wk1 = ((QMP6988_S64_t) ik->bt1 * (QMP6988_S64_t) tx); // 28Q15+16-1=43 (43Q15)
|
||||
wk2 = ((QMP6988_S64_t) ik->bp1 * (QMP6988_S64_t) dp) >> 5; // 31Q20+24-1=54 (49Q15)
|
||||
wk1 += wk2; // 43,49->50Q15
|
||||
wk2 = ((QMP6988_S64_t) ik->bt2 * (QMP6988_S64_t) tx) >> 1; // 34Q38+16-1=49 (48Q37)
|
||||
wk2 = (wk2 * (QMP6988_S64_t) tx) >> 8; // 48Q37+16-1=63 (55Q29)
|
||||
wk3 = wk2; // 55Q29
|
||||
wk2 = ((QMP6988_S64_t) ik->b11 * (QMP6988_S64_t) tx) >> 4; // 28Q34+16-1=43 (39Q30)
|
||||
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1; // 39Q30+24-1=62 (61Q29)
|
||||
wk3 += wk2; // 55,61->62Q29
|
||||
wk2 = ((QMP6988_S64_t) ik->bp2 * (QMP6988_S64_t) dp) >> 13; // 29Q43+24-1=52 (39Q30)
|
||||
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1; // 39Q30+24-1=62 (61Q29)
|
||||
wk3 += wk2; // 62,61->63Q29
|
||||
wk1 += wk3 >> 14; // Q29 >> 14 -> Q15
|
||||
wk2 = ((QMP6988_S64_t) ik->b12 * (QMP6988_S64_t) tx); // 29Q53+16-1=45 (45Q53)
|
||||
wk2 = (wk2 * (QMP6988_S64_t) tx) >> 22; // 45Q53+16-1=61 (39Q31)
|
||||
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1; // 39Q31+24-1=62 (61Q30)
|
||||
wk3 = wk2; // 61Q30
|
||||
wk2 = ((QMP6988_S64_t) ik->b21 * (QMP6988_S64_t) tx) >> 6; // 29Q60+16-1=45 (39Q54)
|
||||
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 23; // 39Q54+24-1=62 (39Q31)
|
||||
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1; // 39Q31+24-1=62 (61Q20)
|
||||
wk3 += wk2; // 61,61->62Q30
|
||||
wk2 = ((QMP6988_S64_t) ik->bp3 * (QMP6988_S64_t) dp) >> 12; // 28Q65+24-1=51 (39Q53)
|
||||
wk2 = (wk2 * (QMP6988_S64_t) dp) >> 23; // 39Q53+24-1=62 (39Q30)
|
||||
wk2 = (wk2 * (QMP6988_S64_t) dp); // 39Q30+24-1=62 (62Q30)
|
||||
wk3 += wk2; // 62,62->63Q30
|
||||
wk1 += wk3 >> 15; // Q30 >> 15 = Q15
|
||||
wk1 = ((int64_t) ik->bt1 * (int64_t) tx); // 28Q15+16-1=43 (43Q15)
|
||||
wk2 = ((int64_t) ik->bp1 * (int64_t) dp) >> 5; // 31Q20+24-1=54 (49Q15)
|
||||
wk1 += wk2; // 43,49->50Q15
|
||||
wk2 = ((int64_t) ik->bt2 * (int64_t) tx) >> 1; // 34Q38+16-1=49 (48Q37)
|
||||
wk2 = (wk2 * (int64_t) tx) >> 8; // 48Q37+16-1=63 (55Q29)
|
||||
wk3 = wk2; // 55Q29
|
||||
wk2 = ((int64_t) ik->b11 * (int64_t) tx) >> 4; // 28Q34+16-1=43 (39Q30)
|
||||
wk2 = (wk2 * (int64_t) dp) >> 1; // 39Q30+24-1=62 (61Q29)
|
||||
wk3 += wk2; // 55,61->62Q29
|
||||
wk2 = ((int64_t) ik->bp2 * (int64_t) dp) >> 13; // 29Q43+24-1=52 (39Q30)
|
||||
wk2 = (wk2 * (int64_t) dp) >> 1; // 39Q30+24-1=62 (61Q29)
|
||||
wk3 += wk2; // 62,61->63Q29
|
||||
wk1 += wk3 >> 14; // Q29 >> 14 -> Q15
|
||||
wk2 = ((int64_t) ik->b12 * (int64_t) tx); // 29Q53+16-1=45 (45Q53)
|
||||
wk2 = (wk2 * (int64_t) tx) >> 22; // 45Q53+16-1=61 (39Q31)
|
||||
wk2 = (wk2 * (int64_t) dp) >> 1; // 39Q31+24-1=62 (61Q30)
|
||||
wk3 = wk2; // 61Q30
|
||||
wk2 = ((int64_t) ik->b21 * (int64_t) tx) >> 6; // 29Q60+16-1=45 (39Q54)
|
||||
wk2 = (wk2 * (int64_t) dp) >> 23; // 39Q54+24-1=62 (39Q31)
|
||||
wk2 = (wk2 * (int64_t) dp) >> 1; // 39Q31+24-1=62 (61Q20)
|
||||
wk3 += wk2; // 61,61->62Q30
|
||||
wk2 = ((int64_t) ik->bp3 * (int64_t) dp) >> 12; // 28Q65+24-1=51 (39Q53)
|
||||
wk2 = (wk2 * (int64_t) dp) >> 23; // 39Q53+24-1=62 (39Q30)
|
||||
wk2 = (wk2 * (int64_t) dp); // 39Q30+24-1=62 (62Q30)
|
||||
wk3 += wk2; // 62,62->63Q30
|
||||
wk1 += wk3 >> 15; // Q30 >> 15 = Q15
|
||||
wk1 /= 32767L;
|
||||
wk1 >>= 11; // Q15 >> 7 = Q4
|
||||
wk1 += ik->b00; // Q4 + 20Q4
|
||||
// wk1 >>= 4; // 28Q4 -> 24Q0
|
||||
ret = (QMP6988_S32_t) wk1;
|
||||
ret = (int32_t) wk1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -274,7 +247,7 @@ void QMP6988Component::set_power_mode_(uint8_t power_mode) {
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void QMP6988Component::write_filter_(unsigned char filter) {
|
||||
void QMP6988Component::write_filter_(QMP6988IIRFilter filter) {
|
||||
uint8_t data;
|
||||
|
||||
data = (filter & 0x03);
|
||||
@@ -282,7 +255,7 @@ void QMP6988Component::write_filter_(unsigned char filter) {
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void QMP6988Component::write_oversampling_pressure_(unsigned char oversampling_p) {
|
||||
void QMP6988Component::write_oversampling_pressure_(QMP6988Oversampling oversampling_p) {
|
||||
uint8_t data;
|
||||
|
||||
this->read_register(QMP6988_CTRLMEAS_REG, &data, 1);
|
||||
@@ -292,7 +265,7 @@ void QMP6988Component::write_oversampling_pressure_(unsigned char oversampling_p
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void QMP6988Component::write_oversampling_temperature_(unsigned char oversampling_t) {
|
||||
void QMP6988Component::write_oversampling_temperature_(QMP6988Oversampling oversampling_t) {
|
||||
uint8_t data;
|
||||
|
||||
this->read_register(QMP6988_CTRLMEAS_REG, &data, 1);
|
||||
@@ -302,16 +275,6 @@ void QMP6988Component::write_oversampling_temperature_(unsigned char oversamplin
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void QMP6988Component::set_temperature_oversampling(QMP6988Oversampling oversampling_t) {
|
||||
this->temperature_oversampling_ = oversampling_t;
|
||||
}
|
||||
|
||||
void QMP6988Component::set_pressure_oversampling(QMP6988Oversampling oversampling_p) {
|
||||
this->pressure_oversampling_ = oversampling_p;
|
||||
}
|
||||
|
||||
void QMP6988Component::set_iir_filter(QMP6988IIRFilter iirfilter) { this->iir_filter_ = iirfilter; }
|
||||
|
||||
void QMP6988Component::calculate_altitude_(float pressure, float temp) {
|
||||
float altitude;
|
||||
altitude = (pow((101325 / pressure), 1 / 5.257) - 1) * (temp + 273.15) / 0.0065;
|
||||
@@ -320,10 +283,10 @@ void QMP6988Component::calculate_altitude_(float pressure, float temp) {
|
||||
|
||||
void QMP6988Component::calculate_pressure_() {
|
||||
uint8_t err = 0;
|
||||
QMP6988_U32_t p_read, t_read;
|
||||
QMP6988_S32_t p_raw, t_raw;
|
||||
uint32_t p_read, t_read;
|
||||
int32_t p_raw, t_raw;
|
||||
uint8_t a_data_uint8_tr[6] = {0};
|
||||
QMP6988_S32_t t_int, p_int;
|
||||
int32_t t_int, p_int;
|
||||
this->qmp6988_data_.temperature = 0;
|
||||
this->qmp6988_data_.pressure = 0;
|
||||
|
||||
@@ -332,13 +295,11 @@ void QMP6988Component::calculate_pressure_() {
|
||||
ESP_LOGE(TAG, "Error reading raw pressure/temp values");
|
||||
return;
|
||||
}
|
||||
p_read = (QMP6988_U32_t) ((((QMP6988_U32_t) (a_data_uint8_tr[0])) << SHIFT_LEFT_16_POSITION) |
|
||||
(((QMP6988_U16_t) (a_data_uint8_tr[1])) << SHIFT_LEFT_8_POSITION) | (a_data_uint8_tr[2]));
|
||||
p_raw = (QMP6988_S32_t) (p_read - SUBTRACTOR);
|
||||
p_read = encode_uint24(a_data_uint8_tr[0], a_data_uint8_tr[1], a_data_uint8_tr[2]);
|
||||
p_raw = (int32_t) (p_read - SUBTRACTOR);
|
||||
|
||||
t_read = (QMP6988_U32_t) ((((QMP6988_U32_t) (a_data_uint8_tr[3])) << SHIFT_LEFT_16_POSITION) |
|
||||
(((QMP6988_U16_t) (a_data_uint8_tr[4])) << SHIFT_LEFT_8_POSITION) | (a_data_uint8_tr[5]));
|
||||
t_raw = (QMP6988_S32_t) (t_read - SUBTRACTOR);
|
||||
t_read = encode_uint24(a_data_uint8_tr[3], a_data_uint8_tr[4], a_data_uint8_tr[5]);
|
||||
t_raw = (int32_t) (t_read - SUBTRACTOR);
|
||||
|
||||
t_int = this->get_compensated_temperature_(&(qmp6988_data_.ik), t_raw);
|
||||
p_int = this->get_compensated_pressure_(&(qmp6988_data_.ik), p_raw, t_int);
|
||||
@@ -348,10 +309,9 @@ void QMP6988Component::calculate_pressure_() {
|
||||
}
|
||||
|
||||
void QMP6988Component::setup() {
|
||||
bool ret;
|
||||
ret = this->device_check_();
|
||||
if (!ret) {
|
||||
ESP_LOGCONFIG(TAG, "Setup failed - device not found");
|
||||
if (!this->device_check_()) {
|
||||
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
this->software_reset_();
|
||||
@@ -365,9 +325,6 @@ void QMP6988Component::setup() {
|
||||
void QMP6988Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "QMP6988:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||
}
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
|
||||
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
|
||||
@@ -377,8 +334,6 @@ void QMP6988Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, " IIR Filter: %s", iir_filter_to_str(this->iir_filter_));
|
||||
}
|
||||
|
||||
float QMP6988Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||
|
||||
void QMP6988Component::update() {
|
||||
this->calculate_pressure_();
|
||||
float pressurehectopascals = this->qmp6988_data_.pressure / 100;
|
||||
|
@@ -1,24 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace qmp6988 {
|
||||
|
||||
#define QMP6988_U16_t unsigned short
|
||||
#define QMP6988_S16_t short
|
||||
#define QMP6988_U32_t unsigned int
|
||||
#define QMP6988_S32_t int
|
||||
#define QMP6988_U64_t unsigned long long
|
||||
#define QMP6988_S64_t long long
|
||||
|
||||
/* oversampling */
|
||||
enum QMP6988Oversampling {
|
||||
enum QMP6988Oversampling : uint8_t {
|
||||
QMP6988_OVERSAMPLING_SKIPPED = 0x00,
|
||||
QMP6988_OVERSAMPLING_1X = 0x01,
|
||||
QMP6988_OVERSAMPLING_2X = 0x02,
|
||||
@@ -30,7 +23,7 @@ enum QMP6988Oversampling {
|
||||
};
|
||||
|
||||
/* filter */
|
||||
enum QMP6988IIRFilter {
|
||||
enum QMP6988IIRFilter : uint8_t {
|
||||
QMP6988_IIR_FILTER_OFF = 0x00,
|
||||
QMP6988_IIR_FILTER_2X = 0x01,
|
||||
QMP6988_IIR_FILTER_4X = 0x02,
|
||||
@@ -40,18 +33,18 @@ enum QMP6988IIRFilter {
|
||||
};
|
||||
|
||||
using qmp6988_cali_data_t = struct Qmp6988CaliData {
|
||||
QMP6988_S32_t COE_a0;
|
||||
QMP6988_S16_t COE_a1;
|
||||
QMP6988_S16_t COE_a2;
|
||||
QMP6988_S32_t COE_b00;
|
||||
QMP6988_S16_t COE_bt1;
|
||||
QMP6988_S16_t COE_bt2;
|
||||
QMP6988_S16_t COE_bp1;
|
||||
QMP6988_S16_t COE_b11;
|
||||
QMP6988_S16_t COE_bp2;
|
||||
QMP6988_S16_t COE_b12;
|
||||
QMP6988_S16_t COE_b21;
|
||||
QMP6988_S16_t COE_bp3;
|
||||
int32_t COE_a0;
|
||||
int16_t COE_a1;
|
||||
int16_t COE_a2;
|
||||
int32_t COE_b00;
|
||||
int16_t COE_bt1;
|
||||
int16_t COE_bt2;
|
||||
int16_t COE_bp1;
|
||||
int16_t COE_b11;
|
||||
int16_t COE_bp2;
|
||||
int16_t COE_b12;
|
||||
int16_t COE_b21;
|
||||
int16_t COE_bp3;
|
||||
};
|
||||
|
||||
using qmp6988_fk_data_t = struct Qmp6988FkData {
|
||||
@@ -60,9 +53,9 @@ using qmp6988_fk_data_t = struct Qmp6988FkData {
|
||||
};
|
||||
|
||||
using qmp6988_ik_data_t = struct Qmp6988IkData {
|
||||
QMP6988_S32_t a0, b00;
|
||||
QMP6988_S32_t a1, a2;
|
||||
QMP6988_S64_t bt1, bt2, bp1, b11, bp2, b12, b21, bp3;
|
||||
int32_t a0, b00;
|
||||
int32_t a1, a2;
|
||||
int64_t bt1, bt2, bp1, b11, bp2, b12, b21, bp3;
|
||||
};
|
||||
|
||||
using qmp6988_data_t = struct Qmp6988Data {
|
||||
@@ -77,17 +70,18 @@ using qmp6988_data_t = struct Qmp6988Data {
|
||||
|
||||
class QMP6988Component : public PollingComponent, public i2c::I2CDevice {
|
||||
public:
|
||||
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
|
||||
void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; }
|
||||
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; }
|
||||
void set_pressure_sensor(sensor::Sensor *pressure_sensor) { this->pressure_sensor_ = pressure_sensor; }
|
||||
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
void update() override;
|
||||
|
||||
void set_iir_filter(QMP6988IIRFilter iirfilter);
|
||||
void set_temperature_oversampling(QMP6988Oversampling oversampling_t);
|
||||
void set_pressure_oversampling(QMP6988Oversampling oversampling_p);
|
||||
void set_iir_filter(QMP6988IIRFilter iirfilter) { this->iir_filter_ = iirfilter; }
|
||||
void set_temperature_oversampling(QMP6988Oversampling oversampling_t) {
|
||||
this->temperature_oversampling_ = oversampling_t;
|
||||
}
|
||||
void set_pressure_oversampling(QMP6988Oversampling oversampling_p) { this->pressure_oversampling_ = oversampling_p; }
|
||||
|
||||
protected:
|
||||
qmp6988_data_t qmp6988_data_;
|
||||
@@ -102,14 +96,14 @@ class QMP6988Component : public PollingComponent, public i2c::I2CDevice {
|
||||
bool get_calibration_data_();
|
||||
bool device_check_();
|
||||
void set_power_mode_(uint8_t power_mode);
|
||||
void write_oversampling_temperature_(unsigned char oversampling_t);
|
||||
void write_oversampling_pressure_(unsigned char oversampling_p);
|
||||
void write_filter_(unsigned char filter);
|
||||
void write_oversampling_temperature_(QMP6988Oversampling oversampling_t);
|
||||
void write_oversampling_pressure_(QMP6988Oversampling oversampling_p);
|
||||
void write_filter_(QMP6988IIRFilter filter);
|
||||
void calculate_pressure_();
|
||||
void calculate_altitude_(float pressure, float temp);
|
||||
|
||||
QMP6988_S32_t get_compensated_pressure_(qmp6988_ik_data_t *ik, QMP6988_S32_t dp, QMP6988_S16_t tx);
|
||||
QMP6988_S16_t get_compensated_temperature_(qmp6988_ik_data_t *ik, QMP6988_S32_t dt);
|
||||
int32_t get_compensated_pressure_(qmp6988_ik_data_t *ik, int32_t dp, int16_t tx);
|
||||
int16_t get_compensated_temperature_(qmp6988_ik_data_t *ik, int32_t dt);
|
||||
};
|
||||
|
||||
} // namespace qmp6988
|
||||
|
@@ -393,10 +393,13 @@ def icon(value):
|
||||
)
|
||||
|
||||
|
||||
def sub_device_id(value: str | None) -> core.ID:
|
||||
def sub_device_id(value: str | None) -> core.ID | None:
|
||||
# Lazy import to avoid circular imports
|
||||
from esphome.core.config import Device
|
||||
|
||||
if not value:
|
||||
return None
|
||||
|
||||
return use_id(Device)(value)
|
||||
|
||||
|
||||
|
@@ -77,8 +77,8 @@ async def setup_entity(var: MockObj, config: ConfigType, platform: str) -> None:
|
||||
"""
|
||||
# Get device info
|
||||
device_name: str | None = None
|
||||
if CONF_DEVICE_ID in config:
|
||||
device_id_obj: ID = config[CONF_DEVICE_ID]
|
||||
device_id_obj: ID | None
|
||||
if device_id_obj := config.get(CONF_DEVICE_ID):
|
||||
device: MockObj = await get_variable(device_id_obj)
|
||||
add(var.set_device(device))
|
||||
# Get device name for object ID calculation
|
||||
@@ -199,8 +199,8 @@ def entity_duplicate_validator(platform: str) -> Callable[[ConfigType], ConfigTy
|
||||
# Get device name if entity is on a sub-device
|
||||
device_name = None
|
||||
device_id = "" # Empty string for main device
|
||||
if CONF_DEVICE_ID in config:
|
||||
device_id_obj = config[CONF_DEVICE_ID]
|
||||
device_id_obj: ID | None
|
||||
if device_id_obj := config.get(CONF_DEVICE_ID):
|
||||
device_name = device_id_obj.id
|
||||
# Use the device ID string directly for uniqueness
|
||||
device_id = device_id_obj.id
|
||||
|
@@ -11,8 +11,8 @@ pyserial==3.5
|
||||
platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile
|
||||
esptool==5.0.2
|
||||
click==8.1.7
|
||||
esphome-dashboard==20250514.0
|
||||
aioesphomeapi==38.2.1
|
||||
esphome-dashboard==20250814.0
|
||||
aioesphomeapi==39.0.0
|
||||
zeroconf==0.147.0
|
||||
puremagic==1.30
|
||||
ruamel.yaml==0.18.14 # dashboard_import
|
||||
|
@@ -139,9 +139,24 @@ def _get_changed_files_github_actions() -> list[str] | None:
|
||||
if event_name == "pull_request":
|
||||
pr_number = _get_pr_number_from_github_env()
|
||||
if pr_number:
|
||||
# Use GitHub CLI to get changed files directly
|
||||
# Try gh pr diff first (faster for small PRs)
|
||||
cmd = ["gh", "pr", "diff", pr_number, "--name-only"]
|
||||
return _get_changed_files_from_command(cmd)
|
||||
try:
|
||||
return _get_changed_files_from_command(cmd)
|
||||
except Exception as e:
|
||||
# If it fails due to the 300 file limit, use the API method
|
||||
if "maximum" in str(e) and "files" in str(e):
|
||||
cmd = [
|
||||
"gh",
|
||||
"api",
|
||||
f"repos/esphome/esphome/pulls/{pr_number}/files",
|
||||
"--paginate",
|
||||
"--jq",
|
||||
".[].filename",
|
||||
]
|
||||
return _get_changed_files_from_command(cmd)
|
||||
# Re-raise for other errors
|
||||
raise
|
||||
|
||||
# For pushes (including squash-and-merge)
|
||||
elif event_name == "push":
|
||||
|
@@ -55,6 +55,12 @@ sensor:
|
||||
lambda: return 4.0;
|
||||
update_interval: 0.1s
|
||||
|
||||
- platform: template
|
||||
name: Living Room Sensor
|
||||
device_id: ""
|
||||
lambda: return 5.0;
|
||||
update_interval: 0.1s
|
||||
|
||||
# Switches with the same name on different devices to test device_id lookup
|
||||
switch:
|
||||
# Switch with no device_id (defaults to 0)
|
||||
@@ -96,3 +102,23 @@ switch:
|
||||
- logger.log: "Turning on Test Switch on Motion Detector"
|
||||
turn_off_action:
|
||||
- logger.log: "Turning off Test Switch on Motion Detector"
|
||||
|
||||
- platform: template
|
||||
name: Living Room Blank Switch
|
||||
device_id: ""
|
||||
id: test_switch_blank_living_room
|
||||
optimistic: true
|
||||
turn_on_action:
|
||||
- logger.log: "Turning on Living Room Blank Switch"
|
||||
turn_off_action:
|
||||
- logger.log: "Turning off Living Room Blank Switch"
|
||||
|
||||
- platform: template
|
||||
name: Living Room None Switch
|
||||
device_id:
|
||||
id: test_switch_none_living_room
|
||||
optimistic: true
|
||||
turn_on_action:
|
||||
- logger.log: "Turning on Living Room None Switch"
|
||||
turn_off_action:
|
||||
- logger.log: "Turning off Living Room None Switch"
|
||||
|
@@ -132,6 +132,7 @@ async def test_areas_and_devices(
|
||||
"Temperature Sensor Reading": temp_sensor.device_id,
|
||||
"Motion Detector Status": motion_detector.device_id,
|
||||
"Smart Switch Power": smart_switch.device_id,
|
||||
"Living Room Sensor": 0, # Main device
|
||||
}
|
||||
|
||||
for entity in sensor_entities:
|
||||
@@ -160,6 +161,18 @@ async def test_areas_and_devices(
|
||||
"Should have a switch with device_id 0 (main device)"
|
||||
)
|
||||
|
||||
# Verify extra switches with blank and none device_id are correctly available
|
||||
extra_switches = [
|
||||
e for e in switch_entities if e.name.startswith("Living Room")
|
||||
]
|
||||
assert len(extra_switches) == 2, (
|
||||
f"Expected 2 extra switches for Living Room, got {len(extra_switches)}"
|
||||
)
|
||||
extra_switch_device_ids = [e.device_id for e in extra_switches]
|
||||
assert all(d == 0 for d in extra_switch_device_ids), (
|
||||
"All extra switches should have device_id 0 (main device)"
|
||||
)
|
||||
|
||||
# Wait for initial states to be received for all switches
|
||||
await asyncio.wait_for(initial_states_future, timeout=2.0)
|
||||
|
||||
|
@@ -183,6 +183,61 @@ def test_get_changed_files_github_actions_pull_request(
|
||||
assert result == expected_files
|
||||
|
||||
|
||||
def test_get_changed_files_github_actions_pull_request_large_pr(
|
||||
monkeypatch: MonkeyPatch,
|
||||
) -> None:
|
||||
"""Test _get_changed_files_github_actions fallback for PRs with >300 files."""
|
||||
monkeypatch.setenv("GITHUB_EVENT_NAME", "pull_request")
|
||||
|
||||
expected_files = ["file1.py", "file2.cpp"]
|
||||
|
||||
with (
|
||||
patch("helpers._get_pr_number_from_github_env", return_value="10214"),
|
||||
patch("helpers._get_changed_files_from_command") as mock_get,
|
||||
):
|
||||
# First call fails with too many files error, second succeeds with API method
|
||||
mock_get.side_effect = [
|
||||
Exception("Sorry, the diff exceeded the maximum number of files (300)"),
|
||||
expected_files,
|
||||
]
|
||||
|
||||
result = _get_changed_files_github_actions()
|
||||
|
||||
assert mock_get.call_count == 2
|
||||
mock_get.assert_any_call(["gh", "pr", "diff", "10214", "--name-only"])
|
||||
mock_get.assert_any_call(
|
||||
[
|
||||
"gh",
|
||||
"api",
|
||||
"repos/esphome/esphome/pulls/10214/files",
|
||||
"--paginate",
|
||||
"--jq",
|
||||
".[].filename",
|
||||
]
|
||||
)
|
||||
assert result == expected_files
|
||||
|
||||
|
||||
def test_get_changed_files_github_actions_pull_request_other_error(
|
||||
monkeypatch: MonkeyPatch,
|
||||
) -> None:
|
||||
"""Test _get_changed_files_github_actions re-raises non-file-limit errors."""
|
||||
monkeypatch.setenv("GITHUB_EVENT_NAME", "pull_request")
|
||||
|
||||
with (
|
||||
patch("helpers._get_pr_number_from_github_env", return_value="1234"),
|
||||
patch("helpers._get_changed_files_from_command") as mock_get,
|
||||
):
|
||||
# Error that is not about file limit
|
||||
mock_get.side_effect = Exception("Command failed: authentication required")
|
||||
|
||||
with pytest.raises(Exception, match="authentication required"):
|
||||
_get_changed_files_github_actions()
|
||||
|
||||
# Should only be called once (no retry with API)
|
||||
mock_get.assert_called_once_with(["gh", "pr", "diff", "1234", "--name-only"])
|
||||
|
||||
|
||||
def test_get_changed_files_github_actions_pull_request_no_pr_number(
|
||||
monkeypatch: MonkeyPatch,
|
||||
) -> None:
|
||||
|
@@ -689,3 +689,19 @@ def test_entity_duplicate_validator_internal_entities() -> None:
|
||||
Invalid, match=r"Duplicate sensor entity with name 'Temperature' found"
|
||||
):
|
||||
validator(config4)
|
||||
|
||||
|
||||
def test_empty_or_null_device_id_on_entity() -> None:
|
||||
"""Test that empty or null device IDs are handled correctly."""
|
||||
# Create validator for sensor platform
|
||||
validator = entity_duplicate_validator("sensor")
|
||||
|
||||
# Entity with empty device_id should pass
|
||||
config1 = {CONF_NAME: "Battery", CONF_DEVICE_ID: ""}
|
||||
validated1 = validator(config1)
|
||||
assert validated1 == config1
|
||||
|
||||
# Entity with None device_id should pass
|
||||
config2 = {CONF_NAME: "Temperature", CONF_DEVICE_ID: None}
|
||||
validated2 = validator(config2)
|
||||
assert validated2 == config2
|
||||
|
Reference in New Issue
Block a user