1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-21 04:32:23 +01:00

Merge branch 'state_class_to_string_flash' into integration

This commit is contained in:
J. Nick Koston
2025-09-05 11:33:27 -05:00
6 changed files with 64 additions and 23 deletions

View File

@@ -39,18 +39,22 @@ ErrorCode I2CDevice::read_register16(uint16_t a_register, uint8_t *data, size_t
} }
ErrorCode I2CDevice::write_register(uint8_t a_register, const uint8_t *data, size_t len) const { ErrorCode I2CDevice::write_register(uint8_t a_register, const uint8_t *data, size_t len) const {
std::vector<uint8_t> v{}; SmallBufferWithHeapFallback<17> buffer_alloc; // Most I2C writes are <= 16 bytes
v.push_back(a_register); uint8_t *buffer = buffer_alloc.get(len + 1);
v.insert(v.end(), data, data + len);
return bus_->write_readv(this->address_, v.data(), v.size(), nullptr, 0); buffer[0] = a_register;
std::copy(data, data + len, buffer + 1);
return this->bus_->write_readv(this->address_, buffer, len + 1, nullptr, 0);
} }
ErrorCode I2CDevice::write_register16(uint16_t a_register, const uint8_t *data, size_t len) const { ErrorCode I2CDevice::write_register16(uint16_t a_register, const uint8_t *data, size_t len) const {
std::vector<uint8_t> v(len + 2); SmallBufferWithHeapFallback<18> buffer_alloc; // Most I2C writes are <= 16 bytes + 2 for register
v[0] = a_register >> 8; uint8_t *buffer = buffer_alloc.get(len + 2);
v[1] = a_register;
std::copy(data, data + len, v.begin() + 2); buffer[0] = a_register >> 8;
return bus_->write_readv(this->address_, v.data(), v.size(), nullptr, 0); buffer[1] = a_register;
std::copy(data, data + len, buffer + 2);
return this->bus_->write_readv(this->address_, buffer, len + 2, nullptr, 0);
} }
bool I2CDevice::read_bytes_16(uint8_t a_register, uint16_t *data, uint8_t len) { bool I2CDevice::read_bytes_16(uint8_t a_register, uint16_t *data, uint8_t len) {

View File

@@ -2,6 +2,7 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <memory>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -10,6 +11,22 @@
namespace esphome { namespace esphome {
namespace i2c { namespace i2c {
/// @brief Helper class for efficient buffer allocation - uses stack for small sizes, heap for large
template<size_t STACK_SIZE> class SmallBufferWithHeapFallback {
public:
uint8_t *get(size_t size) {
if (size <= STACK_SIZE) {
return this->stack_buffer_;
}
this->heap_buffer_ = std::unique_ptr<uint8_t[]>(new uint8_t[size]);
return this->heap_buffer_.get();
}
private:
uint8_t stack_buffer_[STACK_SIZE];
std::unique_ptr<uint8_t[]> heap_buffer_;
};
/// @brief Error codes returned by I2CBus and I2CDevice methods /// @brief Error codes returned by I2CBus and I2CDevice methods
enum ErrorCode { enum ErrorCode {
NO_ERROR = 0, ///< No error found during execution of method NO_ERROR = 0, ///< No error found during execution of method
@@ -74,14 +91,17 @@ class I2CBus {
for (size_t i = 0; i != count; i++) { for (size_t i = 0; i != count; i++) {
total_len += read_buffers[i].len; total_len += read_buffers[i].len;
} }
std::vector<uint8_t> buffer(total_len);
auto err = this->write_readv(address, nullptr, 0, buffer.data(), total_len); SmallBufferWithHeapFallback<128> buffer_alloc; // Most I2C reads are small
uint8_t *buffer = buffer_alloc.get(total_len);
auto err = this->write_readv(address, nullptr, 0, buffer, total_len);
if (err != ERROR_OK) if (err != ERROR_OK)
return err; return err;
size_t pos = 0; size_t pos = 0;
for (size_t i = 0; i != count; i++) { for (size_t i = 0; i != count; i++) {
if (read_buffers[i].len != 0) { if (read_buffers[i].len != 0) {
std::memcpy(read_buffers[i].data, buffer.data() + pos, read_buffers[i].len); std::memcpy(read_buffers[i].data, buffer + pos, read_buffers[i].len);
pos += read_buffers[i].len; pos += read_buffers[i].len;
} }
} }
@@ -91,11 +111,21 @@ class I2CBus {
ESPDEPRECATED("This method is deprecated and will be removed in ESPHome 2026.3.0. Use write_readv() instead.", ESPDEPRECATED("This method is deprecated and will be removed in ESPHome 2026.3.0. Use write_readv() instead.",
"2025.9.0") "2025.9.0")
ErrorCode writev(uint8_t address, const WriteBuffer *write_buffers, size_t count, bool stop = true) { ErrorCode writev(uint8_t address, const WriteBuffer *write_buffers, size_t count, bool stop = true) {
std::vector<uint8_t> buffer{}; size_t total_len = 0;
for (size_t i = 0; i != count; i++) { for (size_t i = 0; i != count; i++) {
buffer.insert(buffer.end(), write_buffers[i].data, write_buffers[i].data + write_buffers[i].len); total_len += write_buffers[i].len;
} }
return this->write_readv(address, buffer.data(), buffer.size(), nullptr, 0);
SmallBufferWithHeapFallback<128> buffer_alloc; // Most I2C writes are small
uint8_t *buffer = buffer_alloc.get(total_len);
size_t pos = 0;
for (size_t i = 0; i != count; i++) {
std::memcpy(buffer + pos, write_buffers[i].data, write_buffers[i].len);
pos += write_buffers[i].len;
}
return this->write_readv(address, buffer, total_len, nullptr, 0);
} }
protected: protected:

View File

@@ -58,8 +58,13 @@ void MQTTSensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon
if (this->sensor_->get_force_update()) if (this->sensor_->get_force_update())
root[MQTT_FORCE_UPDATE] = true; root[MQTT_FORCE_UPDATE] = true;
if (this->sensor_->get_state_class() != STATE_CLASS_NONE) if (this->sensor_->get_state_class() != STATE_CLASS_NONE) {
#ifdef USE_STORE_LOG_STR_IN_FLASH
root[MQTT_STATE_CLASS] = (const __FlashStringHelper *) state_class_to_string(this->sensor_->get_state_class());
#else
root[MQTT_STATE_CLASS] = state_class_to_string(this->sensor_->get_state_class()); root[MQTT_STATE_CLASS] = state_class_to_string(this->sensor_->get_state_class());
#endif
}
config.command_topic = false; config.command_topic = false;
} }

View File

@@ -38,6 +38,7 @@ void SEN5XComponent::setup() {
this->mark_failed(); this->mark_failed();
return; return;
} }
delay(20); // per datasheet
uint16_t raw_read_status; uint16_t raw_read_status;
if (!this->read_data(raw_read_status)) { if (!this->read_data(raw_read_status)) {

View File

@@ -17,7 +17,8 @@ void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *o
"%s State Class: '%s'\n" "%s State Class: '%s'\n"
"%s Unit of Measurement: '%s'\n" "%s Unit of Measurement: '%s'\n"
"%s Accuracy Decimals: %d", "%s Accuracy Decimals: %d",
prefix, type, obj->get_name().c_str(), prefix, state_class_to_string(obj->get_state_class()), prefix, prefix, type, obj->get_name().c_str(), prefix,
LOG_STR_ARG(state_class_to_string(obj->get_state_class())), prefix,
obj->get_unit_of_measurement_ref().c_str(), prefix, obj->get_accuracy_decimals()); obj->get_unit_of_measurement_ref().c_str(), prefix, obj->get_accuracy_decimals());
if (!obj->get_device_class_ref().empty()) { if (!obj->get_device_class_ref().empty()) {
@@ -33,17 +34,17 @@ void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *o
} }
} }
const char *state_class_to_string(StateClass state_class) { const LogString *state_class_to_string(StateClass state_class) {
switch (state_class) { switch (state_class) {
case STATE_CLASS_MEASUREMENT: case STATE_CLASS_MEASUREMENT:
return "measurement"; return LOG_STR("measurement");
case STATE_CLASS_TOTAL_INCREASING: case STATE_CLASS_TOTAL_INCREASING:
return "total_increasing"; return LOG_STR("total_increasing");
case STATE_CLASS_TOTAL: case STATE_CLASS_TOTAL:
return "total"; return LOG_STR("total");
case STATE_CLASS_NONE: case STATE_CLASS_NONE:
default: default:
return ""; return LOG_STR("");
} }
} }

View File

@@ -33,7 +33,7 @@ enum StateClass : uint8_t {
STATE_CLASS_TOTAL = 3, STATE_CLASS_TOTAL = 3,
}; };
const char *state_class_to_string(StateClass state_class); const LogString *state_class_to_string(StateClass state_class);
/** Base-class for all sensors. /** Base-class for all sensors.
* *