[zwave_proxy] Clear Home ID on USB modem disconnect (#15327)

This commit is contained in:
Keith Burzinski
2026-03-31 14:34:16 -05:00
committed by GitHub
parent 2449aa75af
commit 26b426bbff
4 changed files with 80 additions and 7 deletions
+69 -7
View File
@@ -22,6 +22,8 @@ static constexpr uint8_t ZWAVE_COMMAND_GET_NETWORK_IDS = 0x20;
static constexpr uint8_t ZWAVE_COMMAND_TYPE_RESPONSE = 0x01; // Response type field value
static constexpr uint8_t ZWAVE_MIN_GET_NETWORK_IDS_LENGTH = 9; // TYPE + CMD + HOME_ID(4) + NODE_ID + checksum
static constexpr uint32_t HOME_ID_TIMEOUT_MS = 100; // Timeout for waiting for home ID during setup
static constexpr uint32_t RECONNECT_DELAY_MS = 500; // Delay between home ID query attempts after reconnect
static constexpr uint8_t MAX_QUERY_RETRIES = 5; // Max attempts to query home ID after reconnect
static uint8_t calculate_frame_checksum(const uint8_t *data, uint8_t length) {
// Calculate Z-Wave frame checksum
@@ -38,7 +40,10 @@ ZWaveProxy::ZWaveProxy() { global_zwave_proxy = this; }
void ZWaveProxy::setup() {
this->setup_time_ = App.get_loop_component_start_time();
this->send_simple_command_(ZWAVE_COMMAND_GET_NETWORK_IDS);
this->was_connected_ = this->parent_->is_connected();
if (this->was_connected_) {
this->send_simple_command_(ZWAVE_COMMAND_GET_NETWORK_IDS);
}
}
float ZWaveProxy::get_setup_priority() const {
@@ -84,6 +89,14 @@ void ZWaveProxy::loop() {
this->api_connection_ = nullptr; // Unsubscribe if disconnected
}
const bool connected = this->parent_->is_connected();
if (this->was_connected_ != connected) {
this->on_connection_changed_(connected);
}
if (this->reconnect_time_ != 0) {
this->retry_home_id_query_();
}
this->process_uart_();
this->status_clear_warning();
}
@@ -167,6 +180,55 @@ void ZWaveProxy::zwave_proxy_request(api::APIConnection *api_connection, api::en
}
}
void ZWaveProxy::on_connection_changed_(bool connected) {
this->was_connected_ = connected;
if (connected) {
ESP_LOGD(TAG, "Modem reconnected");
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START;
this->buffer_index_ = 0;
this->last_response_ = 0;
this->in_bootloader_ = false;
// Defer the query — the modem needs time to initialize after power is applied
this->reconnect_time_ = App.get_loop_component_start_time();
this->query_retries_ = 0;
} else {
ESP_LOGW(TAG, "Modem disconnected");
this->clear_home_id_();
}
}
void ZWaveProxy::retry_home_id_query_() {
if (this->home_id_ready_) {
// Got the home ID, cancel remaining retries
this->reconnect_time_ = 0;
return;
}
if (App.get_loop_component_start_time() - this->reconnect_time_ <= RECONNECT_DELAY_MS) {
return; // Not yet time for next attempt
}
this->reconnect_time_ = App.get_loop_component_start_time(); // Reset timer for next retry
this->query_retries_++;
if (this->query_retries_ <= MAX_QUERY_RETRIES) {
ESP_LOGD(TAG, "Querying Home ID (attempt %u)", this->query_retries_);
this->send_simple_command_(ZWAVE_COMMAND_GET_NETWORK_IDS);
} else {
ESP_LOGW(TAG, "Failed to read Home ID after %u attempts", MAX_QUERY_RETRIES);
this->reconnect_time_ = 0;
}
}
void ZWaveProxy::clear_home_id_() {
static constexpr uint8_t ZERO_HOME_ID[ZWAVE_HOME_ID_SIZE] = {};
if (this->set_home_id_(ZERO_HOME_ID)) {
this->send_homeid_changed_msg_();
}
this->home_id_ready_ = false;
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START;
this->buffer_index_ = 0;
this->last_response_ = 0;
this->in_bootloader_ = false;
}
bool ZWaveProxy::set_home_id_(const uint8_t *new_home_id) {
if (std::memcmp(this->home_id_.data(), new_home_id, this->home_id_.size()) == 0) {
ESP_LOGV(TAG, "Home ID unchanged");
@@ -309,7 +371,7 @@ void ZWaveProxy::parse_start_(uint8_t byte) {
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START;
switch (byte) {
case ZWAVE_FRAME_TYPE_START:
ESP_LOGVV(TAG, "Received START");
ESP_LOGV(TAG, "Received START");
if (this->in_bootloader_) {
ESP_LOGD(TAG, "Exited bootloader mode");
this->in_bootloader_ = false;
@@ -318,7 +380,7 @@ void ZWaveProxy::parse_start_(uint8_t byte) {
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_LENGTH;
return;
case ZWAVE_FRAME_TYPE_BL_MENU:
ESP_LOGVV(TAG, "Received BL_MENU");
ESP_LOGV(TAG, "Received BL_MENU");
if (!this->in_bootloader_) {
ESP_LOGD(TAG, "Entered bootloader mode");
this->in_bootloader_ = true;
@@ -327,16 +389,16 @@ void ZWaveProxy::parse_start_(uint8_t byte) {
this->parsing_state_ = ZWAVE_PARSING_STATE_READ_BL_MENU;
return;
case ZWAVE_FRAME_TYPE_BL_BEGIN_UPLOAD:
ESP_LOGVV(TAG, "Received BL_BEGIN_UPLOAD");
ESP_LOGV(TAG, "Received BL_BEGIN_UPLOAD");
break;
case ZWAVE_FRAME_TYPE_ACK:
ESP_LOGVV(TAG, "Received ACK");
ESP_LOGV(TAG, "Received ACK");
break;
case ZWAVE_FRAME_TYPE_NAK:
ESP_LOGW(TAG, "Received NAK");
ESP_LOGV(TAG, "Received NAK");
break;
case ZWAVE_FRAME_TYPE_CAN:
ESP_LOGW(TAG, "Received CAN");
ESP_LOGV(TAG, "Received CAN");
break;
default:
ESP_LOGW(TAG, "Unrecognized START: 0x%02X", byte);