mirror of
https://github.com/esphome/esphome.git
synced 2025-09-17 18:52:19 +01:00
Logging tweaks, enable relaying of bootloader messages
This commit is contained in:
@@ -1214,7 +1214,7 @@ void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetCon
|
|||||||
|
|
||||||
#ifdef USE_ZWAVE_PROXY
|
#ifdef USE_ZWAVE_PROXY
|
||||||
void APIConnection::zwave_proxy_frame(const ZWaveProxyFrame &msg) {
|
void APIConnection::zwave_proxy_frame(const ZWaveProxyFrame &msg) {
|
||||||
zwave_proxy::global_zwave_proxy->send_frame(msg.data);
|
zwave_proxy::global_zwave_proxy->send_frame(msg.data, msg.data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIConnection::zwave_proxy_subscribe(const ZWaveProxySubscribeRequest &msg) {
|
void APIConnection::zwave_proxy_subscribe(const ZWaveProxySubscribeRequest &msg) {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include "zwave_proxy.h"
|
#include "zwave_proxy.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace zwave_proxy {
|
namespace zwave_proxy {
|
||||||
@@ -11,9 +12,9 @@ ZWaveProxy::ZWaveProxy() { global_zwave_proxy = this; }
|
|||||||
|
|
||||||
void ZWaveProxy::loop() {
|
void ZWaveProxy::loop() {
|
||||||
if (this->response_handler_()) {
|
if (this->response_handler_()) {
|
||||||
// return; // If a response was handled, exit early to avoid a CAN
|
ESP_LOGV(TAG, "Handled late response");
|
||||||
}
|
}
|
||||||
if (this->api_connection_ != nullptr && !this->api_connection_->is_connection_setup()) {
|
if (this->api_connection_ != nullptr && (!this->api_connection_->is_connection_setup() || !api_is_connected())) {
|
||||||
ESP_LOGW(TAG, "Subscriber disconnected");
|
ESP_LOGW(TAG, "Subscriber disconnected");
|
||||||
this->api_connection_ = nullptr; // Unsubscribe if disconnected
|
this->api_connection_ = nullptr; // Unsubscribe if disconnected
|
||||||
}
|
}
|
||||||
@@ -21,14 +22,19 @@ void ZWaveProxy::loop() {
|
|||||||
while (this->available()) {
|
while (this->available()) {
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
if (!this->read_byte(&byte)) {
|
if (!this->read_byte(&byte)) {
|
||||||
this->status_set_warning("Failed reading from UART");
|
this->status_set_warning("UART read failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this->parse_byte_(byte)) {
|
if (this->parse_byte_(byte)) {
|
||||||
ESP_LOGD(TAG, "Sending to client: %s", YESNO(this->api_connection_ != nullptr));
|
ESP_LOGV(TAG, "Sending to client: %s", YESNO(this->api_connection_ != nullptr));
|
||||||
if (this->api_connection_ != nullptr) {
|
if (this->api_connection_ != nullptr) {
|
||||||
// minimize copying to reduce CPU overhead
|
// minimize copying to reduce CPU overhead
|
||||||
this->outgoing_proto_msg_.data_len = this->buffer_[0] == ZWAVE_FRAME_TYPE_START ? this->buffer_[1] + 2 : 1;
|
if (this->in_bootloader_) {
|
||||||
|
this->outgoing_proto_msg_.data_len = this->buffer_index_;
|
||||||
|
} else {
|
||||||
|
// If this is a data frame, use frame length indicator + 2 (for SoF + checksum), else assume 1 for ACK/NAK/CAN
|
||||||
|
this->outgoing_proto_msg_.data_len = this->buffer_[0] == ZWAVE_FRAME_TYPE_START ? this->buffer_[1] + 2 : 1;
|
||||||
|
}
|
||||||
std::memcpy(this->outgoing_proto_msg_.data, this->buffer_, this->outgoing_proto_msg_.data_len);
|
std::memcpy(this->outgoing_proto_msg_.data, this->buffer_, this->outgoing_proto_msg_.data_len);
|
||||||
this->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE);
|
this->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE);
|
||||||
}
|
}
|
||||||
@@ -56,18 +62,11 @@ void ZWaveProxy::unsubscribe_api_connection(api::APIConnection *api_connection)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ZWaveProxy::send_frame(const uint8_t *data, size_t length) {
|
void ZWaveProxy::send_frame(const uint8_t *data, size_t length) {
|
||||||
if (!length) {
|
|
||||||
if (data[0] == ZWAVE_FRAME_TYPE_START) {
|
|
||||||
length = data[1] + 2; // data[1] is payload length, not including SoF + checksum
|
|
||||||
} else {
|
|
||||||
length = 1; // assume ACK/NAK/CAN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (length == 1 && data[0] == this->last_response_) {
|
if (length == 1 && data[0] == this->last_response_) {
|
||||||
ESP_LOGW(TAG, "Skipping sending duplicate response: 0x%02X", data[0]);
|
ESP_LOGV(TAG, "Skipping sending duplicate response: 0x%02X", data[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ESP_LOGD(TAG, "Sending: %s", format_hex_pretty(data, length).c_str());
|
ESP_LOGVV(TAG, "Sending: %s", format_hex_pretty(data, length).c_str());
|
||||||
this->write_array(data, length);
|
this->write_array(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +83,7 @@ bool ZWaveProxy::parse_byte_(uint8_t byte) {
|
|||||||
this->parsing_state_ = ZWAVE_PARSING_STATE_SEND_NAK;
|
this->parsing_state_ = ZWAVE_PARSING_STATE_SEND_NAK;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ESP_LOGD(TAG, "Received LENGTH: %u", byte);
|
ESP_LOGVV(TAG, "Received LENGTH: %u", byte);
|
||||||
this->end_frame_after_ = this->buffer_index_ + byte;
|
this->end_frame_after_ = this->buffer_index_ + byte;
|
||||||
ESP_LOGVV(TAG, "Calculated EOF: %u", this->end_frame_after_);
|
ESP_LOGVV(TAG, "Calculated EOF: %u", this->end_frame_after_);
|
||||||
this->buffer_[this->buffer_index_++] = byte;
|
this->buffer_[this->buffer_index_++] = byte;
|
||||||
@@ -93,13 +92,13 @@ bool ZWaveProxy::parse_byte_(uint8_t byte) {
|
|||||||
break;
|
break;
|
||||||
case ZWAVE_PARSING_STATE_WAIT_TYPE:
|
case ZWAVE_PARSING_STATE_WAIT_TYPE:
|
||||||
this->buffer_[this->buffer_index_++] = byte;
|
this->buffer_[this->buffer_index_++] = byte;
|
||||||
ESP_LOGD(TAG, "Received TYPE: 0x%02X", byte);
|
ESP_LOGVV(TAG, "Received TYPE: 0x%02X", byte);
|
||||||
this->checksum_ ^= byte;
|
this->checksum_ ^= byte;
|
||||||
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_COMMAND_ID;
|
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_COMMAND_ID;
|
||||||
break;
|
break;
|
||||||
case ZWAVE_PARSING_STATE_WAIT_COMMAND_ID:
|
case ZWAVE_PARSING_STATE_WAIT_COMMAND_ID:
|
||||||
this->buffer_[this->buffer_index_++] = byte;
|
this->buffer_[this->buffer_index_++] = byte;
|
||||||
ESP_LOGD(TAG, "Received COMMAND ID: 0x%02X", byte);
|
ESP_LOGVV(TAG, "Received COMMAND ID: 0x%02X", byte);
|
||||||
this->checksum_ ^= byte;
|
this->checksum_ ^= byte;
|
||||||
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_PAYLOAD;
|
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_PAYLOAD;
|
||||||
break;
|
break;
|
||||||
@@ -113,23 +112,31 @@ bool ZWaveProxy::parse_byte_(uint8_t byte) {
|
|||||||
break;
|
break;
|
||||||
case ZWAVE_PARSING_STATE_WAIT_CHECKSUM:
|
case ZWAVE_PARSING_STATE_WAIT_CHECKSUM:
|
||||||
this->buffer_[this->buffer_index_++] = byte;
|
this->buffer_[this->buffer_index_++] = byte;
|
||||||
ESP_LOGD(TAG, "Received CHECKSUM: 0x%02X", byte);
|
ESP_LOGVV(TAG, "Received CHECKSUM: 0x%02X", byte);
|
||||||
ESP_LOGV(TAG, "Calculated CHECKSUM: 0x%02X", this->checksum_);
|
ESP_LOGV(TAG, "Calculated CHECKSUM: 0x%02X", this->checksum_);
|
||||||
if (this->checksum_ != byte) {
|
if (this->checksum_ != byte) {
|
||||||
ESP_LOGW(TAG, "Bad checksum: expected 0x%02X, got 0x%02X", this->checksum_, byte);
|
ESP_LOGW(TAG, "Bad checksum: expected 0x%02X, got 0x%02X", this->checksum_, byte);
|
||||||
this->parsing_state_ = ZWAVE_PARSING_STATE_SEND_NAK;
|
this->parsing_state_ = ZWAVE_PARSING_STATE_SEND_NAK;
|
||||||
} else {
|
} else {
|
||||||
this->parsing_state_ = ZWAVE_PARSING_STATE_SEND_ACK;
|
this->parsing_state_ = ZWAVE_PARSING_STATE_SEND_ACK;
|
||||||
ESP_LOGD(TAG, "Received frame: %s", format_hex_pretty(this->buffer_, this->buffer_index_).c_str());
|
ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(this->buffer_, this->buffer_index_).c_str());
|
||||||
frame_completed = true;
|
frame_completed = true;
|
||||||
}
|
}
|
||||||
this->response_handler_();
|
this->response_handler_();
|
||||||
break;
|
break;
|
||||||
|
case ZWAVE_PARSING_STATE_READ_BL_MENU:
|
||||||
|
this->buffer_[this->buffer_index_++] = byte;
|
||||||
|
if (!byte) {
|
||||||
|
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START;
|
||||||
|
frame_completed = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ZWAVE_PARSING_STATE_SEND_ACK:
|
case ZWAVE_PARSING_STATE_SEND_ACK:
|
||||||
case ZWAVE_PARSING_STATE_SEND_NAK:
|
case ZWAVE_PARSING_STATE_SEND_NAK:
|
||||||
break; // Should not happen, handled in loop()
|
break; // Should not happen, handled in loop()
|
||||||
default:
|
default:
|
||||||
ESP_LOGD(TAG, "Received unknown byte: 0x%02X", byte);
|
ESP_LOGW(TAG, "Bad parsing state; resetting");
|
||||||
|
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return frame_completed;
|
return frame_completed;
|
||||||
@@ -141,12 +148,28 @@ void ZWaveProxy::parse_start_(uint8_t byte) {
|
|||||||
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START;
|
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START;
|
||||||
switch (byte) {
|
switch (byte) {
|
||||||
case ZWAVE_FRAME_TYPE_START:
|
case ZWAVE_FRAME_TYPE_START:
|
||||||
ESP_LOGD(TAG, "Received START");
|
ESP_LOGVV(TAG, "Received START");
|
||||||
|
if (this->in_bootloader_) {
|
||||||
|
ESP_LOGD(TAG, "Exited bootloader mode");
|
||||||
|
this->in_bootloader_ = false;
|
||||||
|
}
|
||||||
this->buffer_[this->buffer_index_++] = byte;
|
this->buffer_[this->buffer_index_++] = byte;
|
||||||
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_LENGTH;
|
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_LENGTH;
|
||||||
return;
|
return;
|
||||||
|
case ZWAVE_FRAME_TYPE_BL_MENU:
|
||||||
|
ESP_LOGVV(TAG, "Received BL_MENU");
|
||||||
|
if (!this->in_bootloader_) {
|
||||||
|
ESP_LOGD(TAG, "Entered bootloader mode");
|
||||||
|
this->in_bootloader_ = true;
|
||||||
|
}
|
||||||
|
this->buffer_[this->buffer_index_++] = 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");
|
||||||
|
break;
|
||||||
case ZWAVE_FRAME_TYPE_ACK:
|
case ZWAVE_FRAME_TYPE_ACK:
|
||||||
ESP_LOGD(TAG, "Received ACK");
|
ESP_LOGVV(TAG, "Received ACK");
|
||||||
break;
|
break;
|
||||||
case ZWAVE_FRAME_TYPE_NAK:
|
case ZWAVE_FRAME_TYPE_NAK:
|
||||||
ESP_LOGW(TAG, "Received NAK");
|
ESP_LOGW(TAG, "Received NAK");
|
||||||
@@ -155,7 +178,7 @@ void ZWaveProxy::parse_start_(uint8_t byte) {
|
|||||||
ESP_LOGW(TAG, "Received CAN");
|
ESP_LOGW(TAG, "Received CAN");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ESP_LOGW(TAG, "Unexpected type: 0x%02X", byte);
|
ESP_LOGW(TAG, "Unrecognized START: 0x%02X", byte);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Forward response (ACK/NAK/CAN) back to client for processing
|
// Forward response (ACK/NAK/CAN) back to client for processing
|
||||||
@@ -181,8 +204,8 @@ bool ZWaveProxy::response_handler_() {
|
|||||||
return false; // No response handled
|
return false; // No response handled
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Sending %s (0x%02X)", this->last_response_ == ZWAVE_FRAME_TYPE_ACK ? "ACK" : "NAK/CAN",
|
ESP_LOGVV(TAG, "Sending %s (0x%02X)", this->last_response_ == ZWAVE_FRAME_TYPE_ACK ? "ACK" : "NAK/CAN",
|
||||||
this->last_response_);
|
this->last_response_);
|
||||||
this->write_byte(this->last_response_);
|
this->write_byte(this->last_response_);
|
||||||
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START;
|
this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START;
|
||||||
return true;
|
return true;
|
||||||
|
@@ -13,6 +13,8 @@ enum ZWaveResponseTypes : uint8_t {
|
|||||||
ZWAVE_FRAME_TYPE_CAN = 0x18,
|
ZWAVE_FRAME_TYPE_CAN = 0x18,
|
||||||
ZWAVE_FRAME_TYPE_NAK = 0x15,
|
ZWAVE_FRAME_TYPE_NAK = 0x15,
|
||||||
ZWAVE_FRAME_TYPE_START = 0x01,
|
ZWAVE_FRAME_TYPE_START = 0x01,
|
||||||
|
ZWAVE_FRAME_TYPE_BL_MENU = 0x0D,
|
||||||
|
ZWAVE_FRAME_TYPE_BL_BEGIN_UPLOAD = 0x43,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ZWaveParsingState : uint8_t {
|
enum ZWaveParsingState : uint8_t {
|
||||||
@@ -25,6 +27,7 @@ enum ZWaveParsingState : uint8_t {
|
|||||||
ZWAVE_PARSING_STATE_SEND_ACK,
|
ZWAVE_PARSING_STATE_SEND_ACK,
|
||||||
ZWAVE_PARSING_STATE_SEND_CAN,
|
ZWAVE_PARSING_STATE_SEND_CAN,
|
||||||
ZWAVE_PARSING_STATE_SEND_NAK,
|
ZWAVE_PARSING_STATE_SEND_NAK,
|
||||||
|
ZWAVE_PARSING_STATE_READ_BL_MENU,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ZWaveProxyFeature : uint32_t {
|
enum ZWaveProxyFeature : uint32_t {
|
||||||
@@ -44,7 +47,7 @@ class ZWaveProxy : public uart::UARTDevice, public Component {
|
|||||||
|
|
||||||
uint32_t get_feature_flags() const { return ZWaveProxyFeature::FEATURE_ZWAVE_PROXY_ENABLED; }
|
uint32_t get_feature_flags() const { return ZWaveProxyFeature::FEATURE_ZWAVE_PROXY_ENABLED; }
|
||||||
|
|
||||||
void send_frame(const uint8_t *data, size_t length = 0);
|
void send_frame(const uint8_t *data, size_t length);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool parse_byte_(uint8_t byte); // Returns true if frame parsing was completed (a frame is ready in the buffer)
|
bool parse_byte_(uint8_t byte); // Returns true if frame parsing was completed (a frame is ready in the buffer)
|
||||||
@@ -59,6 +62,7 @@ class ZWaveProxy : public uart::UARTDevice, public Component {
|
|||||||
uint8_t end_frame_after_{0}; // Payload reception ends after this index
|
uint8_t end_frame_after_{0}; // Payload reception ends after this index
|
||||||
uint8_t last_response_{0}; // Last response type sent
|
uint8_t last_response_{0}; // Last response type sent
|
||||||
ZWaveParsingState parsing_state_{ZWAVE_PARSING_STATE_WAIT_START};
|
ZWaveParsingState parsing_state_{ZWAVE_PARSING_STATE_WAIT_START};
|
||||||
|
bool in_bootloader_{false}; // True if the device is detected to be in bootloader mode
|
||||||
|
|
||||||
// Pre-allocated message - always ready to send
|
// Pre-allocated message - always ready to send
|
||||||
api::ZWaveProxyFrame outgoing_proto_msg_;
|
api::ZWaveProxyFrame outgoing_proto_msg_;
|
||||||
|
Reference in New Issue
Block a user