From 998a9264a19bdf75e8f233d95c3e5c270dc85427 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 20 Aug 2025 10:05:46 -0500 Subject: [PATCH 1/2] fix race --- .../display/pvvx_display.cpp | 49 +++++++++++++++++-- .../pvvx_mithermometer/display/pvvx_display.h | 2 + 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp b/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp index 4b6c11b332..5ec7296ffd 100644 --- a/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +++ b/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp @@ -46,10 +46,35 @@ void PVVXDisplay::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t } this->connection_established_ = true; this->char_handle_ = chr->handle; -#ifdef USE_TIME - this->sync_time_(); -#endif - this->display(); + + // Check if already paired - if not, writes will be deferred to next update cycle + if (this->parent_->is_paired()) { + ESP_LOGD(TAG, "[%s] Device is paired, writing immediately.", this->parent_->address_str().c_str()); + this->sync_time_and_display_(); + } else { + ESP_LOGD(TAG, "[%s] Device not paired yet, deferring writes until authentication completes.", + this->parent_->address_str().c_str()); + } + break; + } + default: + break; + } +} + +void PVVXDisplay::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { + switch (event) { + case ESP_GAP_BLE_AUTH_CMPL_EVT: { + if (!this->parent_->check_addr(param->ble_security.auth_cmpl.bd_addr)) + return; + + if (param->ble_security.auth_cmpl.success) { + ESP_LOGD(TAG, "[%s] Authentication successful, performing writes.", this->parent_->address_str().c_str()); + // Now that pairing is complete, perform the pending writes + this->sync_time_and_display_(); + } else { + ESP_LOGW(TAG, "[%s] Authentication failed.", this->parent_->address_str().c_str()); + } break; } default: @@ -81,6 +106,11 @@ void PVVXDisplay::display() { this->parent_->address_str().c_str()); return; } + // Check if authentication is required and not complete + if (!this->parent_->is_paired()) { + ESP_LOGD(TAG, "[%s] Waiting for pairing to complete before writing.", this->parent_->address_str().c_str()); + return; + } ESP_LOGD(TAG, "[%s] Send to display: bignum %d, smallnum: %d, cfg: 0x%02x, validity period: %u.", this->parent_->address_str().c_str(), this->bignum_, this->smallnum_, this->cfg_, this->validity_period_); uint8_t blk[8] = {}; @@ -109,6 +139,10 @@ void PVVXDisplay::send_to_setup_char_(uint8_t *blk, size_t size) { ESP_LOGW(TAG, "[%s] Not connected to BLE client.", this->parent_->address_str().c_str()); return; } + if (!this->parent_->is_paired()) { + ESP_LOGW(TAG, "[%s] Cannot write - authentication not complete.", this->parent_->address_str().c_str()); + return; + } auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_, size, blk, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE); @@ -127,6 +161,13 @@ void PVVXDisplay::delayed_disconnect_() { this->set_timeout("disconnect", this->disconnect_delay_ms_, [this]() { this->parent_->set_enabled(false); }); } +void PVVXDisplay::sync_time_and_display_() { +#ifdef USE_TIME + this->sync_time_(); +#endif + this->display(); +} + #ifdef USE_TIME void PVVXDisplay::sync_time_() { if (this->time_ == nullptr) diff --git a/esphome/components/pvvx_mithermometer/display/pvvx_display.h b/esphome/components/pvvx_mithermometer/display/pvvx_display.h index 9739362024..c7fc523420 100644 --- a/esphome/components/pvvx_mithermometer/display/pvvx_display.h +++ b/esphome/components/pvvx_mithermometer/display/pvvx_display.h @@ -43,6 +43,7 @@ class PVVXDisplay : public ble_client::BLEClientNode, public PollingComponent { void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override; + void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override; /// Set validity period of the display information in seconds (1..65535) void set_validity_period(uint16_t validity_period) { this->validity_period_ = validity_period; } @@ -112,6 +113,7 @@ class PVVXDisplay : public ble_client::BLEClientNode, public PollingComponent { void setcfgbit_(uint8_t bit, bool value); void send_to_setup_char_(uint8_t *blk, size_t size); void delayed_disconnect_(); + void sync_time_and_display_(); #ifdef USE_TIME void sync_time_(); time::RealTimeClock *time_{nullptr}; From c88f2eb4d1cfd89bad84ea48ecd818d2a027fc7a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 20 Aug 2025 11:38:07 -0500 Subject: [PATCH 2/2] reduce --- .../display/pvvx_display.cpp | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp b/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp index 5ec7296ffd..b6916ad68f 100644 --- a/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +++ b/esphome/components/pvvx_mithermometer/display/pvvx_display.cpp @@ -47,14 +47,11 @@ void PVVXDisplay::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t this->connection_established_ = true; this->char_handle_ = chr->handle; - // Check if already paired - if not, writes will be deferred to next update cycle - if (this->parent_->is_paired()) { - ESP_LOGD(TAG, "[%s] Device is paired, writing immediately.", this->parent_->address_str().c_str()); - this->sync_time_and_display_(); - } else { - ESP_LOGD(TAG, "[%s] Device not paired yet, deferring writes until authentication completes.", - this->parent_->address_str().c_str()); - } + // Attempt to write immediately + // For devices without security, this will work + // For devices with security that are already paired, this will work + // For devices that need pairing, the write will be retried after auth completes + this->sync_time_and_display_(); break; } default: @@ -106,11 +103,6 @@ void PVVXDisplay::display() { this->parent_->address_str().c_str()); return; } - // Check if authentication is required and not complete - if (!this->parent_->is_paired()) { - ESP_LOGD(TAG, "[%s] Waiting for pairing to complete before writing.", this->parent_->address_str().c_str()); - return; - } ESP_LOGD(TAG, "[%s] Send to display: bignum %d, smallnum: %d, cfg: 0x%02x, validity period: %u.", this->parent_->address_str().c_str(), this->bignum_, this->smallnum_, this->cfg_, this->validity_period_); uint8_t blk[8] = {}; @@ -139,10 +131,6 @@ void PVVXDisplay::send_to_setup_char_(uint8_t *blk, size_t size) { ESP_LOGW(TAG, "[%s] Not connected to BLE client.", this->parent_->address_str().c_str()); return; } - if (!this->parent_->is_paired()) { - ESP_LOGW(TAG, "[%s] Cannot write - authentication not complete.", this->parent_->address_str().c_str()); - return; - } auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_, size, blk, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);