Merge remote-tracking branch 'origin/ota-sbo-fix' into integration

This commit is contained in:
J. Nick Koston
2026-03-18 11:10:31 -10:00
17 changed files with 88 additions and 68 deletions
+1 -1
View File
@@ -183,7 +183,7 @@ class BedjetCodec {
BedjetPacket packet_;
BedjetStatusPacket *status_packet_;
BedjetStatusPacket *status_packet_{nullptr};
BedjetStatusPacket buf_;
};
@@ -102,6 +102,10 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
break;
}
case ESP_GATTC_NOTIFY_EVT: {
if (param->notify.value_len == 0) {
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str());
break;
}
ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(),
param->notify.handle, param->notify.value[0]);
if (param->notify.handle != this->handle)
@@ -131,8 +135,10 @@ float BLESensor::parse_data_(uint8_t *value, uint16_t value_len) {
if (this->has_data_to_value_) {
std::vector<uint8_t> data(value, value + value_len);
return this->data_to_value_func_(data);
} else {
} else if (value_len > 0) {
return value[0];
} else {
return NAN;
}
}
@@ -104,6 +104,10 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
case ESP_GATTC_NOTIFY_EVT: {
if (param->notify.handle != this->handle)
break;
if (param->notify.value_len == 0) {
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str());
break;
}
ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(),
param->notify.handle, param->notify.value[0]);
this->publish_state(reinterpret_cast<const char *>(param->notify.value), param->notify.value_len);
@@ -110,7 +110,7 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp
TaskHandle_t speaker_task_handle_{nullptr};
EventGroupHandle_t event_group_{nullptr};
QueueHandle_t i2s_event_queue_;
QueueHandle_t i2s_event_queue_{nullptr};
std::weak_ptr<RingBuffer> audio_ring_buffer_;
+1 -1
View File
@@ -229,7 +229,7 @@ void Inkplate::eink_off_() {
this->oe_pin_->digital_write(false);
this->gmod_pin_->digital_write(false);
GPIO.out &= ~(this->get_data_pin_mask_() | (1 << this->cl_pin_->get_pin()) | (1 << this->le_pin_->get_pin()));
GPIO.out &= ~(this->get_data_pin_mask_() | (1UL << this->cl_pin_->get_pin()) | (1UL << this->le_pin_->get_pin()));
this->ckv_pin_->digital_write(false);
this->sph_pin_->digital_write(false);
this->spv_pin_->digital_write(false);
+10 -10
View File
@@ -152,16 +152,16 @@ class Inkplate : public display::DisplayBuffer, public i2c::I2CDevice {
size_t get_buffer_length_();
int get_data_pin_mask_() {
int data = 0;
data |= (1 << this->display_data_0_pin_->get_pin());
data |= (1 << this->display_data_1_pin_->get_pin());
data |= (1 << this->display_data_2_pin_->get_pin());
data |= (1 << this->display_data_3_pin_->get_pin());
data |= (1 << this->display_data_4_pin_->get_pin());
data |= (1 << this->display_data_5_pin_->get_pin());
data |= (1 << this->display_data_6_pin_->get_pin());
data |= (1 << this->display_data_7_pin_->get_pin());
uint32_t get_data_pin_mask_() {
uint32_t data = 0;
data |= (1UL << this->display_data_0_pin_->get_pin());
data |= (1UL << this->display_data_1_pin_->get_pin());
data |= (1UL << this->display_data_2_pin_->get_pin());
data |= (1UL << this->display_data_3_pin_->get_pin());
data |= (1UL << this->display_data_4_pin_->get_pin());
data |= (1UL << this->display_data_5_pin_->get_pin());
data |= (1UL << this->display_data_6_pin_->get_pin());
data |= (1UL << this->display_data_7_pin_->get_pin());
return data;
}
+15 -26
View File
@@ -455,12 +455,10 @@ void LD2412Component::handle_periodic_data_() {
}
#ifdef USE_NUMBER
std::function<void(void)> set_number_value(number::Number *n, float value) {
void set_number_value(number::Number *n, float value) {
if (n != nullptr && (!n->has_state() || n->state != value)) {
n->state = value;
return [n, value]() { n->publish_state(value); };
n->publish_state(value);
}
return []() {};
}
#endif
@@ -504,6 +502,9 @@ bool LD2412Component::handle_ack_data_() {
break;
case CMD_QUERY_VERSION: {
if (this->buffer_pos_ < 12 + sizeof(this->version_)) {
return false;
}
std::memcpy(this->version_, &this->buffer_data_[12], sizeof(this->version_));
char version_s[20];
ld24xx::format_version_str(this->version_, version_s);
@@ -596,13 +597,8 @@ bool LD2412Component::handle_ack_data_() {
case CMD_QUERY_MOTION_GATE_SENS: {
#ifdef USE_NUMBER
std::vector<std::function<void(void)>> updates;
updates.reserve(this->gate_still_threshold_numbers_.size());
for (size_t i = 0; i < this->gate_still_threshold_numbers_.size(); i++) {
updates.push_back(set_number_value(this->gate_move_threshold_numbers_[i], this->buffer_data_[10 + i]));
}
for (auto &update : updates) {
update();
for (size_t i = 0; i < this->gate_move_threshold_numbers_.size() && (10 + i) < this->buffer_pos_; i++) {
set_number_value(this->gate_move_threshold_numbers_[i], this->buffer_data_[10 + i]);
}
#endif
break;
@@ -610,13 +606,8 @@ bool LD2412Component::handle_ack_data_() {
case CMD_QUERY_STATIC_GATE_SENS: {
#ifdef USE_NUMBER
std::vector<std::function<void(void)>> updates;
updates.reserve(this->gate_still_threshold_numbers_.size());
for (size_t i = 0; i < this->gate_still_threshold_numbers_.size(); i++) {
updates.push_back(set_number_value(this->gate_still_threshold_numbers_[i], this->buffer_data_[10 + i]));
}
for (auto &update : updates) {
update();
for (size_t i = 0; i < this->gate_still_threshold_numbers_.size() && (10 + i) < this->buffer_pos_; i++) {
set_number_value(this->gate_still_threshold_numbers_[i], this->buffer_data_[10 + i]);
}
#endif
break;
@@ -625,20 +616,21 @@ bool LD2412Component::handle_ack_data_() {
case CMD_QUERY_BASIC_CONF: // Query parameters response
{
#ifdef USE_NUMBER
if (this->buffer_pos_ < 15) {
return false;
}
/*
Moving distance range: 9th byte
Still distance range: 10th byte
*/
std::vector<std::function<void(void)>> updates;
updates.push_back(set_number_value(this->min_distance_gate_number_, this->buffer_data_[10]));
updates.push_back(set_number_value(this->max_distance_gate_number_, this->buffer_data_[11] - 1));
set_number_value(this->min_distance_gate_number_, this->buffer_data_[10]);
set_number_value(this->max_distance_gate_number_, this->buffer_data_[11] - 1);
ESP_LOGV(TAG, "min_distance_gate_number_: %u, max_distance_gate_number_ %u", this->buffer_data_[10],
this->buffer_data_[11]);
/*
None Duration: 11~12th bytes
*/
updates.push_back(
set_number_value(this->timeout_number_, encode_uint16(this->buffer_data_[13], this->buffer_data_[12])));
set_number_value(this->timeout_number_, encode_uint16(this->buffer_data_[13], this->buffer_data_[12]));
ESP_LOGV(TAG, "timeout_number_: %u", encode_uint16(this->buffer_data_[13], this->buffer_data_[12]));
/*
Output pin configuration: 13th bytes
@@ -650,9 +642,6 @@ bool LD2412Component::handle_ack_data_() {
this->out_pin_level_select_->publish_state(out_pin_level_str);
}
#endif
for (auto &update : updates) {
update();
}
#endif
} break;
default:
+12 -8
View File
@@ -170,14 +170,18 @@ static uint8_t calc_checksum(void *data, size_t size) {
return checksum;
}
static int get_firmware_int(const char *version_string) {
std::string version_str = version_string;
if (version_str[0] == 'v') {
version_str.erase(0, 1);
static int32_t get_firmware_int(const char *version_string) {
// Convert "v1.5.4" -> 154 by skipping 'v' and '.', accumulating digits
const char *p = (*version_string == 'v') ? version_string + 1 : version_string;
int32_t result = 0;
for (; *p != '\0'; p++) {
if (*p == '.')
continue;
if (*p < '0' || *p > '9')
return 0;
result = result * 10 + (*p - '0');
}
version_str.erase(remove(version_str.begin(), version_str.end(), '.'), version_str.end());
int version_integer = stoi(version_str);
return version_integer;
return result;
}
float LD2420Component::get_setup_priority() const { return setup_priority::BUS; }
@@ -683,7 +687,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
retry = 0;
}
if (this->cmd_reply_.error > 0) {
this->handle_cmd_error(error);
this->handle_cmd_error(this->cmd_reply_.error);
}
}
return error;
+1 -1
View File
@@ -392,7 +392,7 @@ async def addressable_lambda_effect_to_code(config, effect_id):
"Rainbow",
{
cv.Optional(CONF_SPEED, default=10): cv.uint32_t,
cv.Optional(CONF_WIDTH, default=50): cv.uint32_t,
cv.Optional(CONF_WIDTH, default=50): cv.int_range(min=1, max=65535),
},
)
async def addressable_rainbow_effect_to_code(config, effect_id):
@@ -178,7 +178,7 @@ template<typename N> N mask_and_shift_by_rightbit(N data, uint32_t mask) {
return result;
}
for (size_t pos = 0; pos < sizeof(N) << 3; pos++) {
if ((mask & (1 << pos)) != 0)
if ((mask & (1UL << pos)) != 0)
return result >> pos;
}
return 0;
+13
View File
@@ -13,6 +13,19 @@ OTAGlobalCallback *get_global_ota_callback() {
return global_ota_callback;
}
void OTAComponent::notify_state_deferred_(OTAState state, float progress, uint8_t error) {
// Pack state, error, and progress into a single uint32_t so the lambda
// captures only [this, packed] (8 bytes) — fits in std::function SBO.
// Layout: [state:8][error:8][progress_fixed:16] where progress is 010000 (0.01% resolution)
static_assert(OTA_ERROR <= 0xFF, "OTAState must fit in 8 bits for packing");
uint32_t packed = (static_cast<uint32_t>(state) << 24) | (static_cast<uint32_t>(error) << 16) |
static_cast<uint16_t>(progress * 100.0f);
this->defer([this, packed]() {
this->notify_state_(static_cast<OTAState>(packed >> 24), static_cast<float>(packed & 0xFFFF) / 100.0f,
static_cast<uint8_t>(packed >> 16));
});
}
void OTAComponent::notify_state_(OTAState state, float progress, uint8_t error) {
for (auto *listener : this->state_listeners_) {
listener->on_ota_state(state, progress, error);
+1 -3
View File
@@ -73,9 +73,7 @@ class OTAComponent : public Component {
* This should be used by OTA implementations that run in separate tasks
* (like web_server OTA) to ensure listeners execute in the main loop.
*/
void notify_state_deferred_(OTAState state, float progress, uint8_t error) {
this->defer([this, state, progress, error]() { this->notify_state_(state, progress, error); });
}
void notify_state_deferred_(OTAState state, float progress, uint8_t error);
std::vector<OTAStateListener *> state_listeners_;
#endif
@@ -402,7 +402,7 @@ bool ShellyDimmer::handle_frame_() {
// Handle response.
switch (cmd) {
case SHELLY_DIMMER_PROTO_CMD_POLL: {
if (payload_len < 16) {
if (payload_len < 17) {
return false;
}
+2 -2
View File
@@ -156,9 +156,9 @@ void ST7789V::update() {
void ST7789V::set_model_str(const char *model_str) { this->model_str_ = model_str; }
void ST7789V::write_display_data() {
uint16_t x1 = this->offset_height_;
uint16_t x1 = this->offset_width_;
uint16_t x2 = x1 + get_width_internal() - 1;
uint16_t y1 = this->offset_width_;
uint16_t y1 = this->offset_height_;
uint16_t y2 = y1 + get_height_internal() - 1;
this->enable();
+16 -10
View File
@@ -48,8 +48,8 @@ void DeltaSolBSPlusSensor::handle_message(std::vector<uint8_t> &message) {
if (this->operating_hours2_sensor_ != nullptr)
this->operating_hours2_sensor_->publish_state(get_u16(message, 18));
if (this->heat_quantity_sensor_ != nullptr) {
this->heat_quantity_sensor_->publish_state(get_u16(message, 20) + get_u16(message, 22) * 1000 +
get_u16(message, 24) * 1000000);
this->heat_quantity_sensor_->publish_state(get_u16(message, 20) + get_u16(message, 22) * 1000.0f +
get_u16(message, 24) * 1000000.0f);
}
if (this->time_sensor_ != nullptr)
this->time_sensor_->publish_state(get_u16(message, 12));
@@ -130,8 +130,8 @@ void DeltaSolCSensor::handle_message(std::vector<uint8_t> &message) {
if (this->operating_hours2_sensor_ != nullptr)
this->operating_hours2_sensor_->publish_state(get_u16(message, 14));
if (this->heat_quantity_sensor_ != nullptr) {
this->heat_quantity_sensor_->publish_state(get_u16(message, 16) + get_u16(message, 18) * 1000 +
get_u16(message, 20) * 1000000);
this->heat_quantity_sensor_->publish_state(get_u16(message, 16) + get_u16(message, 18) * 1000.0f +
get_u16(message, 20) * 1000000.0f);
}
if (this->time_sensor_ != nullptr)
this->time_sensor_->publish_state(get_u16(message, 22));
@@ -162,8 +162,10 @@ void DeltaSolCS2Sensor::handle_message(std::vector<uint8_t> &message) {
this->pump_speed_sensor_->publish_state(message[12]);
if (this->operating_hours_sensor_ != nullptr)
this->operating_hours_sensor_->publish_state(get_u16(message, 14));
if (this->heat_quantity_sensor_ != nullptr)
this->heat_quantity_sensor_->publish_state((get_u16(message, 26) << 16) + get_u16(message, 24));
if (this->heat_quantity_sensor_ != nullptr) {
this->heat_quantity_sensor_->publish_state((static_cast<uint32_t>(get_u16(message, 26)) << 16) |
get_u16(message, 24));
}
if (this->version_sensor_ != nullptr)
this->version_sensor_->publish_state(get_u16(message, 28) * 0.01f);
}
@@ -204,8 +206,10 @@ void DeltaSolCS4Sensor::handle_message(std::vector<uint8_t> &message) {
this->operating_hours1_sensor_->publish_state(get_u16(message, 10));
if (this->operating_hours2_sensor_ != nullptr)
this->operating_hours2_sensor_->publish_state(get_u16(message, 14));
if (this->heat_quantity_sensor_ != nullptr)
this->heat_quantity_sensor_->publish_state((get_u16(message, 30) << 16) + get_u16(message, 28));
if (this->heat_quantity_sensor_ != nullptr) {
this->heat_quantity_sensor_->publish_state((static_cast<uint32_t>(get_u16(message, 30)) << 16) |
get_u16(message, 28));
}
if (this->time_sensor_ != nullptr)
this->time_sensor_->publish_state(get_u16(message, 22));
if (this->version_sensor_ != nullptr)
@@ -250,8 +254,10 @@ void DeltaSolCSPlusSensor::handle_message(std::vector<uint8_t> &message) {
this->operating_hours1_sensor_->publish_state(get_u16(message, 10));
if (this->operating_hours2_sensor_ != nullptr)
this->operating_hours2_sensor_->publish_state(get_u16(message, 14));
if (this->heat_quantity_sensor_ != nullptr)
this->heat_quantity_sensor_->publish_state((get_u16(message, 30) << 16) + get_u16(message, 28));
if (this->heat_quantity_sensor_ != nullptr) {
this->heat_quantity_sensor_->publish_state((static_cast<uint32_t>(get_u16(message, 30)) << 16) |
get_u16(message, 28));
}
if (this->time_sensor_ != nullptr)
this->time_sensor_->publish_state(get_u16(message, 22));
if (this->version_sensor_ != nullptr)
+1 -2
View File
@@ -67,8 +67,7 @@ void VBus::loop() {
}
septet_spread(this->buffer_.data(), 7, 6, this->buffer_[13]);
uint16_t id = (this->buffer_[8] << 8) + this->buffer_[7];
uint32_t value =
(this->buffer_[12] << 24) + (this->buffer_[11] << 16) + (this->buffer_[10] << 8) + this->buffer_[9];
uint32_t value = encode_uint32(this->buffer_[12], this->buffer_[11], this->buffer_[10], this->buffer_[9]);
ESP_LOGV(TAG, "P1 C%04x %04x->%04x: %04x %04" PRIx32 " (%" PRIu32 ")", this->command_, this->source_,
this->dest_, id, value, value);
} else if ((this->protocol_ == 0x10) && (this->buffer_.size() == 9)) {
@@ -266,6 +266,7 @@ void VL53L0XSensor::update() {
this->status_momentary_warning("update", 5000);
ESP_LOGW(TAG, "%s - update called before prior reading complete - initiated:%d waiting_for_interrupt:%d",
this->name_.c_str(), this->initiated_read_, this->waiting_for_interrupt_);
return;
}
// initiate single shot measurement