mirror of
https://github.com/esphome/esphome.git
synced 2026-10-03 01:35:59 +00:00
[zwave_proxy] Clear Home ID on USB modem disconnect (#15327)
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user