mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00: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 header_padding = conn->helper_->frame_header_padding(); | ||||||
|   const uint8_t footer_size = conn->helper_->frame_footer_size(); |   const uint8_t footer_size = conn->helper_->frame_footer_size(); | ||||||
|  |  | ||||||
|   // Calculate total size with padding for buffer allocation |   // Calculate total size with padding | ||||||
|   size_t total_calculated_size = calculated_size + header_padding + footer_size; |   size_t total_size = calculated_size + header_padding + footer_size; | ||||||
|  |  | ||||||
|   // Check if it fits |   // Check if it fits | ||||||
|   if (total_calculated_size > remaining_size) { |   if (total_size > remaining_size) { | ||||||
|     return 0;  // Doesn't fit |     return 0;  // Doesn't fit | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Allocate buffer space - pass payload size, allocation functions add header/footer space |   // Get buffer and prepare it inline | ||||||
|   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) |  | ||||||
|   std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref(); |   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 |   // Encode directly into buffer | ||||||
|  |   ProtoWriteBuffer buffer{&shared_buf}; | ||||||
|  |   size_t size_before_encode = shared_buf.size(); | ||||||
|   msg.encode(buffer); |   msg.encode(buffer); | ||||||
|  |  | ||||||
|   // Calculate actual encoded size (not including header that was already added) |   // Calculate actual encoded size (not including header that was already added) | ||||||
| @@ -1620,14 +1631,6 @@ bool APIConnection::schedule_batch_() { | |||||||
|   return true; |   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_() { | void APIConnection::process_batch_() { | ||||||
|   // Ensure PacketInfo remains trivially destructible for our placement new approach |   // Ensure PacketInfo remains trivially destructible for our placement new approach | ||||||
|   static_assert(std::is_trivially_destructible<PacketInfo>::value, |   static_assert(std::is_trivially_destructible<PacketInfo>::value, | ||||||
| @@ -1735,7 +1738,7 @@ void APIConnection::process_batch_() { | |||||||
|     } |     } | ||||||
|     remaining_size -= payload_size; |     remaining_size -= payload_size; | ||||||
|     // Calculate where the next message's header padding will start |     // 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; |     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 |     // Get header padding size - used for both reserve and insert | ||||||
|     uint8_t header_padding = this->helper_->frame_header_padding(); |     uint8_t header_padding = this->helper_->frame_header_padding(); | ||||||
|  |  | ||||||
|     // Get shared buffer from parent server |     // Get shared buffer from parent server | ||||||
|     std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref(); |     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(); |     shared_buf.clear(); | ||||||
|     // Reserve space for header padding + message + footer |     // Reserve space for header padding + message + footer | ||||||
|     // - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext) |     // - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext) | ||||||
|     // - Footer: space for MAC (16 bytes for Noise, 0 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 |     // Resize to add header padding so message encoding starts at the correct position | ||||||
|     shared_buf.resize(header_padding); |     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); |   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(); } |   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: |  protected: | ||||||
|   // Helper function to handle authentication completion |   // Helper function to handle authentication completion | ||||||
|   void complete_authentication_(); |   void complete_authentication_(); | ||||||
|   | |||||||
| @@ -208,11 +208,11 @@ void ESPNowComponent::enable_() { | |||||||
|   esp_wifi_connectionless_module_set_wake_interval(CONFIG_ESPNOW_WAKE_INTERVAL); |   esp_wifi_connectionless_module_set_wake_interval(CONFIG_ESPNOW_WAKE_INTERVAL); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |   this->state_ = ESPNOW_STATE_ENABLED; | ||||||
|  |  | ||||||
|   for (auto peer : this->peers_) { |   for (auto peer : this->peers_) { | ||||||
|     this->add_peer(peer.address); |     this->add_peer(peer.address); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this->state_ = ESPNOW_STATE_ENABLED; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void ESPNowComponent::disable() { | 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) { |   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; |     return ESP_ERR_INVALID_MAC; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ from esphome.components.esp32.const import ( | |||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_ADVANCED, |     CONF_ADVANCED, | ||||||
|  |     CONF_DISABLED, | ||||||
|     CONF_FRAMEWORK, |     CONF_FRAMEWORK, | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
|     CONF_MODE, |     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_MODE, default=modes[0]): cv.one_of(*modes, lower=True), | ||||||
|             cv.Optional(CONF_ENABLE_ECC, default=False): cv.boolean, |             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_SPEED, default=speeds[0]): cv.one_of(*speeds, upper=True), | ||||||
|  |             cv.Optional(CONF_DISABLED, default=False): cv.boolean, | ||||||
|         } |         } | ||||||
|     )(config) |     )(config) | ||||||
|  |  | ||||||
| @@ -112,6 +114,8 @@ FINAL_VALIDATE_SCHEMA = validate_psram_mode | |||||||
|  |  | ||||||
|  |  | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|  |     if config[CONF_DISABLED]: | ||||||
|  |         return | ||||||
|     if CORE.using_arduino: |     if CORE.using_arduino: | ||||||
|         cg.add_build_flag("-DBOARD_HAS_PSRAM") |         cg.add_build_flag("-DBOARD_HAS_PSRAM") | ||||||
|         if config[CONF_MODE] == TYPE_OCTAL: |         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_START = 0xA0; /* QMP6988 compensation coefficients */ | ||||||
| static const uint8_t QMP6988_CALIBRATION_DATA_LENGTH = 25; | 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 */ | /* power mode */ | ||||||
| static const uint8_t QMP6988_SLEEP_MODE = 0x00; | static const uint8_t QMP6988_SLEEP_MODE = 0x00; | ||||||
| static const uint8_t QMP6988_FORCED_MODE = 0x01; | 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_() { | bool QMP6988Component::device_check_() { | ||||||
|   uint8_t ret = 0; |   if (this->read_register(QMP6988_CHIP_ID_REG, &(qmp6988_data_.chip_id), 1) != i2c::ERROR_OK) { | ||||||
|  |     ESP_LOGE(TAG, "Read chip ID (0xD1) failed"); | ||||||
|   ret = this->read_register(QMP6988_CHIP_ID_REG, &(qmp6988_data_.chip_id), 1); |     return false; | ||||||
|   if (ret != i2c::ERROR_OK) { |  | ||||||
|     ESP_LOGE(TAG, "%s: read chip ID (0xD1) failed", __func__); |  | ||||||
|   } |   } | ||||||
|   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; |   return qmp6988_data_.chip_id == QMP6988_CHIP_ID; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool QMP6988Component::get_calibration_data_() { | bool QMP6988Component::get_calibration_data_() { | ||||||
|   uint8_t status = 0; |  | ||||||
|   // BITFIELDS temp_COE; |   // BITFIELDS temp_COE; | ||||||
|   uint8_t a_data_uint8_tr[QMP6988_CALIBRATION_DATA_LENGTH] = {0}; |   uint8_t a_data_uint8_tr[QMP6988_CALIBRATION_DATA_LENGTH] = {0}; | ||||||
|   int len; |  | ||||||
|  |  | ||||||
|   for (len = 0; len < QMP6988_CALIBRATION_DATA_LENGTH; len += 1) { |   for (uint8_t 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 (this->read_register(QMP6988_CALIBRATION_DATA_START + len, &a_data_uint8_tr[len], 1) != i2c::ERROR_OK) { | ||||||
|     if (status != i2c::ERROR_OK) { |       ESP_LOGE(TAG, "Read calibration data (0xA0) error"); | ||||||
|       ESP_LOGE(TAG, "qmp6988 read calibration data (0xA0) error!"); |  | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   qmp6988_data_.qmp6988_cali.COE_a0 = |   qmp6988_data_.qmp6988_cali.COE_a0 = | ||||||
|       (QMP6988_S32_t) (((a_data_uint8_tr[18] << SHIFT_LEFT_12_POSITION) | |       (int32_t) encode_uint32(a_data_uint8_tr[18], a_data_uint8_tr[19], (a_data_uint8_tr[24] & 0x0f) << 4, 0); | ||||||
|                         (a_data_uint8_tr[19] << SHIFT_LEFT_4_POSITION) | (a_data_uint8_tr[24] & 0x0f)) |  | ||||||
|                        << 12); |  | ||||||
|   qmp6988_data_.qmp6988_cali.COE_a0 = qmp6988_data_.qmp6988_cali.COE_a0 >> 12; |   qmp6988_data_.qmp6988_cali.COE_a0 = qmp6988_data_.qmp6988_cali.COE_a0 >> 12; | ||||||
|  |  | ||||||
|   qmp6988_data_.qmp6988_cali.COE_a1 = |   qmp6988_data_.qmp6988_cali.COE_a1 = (int16_t) encode_uint16(a_data_uint8_tr[20], a_data_uint8_tr[21]); | ||||||
|       (QMP6988_S16_t) (((a_data_uint8_tr[20]) << SHIFT_LEFT_8_POSITION) | 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_a2 = |  | ||||||
|       (QMP6988_S16_t) (((a_data_uint8_tr[22]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[23]); |  | ||||||
|  |  | ||||||
|   qmp6988_data_.qmp6988_cali.COE_b00 = |   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) | |       (int32_t) encode_uint32(a_data_uint8_tr[0], a_data_uint8_tr[1], a_data_uint8_tr[24] & 0xf0, 0); | ||||||
|                         ((a_data_uint8_tr[24] & 0xf0) >> SHIFT_RIGHT_4_POSITION)) |  | ||||||
|                        << 12); |  | ||||||
|   qmp6988_data_.qmp6988_cali.COE_b00 = qmp6988_data_.qmp6988_cali.COE_b00 >> 12; |   qmp6988_data_.qmp6988_cali.COE_b00 = qmp6988_data_.qmp6988_cali.COE_b00 >> 12; | ||||||
|  |  | ||||||
|   qmp6988_data_.qmp6988_cali.COE_bt1 = |   qmp6988_data_.qmp6988_cali.COE_bt1 = (int16_t) encode_uint16(a_data_uint8_tr[2], a_data_uint8_tr[3]); | ||||||
|       (QMP6988_S16_t) (((a_data_uint8_tr[2]) << SHIFT_LEFT_8_POSITION) | 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_bt2 = |   qmp6988_data_.qmp6988_cali.COE_bp1 = (int16_t) encode_uint16(a_data_uint8_tr[6], a_data_uint8_tr[7]); | ||||||
|       (QMP6988_S16_t) (((a_data_uint8_tr[4]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[5]); |   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_bp1 = |   qmp6988_data_.qmp6988_cali.COE_bp2 = (int16_t) encode_uint16(a_data_uint8_tr[10], a_data_uint8_tr[11]); | ||||||
|       (QMP6988_S16_t) (((a_data_uint8_tr[6]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[7]); |   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_b11 = |   qmp6988_data_.qmp6988_cali.COE_b21 = (int16_t) encode_uint16(a_data_uint8_tr[14], a_data_uint8_tr[15]); | ||||||
|       (QMP6988_S16_t) (((a_data_uint8_tr[8]) << SHIFT_LEFT_8_POSITION) | a_data_uint8_tr[9]); |   qmp6988_data_.qmp6988_cali.COE_bp3 = (int16_t) encode_uint16(a_data_uint8_tr[16], a_data_uint8_tr[17]); | ||||||
|   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]); |  | ||||||
|  |  | ||||||
|   ESP_LOGV(TAG, "<-----------calibration data-------------->\r\n"); |   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, |   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.a0 = qmp6988_data_.qmp6988_cali.COE_a0;    // 20Q4 | ||||||
|   qmp6988_data_.ik.b00 = qmp6988_data_.qmp6988_cali.COE_b00;  // 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.a1 = 3608L * (int32_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.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.bt1 = 2982L * (int64_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.bt2 = 329854L * (int64_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.bp1 = 19923L * (int64_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.b11 = 2406L * (int64_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.bp2 = 3079L * (int64_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.b12 = 6846L * (int64_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.b21 = 13836L * (int64_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.bp3 = 2915L * (int64_t) qmp6988_data_.qmp6988_cali.COE_bp3 + 157155561L;    // 28Q65 | ||||||
|   ESP_LOGV(TAG, "<----------- int calibration data -------------->\r\n"); |   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, |   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); |            qmp6988_data_.ik.b00); | ||||||
| @@ -188,55 +161,55 @@ bool QMP6988Component::get_calibration_data_() { | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| QMP6988_S16_t QMP6988Component::get_compensated_temperature_(qmp6988_ik_data_t *ik, QMP6988_S32_t dt) { | int16_t QMP6988Component::get_compensated_temperature_(qmp6988_ik_data_t *ik, int32_t dt) { | ||||||
|   QMP6988_S16_t ret; |   int16_t ret; | ||||||
|   QMP6988_S64_t wk1, wk2; |   int64_t wk1, wk2; | ||||||
|  |  | ||||||
|   // wk1: 60Q4 // bit size |   // wk1: 60Q4 // bit size | ||||||
|   wk1 = ((QMP6988_S64_t) ik->a1 * (QMP6988_S64_t) dt);        // 31Q23+24-1=54 (54Q23) |   wk1 = ((int64_t) ik->a1 * (int64_t) dt);        // 31Q23+24-1=54 (54Q23) | ||||||
|   wk2 = ((QMP6988_S64_t) ik->a2 * (QMP6988_S64_t) dt) >> 14;  // 30Q47+24-1=53 (39Q33) |   wk2 = ((int64_t) ik->a2 * (int64_t) dt) >> 14;  // 30Q47+24-1=53 (39Q33) | ||||||
|   wk2 = (wk2 * (QMP6988_S64_t) dt) >> 10;                     // 39Q33+24-1=62 (52Q23) |   wk2 = (wk2 * (int64_t) dt) >> 10;               // 39Q33+24-1=62 (52Q23) | ||||||
|   wk2 = ((wk1 + wk2) / 32767) >> 19;                          // 54,52->55Q23 (20Q04) |   wk2 = ((wk1 + wk2) / 32767) >> 19;              // 54,52->55Q23 (20Q04) | ||||||
|   ret = (QMP6988_S16_t) ((ik->a0 + wk2) >> 4);                // 21Q4 -> 17Q0 |   ret = (int16_t) ((ik->a0 + wk2) >> 4);          // 21Q4 -> 17Q0 | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| QMP6988_S32_t QMP6988Component::get_compensated_pressure_(qmp6988_ik_data_t *ik, QMP6988_S32_t dp, QMP6988_S16_t tx) { | int32_t QMP6988Component::get_compensated_pressure_(qmp6988_ik_data_t *ik, int32_t dp, int16_t tx) { | ||||||
|   QMP6988_S32_t ret; |   int32_t ret; | ||||||
|   QMP6988_S64_t wk1, wk2, wk3; |   int64_t wk1, wk2, wk3; | ||||||
|  |  | ||||||
|   // wk1 = 48Q16 // bit size |   // wk1 = 48Q16 // bit size | ||||||
|   wk1 = ((QMP6988_S64_t) ik->bt1 * (QMP6988_S64_t) tx);        // 28Q15+16-1=43 (43Q15) |   wk1 = ((int64_t) ik->bt1 * (int64_t) tx);        // 28Q15+16-1=43 (43Q15) | ||||||
|   wk2 = ((QMP6988_S64_t) ik->bp1 * (QMP6988_S64_t) dp) >> 5;   // 31Q20+24-1=54 (49Q15) |   wk2 = ((int64_t) ik->bp1 * (int64_t) dp) >> 5;   // 31Q20+24-1=54 (49Q15) | ||||||
|   wk1 += wk2;                                                  // 43,49->50Q15 |   wk1 += wk2;                                      // 43,49->50Q15 | ||||||
|   wk2 = ((QMP6988_S64_t) ik->bt2 * (QMP6988_S64_t) tx) >> 1;   // 34Q38+16-1=49 (48Q37) |   wk2 = ((int64_t) ik->bt2 * (int64_t) tx) >> 1;   // 34Q38+16-1=49 (48Q37) | ||||||
|   wk2 = (wk2 * (QMP6988_S64_t) tx) >> 8;                       // 48Q37+16-1=63 (55Q29) |   wk2 = (wk2 * (int64_t) tx) >> 8;                 // 48Q37+16-1=63 (55Q29) | ||||||
|   wk3 = wk2;                                                   // 55Q29 |   wk3 = wk2;                                       // 55Q29 | ||||||
|   wk2 = ((QMP6988_S64_t) ik->b11 * (QMP6988_S64_t) tx) >> 4;   // 28Q34+16-1=43 (39Q30) |   wk2 = ((int64_t) ik->b11 * (int64_t) tx) >> 4;   // 28Q34+16-1=43 (39Q30) | ||||||
|   wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1;                       // 39Q30+24-1=62 (61Q29) |   wk2 = (wk2 * (int64_t) dp) >> 1;                 // 39Q30+24-1=62 (61Q29) | ||||||
|   wk3 += wk2;                                                  // 55,61->62Q29 |   wk3 += wk2;                                      // 55,61->62Q29 | ||||||
|   wk2 = ((QMP6988_S64_t) ik->bp2 * (QMP6988_S64_t) dp) >> 13;  // 29Q43+24-1=52 (39Q30) |   wk2 = ((int64_t) ik->bp2 * (int64_t) dp) >> 13;  // 29Q43+24-1=52 (39Q30) | ||||||
|   wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1;                       // 39Q30+24-1=62 (61Q29) |   wk2 = (wk2 * (int64_t) dp) >> 1;                 // 39Q30+24-1=62 (61Q29) | ||||||
|   wk3 += wk2;                                                  // 62,61->63Q29 |   wk3 += wk2;                                      // 62,61->63Q29 | ||||||
|   wk1 += wk3 >> 14;                                            // Q29 >> 14 -> Q15 |   wk1 += wk3 >> 14;                                // Q29 >> 14 -> Q15 | ||||||
|   wk2 = ((QMP6988_S64_t) ik->b12 * (QMP6988_S64_t) tx);        // 29Q53+16-1=45 (45Q53) |   wk2 = ((int64_t) ik->b12 * (int64_t) tx);        // 29Q53+16-1=45 (45Q53) | ||||||
|   wk2 = (wk2 * (QMP6988_S64_t) tx) >> 22;                      // 45Q53+16-1=61 (39Q31) |   wk2 = (wk2 * (int64_t) tx) >> 22;                // 45Q53+16-1=61 (39Q31) | ||||||
|   wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1;                       // 39Q31+24-1=62 (61Q30) |   wk2 = (wk2 * (int64_t) dp) >> 1;                 // 39Q31+24-1=62 (61Q30) | ||||||
|   wk3 = wk2;                                                   // 61Q30 |   wk3 = wk2;                                       // 61Q30 | ||||||
|   wk2 = ((QMP6988_S64_t) ik->b21 * (QMP6988_S64_t) tx) >> 6;   // 29Q60+16-1=45 (39Q54) |   wk2 = ((int64_t) ik->b21 * (int64_t) tx) >> 6;   // 29Q60+16-1=45 (39Q54) | ||||||
|   wk2 = (wk2 * (QMP6988_S64_t) dp) >> 23;                      // 39Q54+24-1=62 (39Q31) |   wk2 = (wk2 * (int64_t) dp) >> 23;                // 39Q54+24-1=62 (39Q31) | ||||||
|   wk2 = (wk2 * (QMP6988_S64_t) dp) >> 1;                       // 39Q31+24-1=62 (61Q20) |   wk2 = (wk2 * (int64_t) dp) >> 1;                 // 39Q31+24-1=62 (61Q20) | ||||||
|   wk3 += wk2;                                                  // 61,61->62Q30 |   wk3 += wk2;                                      // 61,61->62Q30 | ||||||
|   wk2 = ((QMP6988_S64_t) ik->bp3 * (QMP6988_S64_t) dp) >> 12;  // 28Q65+24-1=51 (39Q53) |   wk2 = ((int64_t) ik->bp3 * (int64_t) dp) >> 12;  // 28Q65+24-1=51 (39Q53) | ||||||
|   wk2 = (wk2 * (QMP6988_S64_t) dp) >> 23;                      // 39Q53+24-1=62 (39Q30) |   wk2 = (wk2 * (int64_t) dp) >> 23;                // 39Q53+24-1=62 (39Q30) | ||||||
|   wk2 = (wk2 * (QMP6988_S64_t) dp);                            // 39Q30+24-1=62 (62Q30) |   wk2 = (wk2 * (int64_t) dp);                      // 39Q30+24-1=62 (62Q30) | ||||||
|   wk3 += wk2;                                                  // 62,62->63Q30 |   wk3 += wk2;                                      // 62,62->63Q30 | ||||||
|   wk1 += wk3 >> 15;                                            // Q30 >> 15 = Q15 |   wk1 += wk3 >> 15;                                // Q30 >> 15 = Q15 | ||||||
|   wk1 /= 32767L; |   wk1 /= 32767L; | ||||||
|   wk1 >>= 11;      // Q15 >> 7 = Q4 |   wk1 >>= 11;      // Q15 >> 7 = Q4 | ||||||
|   wk1 += ik->b00;  // Q4 + 20Q4 |   wk1 += ik->b00;  // Q4 + 20Q4 | ||||||
|   // wk1 >>= 4; // 28Q4 -> 24Q0 |   // wk1 >>= 4; // 28Q4 -> 24Q0 | ||||||
|   ret = (QMP6988_S32_t) wk1; |   ret = (int32_t) wk1; | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -274,7 +247,7 @@ void QMP6988Component::set_power_mode_(uint8_t power_mode) { | |||||||
|   delay(10); |   delay(10); | ||||||
| } | } | ||||||
|  |  | ||||||
| void QMP6988Component::write_filter_(unsigned char filter) { | void QMP6988Component::write_filter_(QMP6988IIRFilter filter) { | ||||||
|   uint8_t data; |   uint8_t data; | ||||||
|  |  | ||||||
|   data = (filter & 0x03); |   data = (filter & 0x03); | ||||||
| @@ -282,7 +255,7 @@ void QMP6988Component::write_filter_(unsigned char filter) { | |||||||
|   delay(10); |   delay(10); | ||||||
| } | } | ||||||
|  |  | ||||||
| void QMP6988Component::write_oversampling_pressure_(unsigned char oversampling_p) { | void QMP6988Component::write_oversampling_pressure_(QMP6988Oversampling oversampling_p) { | ||||||
|   uint8_t data; |   uint8_t data; | ||||||
|  |  | ||||||
|   this->read_register(QMP6988_CTRLMEAS_REG, &data, 1); |   this->read_register(QMP6988_CTRLMEAS_REG, &data, 1); | ||||||
| @@ -292,7 +265,7 @@ void QMP6988Component::write_oversampling_pressure_(unsigned char oversampling_p | |||||||
|   delay(10); |   delay(10); | ||||||
| } | } | ||||||
|  |  | ||||||
| void QMP6988Component::write_oversampling_temperature_(unsigned char oversampling_t) { | void QMP6988Component::write_oversampling_temperature_(QMP6988Oversampling oversampling_t) { | ||||||
|   uint8_t data; |   uint8_t data; | ||||||
|  |  | ||||||
|   this->read_register(QMP6988_CTRLMEAS_REG, &data, 1); |   this->read_register(QMP6988_CTRLMEAS_REG, &data, 1); | ||||||
| @@ -302,16 +275,6 @@ void QMP6988Component::write_oversampling_temperature_(unsigned char oversamplin | |||||||
|   delay(10); |   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) { | void QMP6988Component::calculate_altitude_(float pressure, float temp) { | ||||||
|   float altitude; |   float altitude; | ||||||
|   altitude = (pow((101325 / pressure), 1 / 5.257) - 1) * (temp + 273.15) / 0.0065; |   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_() { | void QMP6988Component::calculate_pressure_() { | ||||||
|   uint8_t err = 0; |   uint8_t err = 0; | ||||||
|   QMP6988_U32_t p_read, t_read; |   uint32_t p_read, t_read; | ||||||
|   QMP6988_S32_t p_raw, t_raw; |   int32_t p_raw, t_raw; | ||||||
|   uint8_t a_data_uint8_tr[6] = {0}; |   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_.temperature = 0; | ||||||
|   this->qmp6988_data_.pressure = 0; |   this->qmp6988_data_.pressure = 0; | ||||||
|  |  | ||||||
| @@ -332,13 +295,11 @@ void QMP6988Component::calculate_pressure_() { | |||||||
|     ESP_LOGE(TAG, "Error reading raw pressure/temp values"); |     ESP_LOGE(TAG, "Error reading raw pressure/temp values"); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   p_read = (QMP6988_U32_t) ((((QMP6988_U32_t) (a_data_uint8_tr[0])) << SHIFT_LEFT_16_POSITION) | |   p_read = encode_uint24(a_data_uint8_tr[0], a_data_uint8_tr[1], a_data_uint8_tr[2]); | ||||||
|                             (((QMP6988_U16_t) (a_data_uint8_tr[1])) << SHIFT_LEFT_8_POSITION) | (a_data_uint8_tr[2])); |   p_raw = (int32_t) (p_read - SUBTRACTOR); | ||||||
|   p_raw = (QMP6988_S32_t) (p_read - SUBTRACTOR); |  | ||||||
|  |  | ||||||
|   t_read = (QMP6988_U32_t) ((((QMP6988_U32_t) (a_data_uint8_tr[3])) << SHIFT_LEFT_16_POSITION) | |   t_read = encode_uint24(a_data_uint8_tr[3], a_data_uint8_tr[4], a_data_uint8_tr[5]); | ||||||
|                             (((QMP6988_U16_t) (a_data_uint8_tr[4])) << SHIFT_LEFT_8_POSITION) | (a_data_uint8_tr[5])); |   t_raw = (int32_t) (t_read - SUBTRACTOR); | ||||||
|   t_raw = (QMP6988_S32_t) (t_read - SUBTRACTOR); |  | ||||||
|  |  | ||||||
|   t_int = this->get_compensated_temperature_(&(qmp6988_data_.ik), t_raw); |   t_int = this->get_compensated_temperature_(&(qmp6988_data_.ik), t_raw); | ||||||
|   p_int = this->get_compensated_pressure_(&(qmp6988_data_.ik), p_raw, t_int); |   p_int = this->get_compensated_pressure_(&(qmp6988_data_.ik), p_raw, t_int); | ||||||
| @@ -348,10 +309,9 @@ void QMP6988Component::calculate_pressure_() { | |||||||
| } | } | ||||||
|  |  | ||||||
| void QMP6988Component::setup() { | void QMP6988Component::setup() { | ||||||
|   bool ret; |   if (!this->device_check_()) { | ||||||
|   ret = this->device_check_(); |     this->mark_failed(ESP_LOG_MSG_COMM_FAIL); | ||||||
|   if (!ret) { |     return; | ||||||
|     ESP_LOGCONFIG(TAG, "Setup failed - device not found"); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this->software_reset_(); |   this->software_reset_(); | ||||||
| @@ -365,9 +325,6 @@ void QMP6988Component::setup() { | |||||||
| void QMP6988Component::dump_config() { | void QMP6988Component::dump_config() { | ||||||
|   ESP_LOGCONFIG(TAG, "QMP6988:"); |   ESP_LOGCONFIG(TAG, "QMP6988:"); | ||||||
|   LOG_I2C_DEVICE(this); |   LOG_I2C_DEVICE(this); | ||||||
|   if (this->is_failed()) { |  | ||||||
|     ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); |  | ||||||
|   } |  | ||||||
|   LOG_UPDATE_INTERVAL(this); |   LOG_UPDATE_INTERVAL(this); | ||||||
|  |  | ||||||
|   LOG_SENSOR("  ", "Temperature", this->temperature_sensor_); |   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_)); |   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() { | void QMP6988Component::update() { | ||||||
|   this->calculate_pressure_(); |   this->calculate_pressure_(); | ||||||
|   float pressurehectopascals = this->qmp6988_data_.pressure / 100; |   float pressurehectopascals = this->qmp6988_data_.pressure / 100; | ||||||
|   | |||||||
| @@ -1,24 +1,17 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/i2c/i2c.h" | ||||||
|  | #include "esphome/components/sensor/sensor.h" | ||||||
| #include "esphome/core/component.h" | #include "esphome/core/component.h" | ||||||
| #include "esphome/core/hal.h" | #include "esphome/core/hal.h" | ||||||
| #include "esphome/core/helpers.h" | #include "esphome/core/helpers.h" | ||||||
| #include "esphome/core/log.h" | #include "esphome/core/log.h" | ||||||
| #include "esphome/components/sensor/sensor.h" |  | ||||||
| #include "esphome/components/i2c/i2c.h" |  | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace qmp6988 { | 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 */ | /* oversampling */ | ||||||
| enum QMP6988Oversampling { | enum QMP6988Oversampling : uint8_t { | ||||||
|   QMP6988_OVERSAMPLING_SKIPPED = 0x00, |   QMP6988_OVERSAMPLING_SKIPPED = 0x00, | ||||||
|   QMP6988_OVERSAMPLING_1X = 0x01, |   QMP6988_OVERSAMPLING_1X = 0x01, | ||||||
|   QMP6988_OVERSAMPLING_2X = 0x02, |   QMP6988_OVERSAMPLING_2X = 0x02, | ||||||
| @@ -30,7 +23,7 @@ enum QMP6988Oversampling { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| /* filter */ | /* filter */ | ||||||
| enum QMP6988IIRFilter { | enum QMP6988IIRFilter : uint8_t { | ||||||
|   QMP6988_IIR_FILTER_OFF = 0x00, |   QMP6988_IIR_FILTER_OFF = 0x00, | ||||||
|   QMP6988_IIR_FILTER_2X = 0x01, |   QMP6988_IIR_FILTER_2X = 0x01, | ||||||
|   QMP6988_IIR_FILTER_4X = 0x02, |   QMP6988_IIR_FILTER_4X = 0x02, | ||||||
| @@ -40,18 +33,18 @@ enum QMP6988IIRFilter { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| using qmp6988_cali_data_t = struct Qmp6988CaliData { | using qmp6988_cali_data_t = struct Qmp6988CaliData { | ||||||
|   QMP6988_S32_t COE_a0; |   int32_t COE_a0; | ||||||
|   QMP6988_S16_t COE_a1; |   int16_t COE_a1; | ||||||
|   QMP6988_S16_t COE_a2; |   int16_t COE_a2; | ||||||
|   QMP6988_S32_t COE_b00; |   int32_t COE_b00; | ||||||
|   QMP6988_S16_t COE_bt1; |   int16_t COE_bt1; | ||||||
|   QMP6988_S16_t COE_bt2; |   int16_t COE_bt2; | ||||||
|   QMP6988_S16_t COE_bp1; |   int16_t COE_bp1; | ||||||
|   QMP6988_S16_t COE_b11; |   int16_t COE_b11; | ||||||
|   QMP6988_S16_t COE_bp2; |   int16_t COE_bp2; | ||||||
|   QMP6988_S16_t COE_b12; |   int16_t COE_b12; | ||||||
|   QMP6988_S16_t COE_b21; |   int16_t COE_b21; | ||||||
|   QMP6988_S16_t COE_bp3; |   int16_t COE_bp3; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| using qmp6988_fk_data_t = struct Qmp6988FkData { | 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 { | using qmp6988_ik_data_t = struct Qmp6988IkData { | ||||||
|   QMP6988_S32_t a0, b00; |   int32_t a0, b00; | ||||||
|   QMP6988_S32_t a1, a2; |   int32_t a1, a2; | ||||||
|   QMP6988_S64_t bt1, bt2, bp1, b11, bp2, b12, b21, bp3; |   int64_t bt1, bt2, bp1, b11, bp2, b12, b21, bp3; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| using qmp6988_data_t = struct Qmp6988Data { | using qmp6988_data_t = struct Qmp6988Data { | ||||||
| @@ -77,17 +70,18 @@ using qmp6988_data_t = struct Qmp6988Data { | |||||||
|  |  | ||||||
| class QMP6988Component : public PollingComponent, public i2c::I2CDevice { | class QMP6988Component : public PollingComponent, public i2c::I2CDevice { | ||||||
|  public: |  public: | ||||||
|   void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } |   void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; } | ||||||
|   void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; } |   void set_pressure_sensor(sensor::Sensor *pressure_sensor) { this->pressure_sensor_ = pressure_sensor; } | ||||||
|  |  | ||||||
|   void setup() override; |   void setup() override; | ||||||
|   void dump_config() override; |   void dump_config() override; | ||||||
|   float get_setup_priority() const override; |  | ||||||
|   void update() override; |   void update() override; | ||||||
|  |  | ||||||
|   void set_iir_filter(QMP6988IIRFilter iirfilter); |   void set_iir_filter(QMP6988IIRFilter iirfilter) { this->iir_filter_ = iirfilter; } | ||||||
|   void set_temperature_oversampling(QMP6988Oversampling oversampling_t); |   void set_temperature_oversampling(QMP6988Oversampling oversampling_t) { | ||||||
|   void set_pressure_oversampling(QMP6988Oversampling oversampling_p); |     this->temperature_oversampling_ = oversampling_t; | ||||||
|  |   } | ||||||
|  |   void set_pressure_oversampling(QMP6988Oversampling oversampling_p) { this->pressure_oversampling_ = oversampling_p; } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   qmp6988_data_t qmp6988_data_; |   qmp6988_data_t qmp6988_data_; | ||||||
| @@ -102,14 +96,14 @@ class QMP6988Component : public PollingComponent, public i2c::I2CDevice { | |||||||
|   bool get_calibration_data_(); |   bool get_calibration_data_(); | ||||||
|   bool device_check_(); |   bool device_check_(); | ||||||
|   void set_power_mode_(uint8_t power_mode); |   void set_power_mode_(uint8_t power_mode); | ||||||
|   void write_oversampling_temperature_(unsigned char oversampling_t); |   void write_oversampling_temperature_(QMP6988Oversampling oversampling_t); | ||||||
|   void write_oversampling_pressure_(unsigned char oversampling_p); |   void write_oversampling_pressure_(QMP6988Oversampling oversampling_p); | ||||||
|   void write_filter_(unsigned char filter); |   void write_filter_(QMP6988IIRFilter filter); | ||||||
|   void calculate_pressure_(); |   void calculate_pressure_(); | ||||||
|   void calculate_altitude_(float pressure, float temp); |   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); |   int32_t get_compensated_pressure_(qmp6988_ik_data_t *ik, int32_t dp, int16_t tx); | ||||||
|   QMP6988_S16_t get_compensated_temperature_(qmp6988_ik_data_t *ik, QMP6988_S32_t dt); |   int16_t get_compensated_temperature_(qmp6988_ik_data_t *ik, int32_t dt); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace qmp6988 | }  // 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 |     # Lazy import to avoid circular imports | ||||||
|     from esphome.core.config import Device |     from esphome.core.config import Device | ||||||
|  |  | ||||||
|  |     if not value: | ||||||
|  |         return None | ||||||
|  |  | ||||||
|     return use_id(Device)(value) |     return use_id(Device)(value) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -77,8 +77,8 @@ async def setup_entity(var: MockObj, config: ConfigType, platform: str) -> None: | |||||||
|     """ |     """ | ||||||
|     # Get device info |     # Get device info | ||||||
|     device_name: str | None = None |     device_name: str | None = None | ||||||
|     if CONF_DEVICE_ID in config: |     device_id_obj: ID | None | ||||||
|         device_id_obj: ID = config[CONF_DEVICE_ID] |     if device_id_obj := config.get(CONF_DEVICE_ID): | ||||||
|         device: MockObj = await get_variable(device_id_obj) |         device: MockObj = await get_variable(device_id_obj) | ||||||
|         add(var.set_device(device)) |         add(var.set_device(device)) | ||||||
|         # Get device name for object ID calculation |         # 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 |         # Get device name if entity is on a sub-device | ||||||
|         device_name = None |         device_name = None | ||||||
|         device_id = ""  # Empty string for main device |         device_id = ""  # Empty string for main device | ||||||
|         if CONF_DEVICE_ID in config: |         device_id_obj: ID | None | ||||||
|             device_id_obj = config[CONF_DEVICE_ID] |         if device_id_obj := config.get(CONF_DEVICE_ID): | ||||||
|             device_name = device_id_obj.id |             device_name = device_id_obj.id | ||||||
|             # Use the device ID string directly for uniqueness |             # Use the device ID string directly for uniqueness | ||||||
|             device_id = device_id_obj.id |             device_id = device_id_obj.id | ||||||
|   | |||||||
| @@ -11,8 +11,8 @@ pyserial==3.5 | |||||||
| platformio==6.1.18  # When updating platformio, also update /docker/Dockerfile | platformio==6.1.18  # When updating platformio, also update /docker/Dockerfile | ||||||
| esptool==5.0.2 | esptool==5.0.2 | ||||||
| click==8.1.7 | click==8.1.7 | ||||||
| esphome-dashboard==20250514.0 | esphome-dashboard==20250814.0 | ||||||
| aioesphomeapi==38.2.1 | aioesphomeapi==39.0.0 | ||||||
| zeroconf==0.147.0 | zeroconf==0.147.0 | ||||||
| puremagic==1.30 | puremagic==1.30 | ||||||
| ruamel.yaml==0.18.14 # dashboard_import | 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": |     if event_name == "pull_request": | ||||||
|         pr_number = _get_pr_number_from_github_env() |         pr_number = _get_pr_number_from_github_env() | ||||||
|         if pr_number: |         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"] |             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) |     # For pushes (including squash-and-merge) | ||||||
|     elif event_name == "push": |     elif event_name == "push": | ||||||
|   | |||||||
| @@ -55,6 +55,12 @@ sensor: | |||||||
|     lambda: return 4.0; |     lambda: return 4.0; | ||||||
|     update_interval: 0.1s |     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 | # Switches with the same name on different devices to test device_id lookup | ||||||
| switch: | switch: | ||||||
|   # Switch with no device_id (defaults to 0) |   # Switch with no device_id (defaults to 0) | ||||||
| @@ -96,3 +102,23 @@ switch: | |||||||
|       - logger.log: "Turning on Test Switch on Motion Detector" |       - logger.log: "Turning on Test Switch on Motion Detector" | ||||||
|     turn_off_action: |     turn_off_action: | ||||||
|       - logger.log: "Turning off Test Switch on Motion Detector" |       - 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, |             "Temperature Sensor Reading": temp_sensor.device_id, | ||||||
|             "Motion Detector Status": motion_detector.device_id, |             "Motion Detector Status": motion_detector.device_id, | ||||||
|             "Smart Switch Power": smart_switch.device_id, |             "Smart Switch Power": smart_switch.device_id, | ||||||
|  |             "Living Room Sensor": 0,  # Main device | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         for entity in sensor_entities: |         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)" |             "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 |         # Wait for initial states to be received for all switches | ||||||
|         await asyncio.wait_for(initial_states_future, timeout=2.0) |         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 |         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( | def test_get_changed_files_github_actions_pull_request_no_pr_number( | ||||||
|     monkeypatch: MonkeyPatch, |     monkeypatch: MonkeyPatch, | ||||||
| ) -> None: | ) -> None: | ||||||
|   | |||||||
| @@ -689,3 +689,19 @@ def test_entity_duplicate_validator_internal_entities() -> None: | |||||||
|         Invalid, match=r"Duplicate sensor entity with name 'Temperature' found" |         Invalid, match=r"Duplicate sensor entity with name 'Temperature' found" | ||||||
|     ): |     ): | ||||||
|         validator(config4) |         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