mirror of
https://github.com/esphome/esphome.git
synced 2025-09-13 16:52:18 +01:00
Merge branch 'dev' into binary_sensor_gpio_polling
This commit is contained in:
2
.github/workflows/ci-docker.yml
vendored
2
.github/workflows/ci-docker.yml
vendored
@@ -49,7 +49,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: "3.10"
|
python-version: "3.10"
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3.11.0
|
uses: docker/setup-buildx-action@v3.11.1
|
||||||
|
|
||||||
- name: Set TAG
|
- name: Set TAG
|
||||||
run: |
|
run: |
|
||||||
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -99,7 +99,7 @@ jobs:
|
|||||||
python-version: "3.10"
|
python-version: "3.10"
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3.11.0
|
uses: docker/setup-buildx-action@v3.11.1
|
||||||
|
|
||||||
- name: Log in to docker hub
|
- name: Log in to docker hub
|
||||||
uses: docker/login-action@v3.4.0
|
uses: docker/login-action@v3.4.0
|
||||||
@@ -178,7 +178,7 @@ jobs:
|
|||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3.11.0
|
uses: docker/setup-buildx-action@v3.11.1
|
||||||
|
|
||||||
- name: Log in to docker hub
|
- name: Log in to docker hub
|
||||||
if: matrix.registry == 'dockerhub'
|
if: matrix.registry == 'dockerhub'
|
||||||
|
@@ -193,14 +193,13 @@ void AcDimmer::setup() {
|
|||||||
setTimer1Callback(&timer_interrupt);
|
setTimer1Callback(&timer_interrupt);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
// 80 Divider -> 1 count=1µs
|
// timer frequency of 1mhz
|
||||||
dimmer_timer = timerBegin(0, 80, true);
|
dimmer_timer = timerBegin(1000000);
|
||||||
timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr, true);
|
timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr);
|
||||||
// For ESP32, we can't use dynamic interval calculation because the timerX functions
|
// For ESP32, we can't use dynamic interval calculation because the timerX functions
|
||||||
// are not callable from ISR (placed in flash storage).
|
// are not callable from ISR (placed in flash storage).
|
||||||
// Here we just use an interrupt firing every 50 µs.
|
// Here we just use an interrupt firing every 50 µs.
|
||||||
timerAlarmWrite(dimmer_timer, 50, true);
|
timerAlarm(dimmer_timer, 50, true, 0);
|
||||||
timerAlarmEnable(dimmer_timer);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void AcDimmer::write_state(float state) {
|
void AcDimmer::write_state(float state) {
|
||||||
|
@@ -61,8 +61,8 @@ void APIConnection::start() {
|
|||||||
APIError err = this->helper_->init();
|
APIError err = this->helper_->init();
|
||||||
if (err != APIError::OK) {
|
if (err != APIError::OK) {
|
||||||
on_fatal_error();
|
on_fatal_error();
|
||||||
ESP_LOGW(TAG, "%s: Helper init failed: %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
|
ESP_LOGW(TAG, "%s: Helper init failed: %s errno=%d", this->get_client_combined_info().c_str(),
|
||||||
errno);
|
api_error_to_str(err), errno);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->client_info_ = helper_->getpeername();
|
this->client_info_ = helper_->getpeername();
|
||||||
@@ -91,7 +91,7 @@ void APIConnection::loop() {
|
|||||||
// when network is disconnected force disconnect immediately
|
// when network is disconnected force disconnect immediately
|
||||||
// don't wait for timeout
|
// don't wait for timeout
|
||||||
this->on_fatal_error();
|
this->on_fatal_error();
|
||||||
ESP_LOGW(TAG, "%s: Network unavailable; disconnecting", this->client_combined_info_.c_str());
|
ESP_LOGW(TAG, "%s: Network unavailable; disconnecting", this->get_client_combined_info().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this->next_close_) {
|
if (this->next_close_) {
|
||||||
@@ -104,7 +104,7 @@ void APIConnection::loop() {
|
|||||||
APIError err = this->helper_->loop();
|
APIError err = this->helper_->loop();
|
||||||
if (err != APIError::OK) {
|
if (err != APIError::OK) {
|
||||||
on_fatal_error();
|
on_fatal_error();
|
||||||
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->client_combined_info_.c_str(),
|
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->get_client_combined_info().c_str(),
|
||||||
api_error_to_str(err), errno);
|
api_error_to_str(err), errno);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -118,12 +118,12 @@ void APIConnection::loop() {
|
|||||||
} else if (err != APIError::OK) {
|
} else if (err != APIError::OK) {
|
||||||
on_fatal_error();
|
on_fatal_error();
|
||||||
if (err == APIError::SOCKET_READ_FAILED && errno == ECONNRESET) {
|
if (err == APIError::SOCKET_READ_FAILED && errno == ECONNRESET) {
|
||||||
ESP_LOGW(TAG, "%s: Connection reset", this->client_combined_info_.c_str());
|
ESP_LOGW(TAG, "%s: Connection reset", this->get_client_combined_info().c_str());
|
||||||
} else if (err == APIError::CONNECTION_CLOSED) {
|
} else if (err == APIError::CONNECTION_CLOSED) {
|
||||||
ESP_LOGW(TAG, "%s: Connection closed", this->client_combined_info_.c_str());
|
ESP_LOGW(TAG, "%s: Connection closed", this->get_client_combined_info().c_str());
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "%s: Reading failed: %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
|
ESP_LOGW(TAG, "%s: Reading failed: %s errno=%d", this->get_client_combined_info().c_str(),
|
||||||
errno);
|
api_error_to_str(err), errno);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@@ -157,7 +157,7 @@ void APIConnection::loop() {
|
|||||||
// Disconnect if not responded within 2.5*keepalive
|
// Disconnect if not responded within 2.5*keepalive
|
||||||
if (now - this->last_traffic_ > (KEEPALIVE_TIMEOUT_MS * 5) / 2) {
|
if (now - this->last_traffic_ > (KEEPALIVE_TIMEOUT_MS * 5) / 2) {
|
||||||
on_fatal_error();
|
on_fatal_error();
|
||||||
ESP_LOGW(TAG, "%s is unresponsive; disconnecting", this->client_combined_info_.c_str());
|
ESP_LOGW(TAG, "%s is unresponsive; disconnecting", this->get_client_combined_info().c_str());
|
||||||
}
|
}
|
||||||
} else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS && now > this->next_ping_retry_) {
|
} else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS && now > this->next_ping_retry_) {
|
||||||
ESP_LOGVV(TAG, "Sending keepalive PING");
|
ESP_LOGVV(TAG, "Sending keepalive PING");
|
||||||
@@ -166,7 +166,7 @@ void APIConnection::loop() {
|
|||||||
this->next_ping_retry_ = now + ping_retry_interval;
|
this->next_ping_retry_ = now + ping_retry_interval;
|
||||||
this->ping_retries_++;
|
this->ping_retries_++;
|
||||||
std::string warn_str = str_sprintf("%s: Sending keepalive failed %u time(s);",
|
std::string warn_str = str_sprintf("%s: Sending keepalive failed %u time(s);",
|
||||||
this->client_combined_info_.c_str(), this->ping_retries_);
|
this->get_client_combined_info().c_str(), this->ping_retries_);
|
||||||
if (this->ping_retries_ >= max_ping_retries) {
|
if (this->ping_retries_ >= max_ping_retries) {
|
||||||
on_fatal_error();
|
on_fatal_error();
|
||||||
ESP_LOGE(TAG, "%s disconnecting", warn_str.c_str());
|
ESP_LOGE(TAG, "%s disconnecting", warn_str.c_str());
|
||||||
@@ -233,7 +233,7 @@ DisconnectResponse APIConnection::disconnect(const DisconnectRequest &msg) {
|
|||||||
// remote initiated disconnect_client
|
// remote initiated disconnect_client
|
||||||
// don't close yet, we still need to send the disconnect response
|
// don't close yet, we still need to send the disconnect response
|
||||||
// close will happen on next loop
|
// close will happen on next loop
|
||||||
ESP_LOGD(TAG, "%s disconnected", this->client_combined_info_.c_str());
|
ESP_LOGD(TAG, "%s disconnected", this->get_client_combined_info().c_str());
|
||||||
this->next_close_ = true;
|
this->next_close_ = true;
|
||||||
DisconnectResponse resp;
|
DisconnectResponse resp;
|
||||||
return resp;
|
return resp;
|
||||||
@@ -1544,8 +1544,7 @@ bool APIConnection::try_send_log_message(int level, const char *tag, const char
|
|||||||
HelloResponse APIConnection::hello(const HelloRequest &msg) {
|
HelloResponse APIConnection::hello(const HelloRequest &msg) {
|
||||||
this->client_info_ = msg.client_info;
|
this->client_info_ = msg.client_info;
|
||||||
this->client_peername_ = this->helper_->getpeername();
|
this->client_peername_ = this->helper_->getpeername();
|
||||||
this->client_combined_info_ = this->client_info_ + " (" + this->client_peername_ + ")";
|
this->helper_->set_log_info(this->get_client_combined_info());
|
||||||
this->helper_->set_log_info(this->client_combined_info_);
|
|
||||||
this->client_api_version_major_ = msg.api_version_major;
|
this->client_api_version_major_ = msg.api_version_major;
|
||||||
this->client_api_version_minor_ = msg.api_version_minor;
|
this->client_api_version_minor_ = msg.api_version_minor;
|
||||||
ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu32 ".%" PRIu32, this->client_info_.c_str(),
|
ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu32 ".%" PRIu32, this->client_info_.c_str(),
|
||||||
@@ -1567,7 +1566,7 @@ ConnectResponse APIConnection::connect(const ConnectRequest &msg) {
|
|||||||
// bool invalid_password = 1;
|
// bool invalid_password = 1;
|
||||||
resp.invalid_password = !correct;
|
resp.invalid_password = !correct;
|
||||||
if (correct) {
|
if (correct) {
|
||||||
ESP_LOGD(TAG, "%s connected", this->client_combined_info_.c_str());
|
ESP_LOGD(TAG, "%s connected", this->get_client_combined_info().c_str());
|
||||||
this->connection_state_ = ConnectionState::AUTHENTICATED;
|
this->connection_state_ = ConnectionState::AUTHENTICATED;
|
||||||
this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->client_peername_);
|
this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->client_peername_);
|
||||||
#ifdef USE_HOMEASSISTANT_TIME
|
#ifdef USE_HOMEASSISTANT_TIME
|
||||||
@@ -1673,7 +1672,7 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) {
|
|||||||
APIError err = this->helper_->loop();
|
APIError err = this->helper_->loop();
|
||||||
if (err != APIError::OK) {
|
if (err != APIError::OK) {
|
||||||
on_fatal_error();
|
on_fatal_error();
|
||||||
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->client_combined_info_.c_str(),
|
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->get_client_combined_info().c_str(),
|
||||||
api_error_to_str(err), errno);
|
api_error_to_str(err), errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1695,10 +1694,10 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint16_t message_type)
|
|||||||
if (err != APIError::OK) {
|
if (err != APIError::OK) {
|
||||||
on_fatal_error();
|
on_fatal_error();
|
||||||
if (err == APIError::SOCKET_WRITE_FAILED && errno == ECONNRESET) {
|
if (err == APIError::SOCKET_WRITE_FAILED && errno == ECONNRESET) {
|
||||||
ESP_LOGW(TAG, "%s: Connection reset", this->client_combined_info_.c_str());
|
ESP_LOGW(TAG, "%s: Connection reset", this->get_client_combined_info().c_str());
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "%s: Packet write failed %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
|
ESP_LOGW(TAG, "%s: Packet write failed %s errno=%d", this->get_client_combined_info().c_str(),
|
||||||
errno);
|
api_error_to_str(err), errno);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1707,11 +1706,11 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint16_t message_type)
|
|||||||
}
|
}
|
||||||
void APIConnection::on_unauthenticated_access() {
|
void APIConnection::on_unauthenticated_access() {
|
||||||
this->on_fatal_error();
|
this->on_fatal_error();
|
||||||
ESP_LOGD(TAG, "%s requested access without authentication", this->client_combined_info_.c_str());
|
ESP_LOGD(TAG, "%s requested access without authentication", this->get_client_combined_info().c_str());
|
||||||
}
|
}
|
||||||
void APIConnection::on_no_setup_connection() {
|
void APIConnection::on_no_setup_connection() {
|
||||||
this->on_fatal_error();
|
this->on_fatal_error();
|
||||||
ESP_LOGD(TAG, "%s requested access without full connection", this->client_combined_info_.c_str());
|
ESP_LOGD(TAG, "%s requested access without full connection", this->get_client_combined_info().c_str());
|
||||||
}
|
}
|
||||||
void APIConnection::on_fatal_error() {
|
void APIConnection::on_fatal_error() {
|
||||||
this->helper_->close();
|
this->helper_->close();
|
||||||
@@ -1860,10 +1859,10 @@ void APIConnection::process_batch_() {
|
|||||||
if (err != APIError::OK && err != APIError::WOULD_BLOCK) {
|
if (err != APIError::OK && err != APIError::WOULD_BLOCK) {
|
||||||
on_fatal_error();
|
on_fatal_error();
|
||||||
if (err == APIError::SOCKET_WRITE_FAILED && errno == ECONNRESET) {
|
if (err == APIError::SOCKET_WRITE_FAILED && errno == ECONNRESET) {
|
||||||
ESP_LOGW(TAG, "%s: Connection reset during batch write", this->client_combined_info_.c_str());
|
ESP_LOGW(TAG, "%s: Connection reset during batch write", this->get_client_combined_info().c_str());
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "%s: Batch write failed %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
|
ESP_LOGW(TAG, "%s: Batch write failed %s errno=%d", this->get_client_combined_info().c_str(),
|
||||||
errno);
|
api_error_to_str(err), errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -275,7 +275,13 @@ class APIConnection : public APIServerConnection {
|
|||||||
bool try_to_clear_buffer(bool log_out_of_space);
|
bool try_to_clear_buffer(bool log_out_of_space);
|
||||||
bool send_buffer(ProtoWriteBuffer buffer, uint16_t message_type) override;
|
bool send_buffer(ProtoWriteBuffer buffer, uint16_t message_type) override;
|
||||||
|
|
||||||
std::string get_client_combined_info() const { return this->client_combined_info_; }
|
std::string get_client_combined_info() const {
|
||||||
|
if (this->client_info_ == this->client_peername_) {
|
||||||
|
// Before Hello message, both are the same (just IP:port)
|
||||||
|
return this->client_info_;
|
||||||
|
}
|
||||||
|
return this->client_info_ + " (" + this->client_peername_ + ")";
|
||||||
|
}
|
||||||
|
|
||||||
// Buffer allocator methods for batch processing
|
// Buffer allocator methods for batch processing
|
||||||
ProtoWriteBuffer allocate_single_message_buffer(uint16_t size);
|
ProtoWriteBuffer allocate_single_message_buffer(uint16_t size);
|
||||||
@@ -432,37 +438,44 @@ class APIConnection : public APIServerConnection {
|
|||||||
// Helper function to get estimated message size for buffer pre-allocation
|
// Helper function to get estimated message size for buffer pre-allocation
|
||||||
static uint16_t get_estimated_message_size(uint16_t message_type);
|
static uint16_t get_estimated_message_size(uint16_t message_type);
|
||||||
|
|
||||||
enum class ConnectionState {
|
// Pointers first (4 bytes each, naturally aligned)
|
||||||
|
std::unique_ptr<APIFrameHelper> helper_;
|
||||||
|
APIServer *parent_;
|
||||||
|
|
||||||
|
// 4-byte aligned types
|
||||||
|
uint32_t last_traffic_;
|
||||||
|
uint32_t next_ping_retry_{0};
|
||||||
|
int state_subs_at_ = -1;
|
||||||
|
|
||||||
|
// Strings (12 bytes each on 32-bit)
|
||||||
|
std::string client_info_;
|
||||||
|
std::string client_peername_;
|
||||||
|
|
||||||
|
// 2-byte aligned types
|
||||||
|
uint16_t client_api_version_major_{0};
|
||||||
|
uint16_t client_api_version_minor_{0};
|
||||||
|
|
||||||
|
// Group all 1-byte types together to minimize padding
|
||||||
|
enum class ConnectionState : uint8_t {
|
||||||
WAITING_FOR_HELLO,
|
WAITING_FOR_HELLO,
|
||||||
CONNECTED,
|
CONNECTED,
|
||||||
AUTHENTICATED,
|
AUTHENTICATED,
|
||||||
} connection_state_{ConnectionState::WAITING_FOR_HELLO};
|
} connection_state_{ConnectionState::WAITING_FOR_HELLO};
|
||||||
|
uint8_t log_subscription_{ESPHOME_LOG_LEVEL_NONE};
|
||||||
bool remove_{false};
|
bool remove_{false};
|
||||||
|
|
||||||
std::unique_ptr<APIFrameHelper> helper_;
|
|
||||||
|
|
||||||
std::string client_info_;
|
|
||||||
std::string client_peername_;
|
|
||||||
std::string client_combined_info_;
|
|
||||||
uint32_t client_api_version_major_{0};
|
|
||||||
uint32_t client_api_version_minor_{0};
|
|
||||||
#ifdef USE_ESP32_CAMERA
|
|
||||||
esp32_camera::CameraImageReader image_reader_;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool state_subscription_{false};
|
bool state_subscription_{false};
|
||||||
int log_subscription_{ESPHOME_LOG_LEVEL_NONE};
|
|
||||||
uint32_t last_traffic_;
|
|
||||||
uint32_t next_ping_retry_{0};
|
|
||||||
uint8_t ping_retries_{0};
|
|
||||||
bool sent_ping_{false};
|
bool sent_ping_{false};
|
||||||
bool service_call_subscription_{false};
|
bool service_call_subscription_{false};
|
||||||
bool next_close_ = false;
|
bool next_close_ = false;
|
||||||
APIServer *parent_;
|
uint8_t ping_retries_{0};
|
||||||
|
// 8 bytes used, no padding needed
|
||||||
|
|
||||||
|
// Larger objects at the end
|
||||||
InitialStateIterator initial_state_iterator_;
|
InitialStateIterator initial_state_iterator_;
|
||||||
ListEntitiesIterator list_entities_iterator_;
|
ListEntitiesIterator list_entities_iterator_;
|
||||||
int state_subs_at_ = -1;
|
#ifdef USE_ESP32_CAMERA
|
||||||
|
esp32_camera::CameraImageReader image_reader_;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Function pointer type for message encoding
|
// Function pointer type for message encoding
|
||||||
using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size, bool is_single);
|
using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size, bool is_single);
|
||||||
|
@@ -125,38 +125,6 @@ class APIFrameHelper {
|
|||||||
const uint8_t *current_data() const { return data.data() + offset; }
|
const uint8_t *current_data() const { return data.data() + offset; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Queue of data buffers to be sent
|
|
||||||
std::deque<SendBuffer> tx_buf_;
|
|
||||||
|
|
||||||
// Common state enum for all frame helpers
|
|
||||||
// Note: Not all states are used by all implementations
|
|
||||||
// - INITIALIZE: Used by both Noise and Plaintext
|
|
||||||
// - CLIENT_HELLO, SERVER_HELLO, HANDSHAKE: Only used by Noise protocol
|
|
||||||
// - DATA: Used by both Noise and Plaintext
|
|
||||||
// - CLOSED: Used by both Noise and Plaintext
|
|
||||||
// - FAILED: Used by both Noise and Plaintext
|
|
||||||
// - EXPLICIT_REJECT: Only used by Noise protocol
|
|
||||||
enum class State {
|
|
||||||
INITIALIZE = 1,
|
|
||||||
CLIENT_HELLO = 2, // Noise only
|
|
||||||
SERVER_HELLO = 3, // Noise only
|
|
||||||
HANDSHAKE = 4, // Noise only
|
|
||||||
DATA = 5,
|
|
||||||
CLOSED = 6,
|
|
||||||
FAILED = 7,
|
|
||||||
EXPLICIT_REJECT = 8, // Noise only
|
|
||||||
};
|
|
||||||
|
|
||||||
// Current state of the frame helper
|
|
||||||
State state_{State::INITIALIZE};
|
|
||||||
|
|
||||||
// Helper name for logging
|
|
||||||
std::string info_;
|
|
||||||
|
|
||||||
// Socket for communication
|
|
||||||
socket::Socket *socket_{nullptr};
|
|
||||||
std::unique_ptr<socket::Socket> socket_owned_;
|
|
||||||
|
|
||||||
// Common implementation for writing raw data to socket
|
// Common implementation for writing raw data to socket
|
||||||
APIError write_raw_(const struct iovec *iov, int iovcnt);
|
APIError write_raw_(const struct iovec *iov, int iovcnt);
|
||||||
|
|
||||||
@@ -169,15 +137,41 @@ class APIFrameHelper {
|
|||||||
APIError write_raw_(const struct iovec *iov, int iovcnt, socket::Socket *socket, std::vector<uint8_t> &tx_buf,
|
APIError write_raw_(const struct iovec *iov, int iovcnt, socket::Socket *socket, std::vector<uint8_t> &tx_buf,
|
||||||
const std::string &info, StateEnum &state, StateEnum failed_state);
|
const std::string &info, StateEnum &state, StateEnum failed_state);
|
||||||
|
|
||||||
|
// Pointers first (4 bytes each)
|
||||||
|
socket::Socket *socket_{nullptr};
|
||||||
|
std::unique_ptr<socket::Socket> socket_owned_;
|
||||||
|
|
||||||
|
// Common state enum for all frame helpers
|
||||||
|
// Note: Not all states are used by all implementations
|
||||||
|
// - INITIALIZE: Used by both Noise and Plaintext
|
||||||
|
// - CLIENT_HELLO, SERVER_HELLO, HANDSHAKE: Only used by Noise protocol
|
||||||
|
// - DATA: Used by both Noise and Plaintext
|
||||||
|
// - CLOSED: Used by both Noise and Plaintext
|
||||||
|
// - FAILED: Used by both Noise and Plaintext
|
||||||
|
// - EXPLICIT_REJECT: Only used by Noise protocol
|
||||||
|
enum class State : uint8_t {
|
||||||
|
INITIALIZE = 1,
|
||||||
|
CLIENT_HELLO = 2, // Noise only
|
||||||
|
SERVER_HELLO = 3, // Noise only
|
||||||
|
HANDSHAKE = 4, // Noise only
|
||||||
|
DATA = 5,
|
||||||
|
CLOSED = 6,
|
||||||
|
FAILED = 7,
|
||||||
|
EXPLICIT_REJECT = 8, // Noise only
|
||||||
|
};
|
||||||
|
|
||||||
|
// Containers (size varies, but typically 12+ bytes on 32-bit)
|
||||||
|
std::deque<SendBuffer> tx_buf_;
|
||||||
|
std::string info_;
|
||||||
|
std::vector<struct iovec> reusable_iovs_;
|
||||||
|
std::vector<uint8_t> rx_buf_;
|
||||||
|
|
||||||
|
// Group smaller types together
|
||||||
|
uint16_t rx_buf_len_ = 0;
|
||||||
|
State state_{State::INITIALIZE};
|
||||||
uint8_t frame_header_padding_{0};
|
uint8_t frame_header_padding_{0};
|
||||||
uint8_t frame_footer_size_{0};
|
uint8_t frame_footer_size_{0};
|
||||||
|
// 5 bytes total, 3 bytes padding
|
||||||
// Reusable IOV array for write_protobuf_packets to avoid repeated allocations
|
|
||||||
std::vector<struct iovec> reusable_iovs_;
|
|
||||||
|
|
||||||
// Receive buffer for reading frame data
|
|
||||||
std::vector<uint8_t> rx_buf_;
|
|
||||||
uint16_t rx_buf_len_ = 0;
|
|
||||||
|
|
||||||
// Common initialization for both plaintext and noise protocols
|
// Common initialization for both plaintext and noise protocols
|
||||||
APIError init_common_();
|
APIError init_common_();
|
||||||
@@ -213,19 +207,28 @@ class APINoiseFrameHelper : public APIFrameHelper {
|
|||||||
APIError init_handshake_();
|
APIError init_handshake_();
|
||||||
APIError check_handshake_finished_();
|
APIError check_handshake_finished_();
|
||||||
void send_explicit_handshake_reject_(const std::string &reason);
|
void send_explicit_handshake_reject_(const std::string &reason);
|
||||||
|
|
||||||
|
// Pointers first (4 bytes each)
|
||||||
|
NoiseHandshakeState *handshake_{nullptr};
|
||||||
|
NoiseCipherState *send_cipher_{nullptr};
|
||||||
|
NoiseCipherState *recv_cipher_{nullptr};
|
||||||
|
|
||||||
|
// Shared pointer (8 bytes on 32-bit = 4 bytes control block pointer + 4 bytes object pointer)
|
||||||
|
std::shared_ptr<APINoiseContext> ctx_;
|
||||||
|
|
||||||
|
// Vector (12 bytes on 32-bit)
|
||||||
|
std::vector<uint8_t> prologue_;
|
||||||
|
|
||||||
|
// NoiseProtocolId (size depends on implementation)
|
||||||
|
NoiseProtocolId nid_;
|
||||||
|
|
||||||
|
// Group small types together
|
||||||
// Fixed-size header buffer for noise protocol:
|
// Fixed-size header buffer for noise protocol:
|
||||||
// 1 byte for indicator + 2 bytes for message size (16-bit value, not varint)
|
// 1 byte for indicator + 2 bytes for message size (16-bit value, not varint)
|
||||||
// Note: Maximum message size is UINT16_MAX (65535), with a limit of 128 bytes during handshake phase
|
// Note: Maximum message size is UINT16_MAX (65535), with a limit of 128 bytes during handshake phase
|
||||||
uint8_t rx_header_buf_[3];
|
uint8_t rx_header_buf_[3];
|
||||||
uint8_t rx_header_buf_len_ = 0;
|
uint8_t rx_header_buf_len_ = 0;
|
||||||
|
// 4 bytes total, no padding
|
||||||
std::vector<uint8_t> prologue_;
|
|
||||||
|
|
||||||
std::shared_ptr<APINoiseContext> ctx_;
|
|
||||||
NoiseHandshakeState *handshake_{nullptr};
|
|
||||||
NoiseCipherState *send_cipher_{nullptr};
|
|
||||||
NoiseCipherState *recv_cipher_{nullptr};
|
|
||||||
NoiseProtocolId nid_;
|
|
||||||
};
|
};
|
||||||
#endif // USE_API_NOISE
|
#endif // USE_API_NOISE
|
||||||
|
|
||||||
@@ -252,6 +255,12 @@ class APIPlaintextFrameHelper : public APIFrameHelper {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
APIError try_read_frame_(ParsedFrame *frame);
|
APIError try_read_frame_(ParsedFrame *frame);
|
||||||
|
|
||||||
|
// Group 2-byte aligned types
|
||||||
|
uint16_t rx_header_parsed_type_ = 0;
|
||||||
|
uint16_t rx_header_parsed_len_ = 0;
|
||||||
|
|
||||||
|
// Group 1-byte types together
|
||||||
// Fixed-size header buffer for plaintext protocol:
|
// Fixed-size header buffer for plaintext protocol:
|
||||||
// We now store the indicator byte + the two varints.
|
// We now store the indicator byte + the two varints.
|
||||||
// To match noise protocol's maximum message size (UINT16_MAX = 65535), we need:
|
// To match noise protocol's maximum message size (UINT16_MAX = 65535), we need:
|
||||||
@@ -263,8 +272,7 @@ class APIPlaintextFrameHelper : public APIFrameHelper {
|
|||||||
uint8_t rx_header_buf_[6]; // 1 byte indicator + 5 bytes for varints (3 for size + 2 for type)
|
uint8_t rx_header_buf_[6]; // 1 byte indicator + 5 bytes for varints (3 for size + 2 for type)
|
||||||
uint8_t rx_header_buf_pos_ = 0;
|
uint8_t rx_header_buf_pos_ = 0;
|
||||||
bool rx_header_parsed_ = false;
|
bool rx_header_parsed_ = false;
|
||||||
uint16_t rx_header_parsed_type_ = 0;
|
// 8 bytes total, no padding needed
|
||||||
uint16_t rx_header_parsed_len_ = 0;
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -797,28 +797,18 @@ void ConnectResponse::dump_to(std::string &out) const {
|
|||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void DisconnectRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void DisconnectRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void DisconnectRequest::dump_to(std::string &out) const { out.append("DisconnectRequest {}"); }
|
void DisconnectRequest::dump_to(std::string &out) const { out.append("DisconnectRequest {}"); }
|
||||||
#endif
|
#endif
|
||||||
void DisconnectResponse::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void DisconnectResponse::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void DisconnectResponse::dump_to(std::string &out) const { out.append("DisconnectResponse {}"); }
|
void DisconnectResponse::dump_to(std::string &out) const { out.append("DisconnectResponse {}"); }
|
||||||
#endif
|
#endif
|
||||||
void PingRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void PingRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void PingRequest::dump_to(std::string &out) const { out.append("PingRequest {}"); }
|
void PingRequest::dump_to(std::string &out) const { out.append("PingRequest {}"); }
|
||||||
#endif
|
#endif
|
||||||
void PingResponse::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void PingResponse::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void PingResponse::dump_to(std::string &out) const { out.append("PingResponse {}"); }
|
void PingResponse::dump_to(std::string &out) const { out.append("PingResponse {}"); }
|
||||||
#endif
|
#endif
|
||||||
void DeviceInfoRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void DeviceInfoRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void DeviceInfoRequest::dump_to(std::string &out) const { out.append("DeviceInfoRequest {}"); }
|
void DeviceInfoRequest::dump_to(std::string &out) const { out.append("DeviceInfoRequest {}"); }
|
||||||
#endif
|
#endif
|
||||||
@@ -1039,18 +1029,12 @@ void DeviceInfoResponse::dump_to(std::string &out) const {
|
|||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void ListEntitiesRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void ListEntitiesRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesRequest::dump_to(std::string &out) const { out.append("ListEntitiesRequest {}"); }
|
void ListEntitiesRequest::dump_to(std::string &out) const { out.append("ListEntitiesRequest {}"); }
|
||||||
#endif
|
#endif
|
||||||
void ListEntitiesDoneResponse::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void ListEntitiesDoneResponse::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesDoneResponse::dump_to(std::string &out) const { out.append("ListEntitiesDoneResponse {}"); }
|
void ListEntitiesDoneResponse::dump_to(std::string &out) const { out.append("ListEntitiesDoneResponse {}"); }
|
||||||
#endif
|
#endif
|
||||||
void SubscribeStatesRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void SubscribeStatesRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void SubscribeStatesRequest::dump_to(std::string &out) const { out.append("SubscribeStatesRequest {}"); }
|
void SubscribeStatesRequest::dump_to(std::string &out) const { out.append("SubscribeStatesRequest {}"); }
|
||||||
#endif
|
#endif
|
||||||
@@ -3371,8 +3355,6 @@ void NoiseEncryptionSetKeyResponse::dump_to(std::string &out) const {
|
|||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void SubscribeHomeassistantServicesRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void SubscribeHomeassistantServicesRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void SubscribeHomeassistantServicesRequest::dump_to(std::string &out) const {
|
void SubscribeHomeassistantServicesRequest::dump_to(std::string &out) const {
|
||||||
out.append("SubscribeHomeassistantServicesRequest {}");
|
out.append("SubscribeHomeassistantServicesRequest {}");
|
||||||
@@ -3498,8 +3480,6 @@ void HomeassistantServiceResponse::dump_to(std::string &out) const {
|
|||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void SubscribeHomeAssistantStatesRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void SubscribeHomeAssistantStatesRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void SubscribeHomeAssistantStatesRequest::dump_to(std::string &out) const {
|
void SubscribeHomeAssistantStatesRequest::dump_to(std::string &out) const {
|
||||||
out.append("SubscribeHomeAssistantStatesRequest {}");
|
out.append("SubscribeHomeAssistantStatesRequest {}");
|
||||||
@@ -3603,8 +3583,6 @@ void HomeAssistantStateResponse::dump_to(std::string &out) const {
|
|||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void GetTimeRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void GetTimeRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void GetTimeRequest::dump_to(std::string &out) const { out.append("GetTimeRequest {}"); }
|
void GetTimeRequest::dump_to(std::string &out) const { out.append("GetTimeRequest {}"); }
|
||||||
#endif
|
#endif
|
||||||
@@ -7499,8 +7477,6 @@ void BluetoothGATTNotifyDataResponse::dump_to(std::string &out) const {
|
|||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void SubscribeBluetoothConnectionsFreeRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void SubscribeBluetoothConnectionsFreeRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void SubscribeBluetoothConnectionsFreeRequest::dump_to(std::string &out) const {
|
void SubscribeBluetoothConnectionsFreeRequest::dump_to(std::string &out) const {
|
||||||
out.append("SubscribeBluetoothConnectionsFreeRequest {}");
|
out.append("SubscribeBluetoothConnectionsFreeRequest {}");
|
||||||
@@ -7784,8 +7760,6 @@ void BluetoothDeviceUnpairingResponse::dump_to(std::string &out) const {
|
|||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void UnsubscribeBluetoothLEAdvertisementsRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void UnsubscribeBluetoothLEAdvertisementsRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void UnsubscribeBluetoothLEAdvertisementsRequest::dump_to(std::string &out) const {
|
void UnsubscribeBluetoothLEAdvertisementsRequest::dump_to(std::string &out) const {
|
||||||
out.append("UnsubscribeBluetoothLEAdvertisementsRequest {}");
|
out.append("UnsubscribeBluetoothLEAdvertisementsRequest {}");
|
||||||
@@ -8451,8 +8425,6 @@ void VoiceAssistantWakeWord::dump_to(std::string &out) const {
|
|||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void VoiceAssistantConfigurationRequest::encode(ProtoWriteBuffer buffer) const {}
|
|
||||||
void VoiceAssistantConfigurationRequest::calculate_size(uint32_t &total_size) const {}
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void VoiceAssistantConfigurationRequest::dump_to(std::string &out) const {
|
void VoiceAssistantConfigurationRequest::dump_to(std::string &out) const {
|
||||||
out.append("VoiceAssistantConfigurationRequest {}");
|
out.append("VoiceAssistantConfigurationRequest {}");
|
||||||
|
@@ -357,8 +357,6 @@ class DisconnectRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "disconnect_request"; }
|
static constexpr const char *message_name() { return "disconnect_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -372,8 +370,6 @@ class DisconnectResponse : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "disconnect_response"; }
|
static constexpr const char *message_name() { return "disconnect_response"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -387,8 +383,6 @@ class PingRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "ping_request"; }
|
static constexpr const char *message_name() { return "ping_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -402,8 +396,6 @@ class PingResponse : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "ping_response"; }
|
static constexpr const char *message_name() { return "ping_response"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -417,8 +409,6 @@ class DeviceInfoRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "device_info_request"; }
|
static constexpr const char *message_name() { return "device_info_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -468,8 +458,6 @@ class ListEntitiesRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_request"; }
|
static constexpr const char *message_name() { return "list_entities_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -483,8 +471,6 @@ class ListEntitiesDoneResponse : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_done_response"; }
|
static constexpr const char *message_name() { return "list_entities_done_response"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -498,8 +484,6 @@ class SubscribeStatesRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "subscribe_states_request"; }
|
static constexpr const char *message_name() { return "subscribe_states_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -1011,8 +995,6 @@ class SubscribeHomeassistantServicesRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "subscribe_homeassistant_services_request"; }
|
static constexpr const char *message_name() { return "subscribe_homeassistant_services_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -1061,8 +1043,6 @@ class SubscribeHomeAssistantStatesRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "subscribe_home_assistant_states_request"; }
|
static constexpr const char *message_name() { return "subscribe_home_assistant_states_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -1115,8 +1095,6 @@ class GetTimeRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "get_time_request"; }
|
static constexpr const char *message_name() { return "get_time_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -2117,8 +2095,6 @@ class SubscribeBluetoothConnectionsFreeRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "subscribe_bluetooth_connections_free_request"; }
|
static constexpr const char *message_name() { return "subscribe_bluetooth_connections_free_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -2244,8 +2220,6 @@ class UnsubscribeBluetoothLEAdvertisementsRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "unsubscribe_bluetooth_le_advertisements_request"; }
|
static constexpr const char *message_name() { return "unsubscribe_bluetooth_le_advertisements_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
@@ -2512,8 +2486,6 @@ class VoiceAssistantConfigurationRequest : public ProtoMessage {
|
|||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "voice_assistant_configuration_request"; }
|
static constexpr const char *message_name() { return "voice_assistant_configuration_request"; }
|
||||||
#endif
|
#endif
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -620,545 +620,301 @@ void APIServerConnection::on_ping_request(const PingRequest &msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void APIServerConnection::on_device_info_request(const DeviceInfoRequest &msg) {
|
void APIServerConnection::on_device_info_request(const DeviceInfoRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_connection_setup_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DeviceInfoResponse ret = this->device_info(msg);
|
DeviceInfoResponse ret = this->device_info(msg);
|
||||||
if (!this->send_message(ret)) {
|
if (!this->send_message(ret)) {
|
||||||
this->on_fatal_error();
|
this->on_fatal_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void APIServerConnection::on_list_entities_request(const ListEntitiesRequest &msg) {
|
void APIServerConnection::on_list_entities_request(const ListEntitiesRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->list_entities(msg);
|
this->list_entities(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void APIServerConnection::on_subscribe_states_request(const SubscribeStatesRequest &msg) {
|
void APIServerConnection::on_subscribe_states_request(const SubscribeStatesRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->subscribe_states(msg);
|
this->subscribe_states(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void APIServerConnection::on_subscribe_logs_request(const SubscribeLogsRequest &msg) {
|
void APIServerConnection::on_subscribe_logs_request(const SubscribeLogsRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->subscribe_logs(msg);
|
this->subscribe_logs(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void APIServerConnection::on_subscribe_homeassistant_services_request(
|
void APIServerConnection::on_subscribe_homeassistant_services_request(
|
||||||
const SubscribeHomeassistantServicesRequest &msg) {
|
const SubscribeHomeassistantServicesRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->subscribe_homeassistant_services(msg);
|
this->subscribe_homeassistant_services(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void APIServerConnection::on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) {
|
void APIServerConnection::on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->subscribe_home_assistant_states(msg);
|
this->subscribe_home_assistant_states(msg);
|
||||||
}
|
}
|
||||||
void APIServerConnection::on_get_time_request(const GetTimeRequest &msg) {
|
|
||||||
if (!this->is_connection_setup()) {
|
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
void APIServerConnection::on_get_time_request(const GetTimeRequest &msg) {
|
||||||
|
if (this->check_connection_setup_()) {
|
||||||
GetTimeResponse ret = this->get_time(msg);
|
GetTimeResponse ret = this->get_time(msg);
|
||||||
if (!this->send_message(ret)) {
|
if (!this->send_message(ret)) {
|
||||||
this->on_fatal_error();
|
this->on_fatal_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void APIServerConnection::on_execute_service_request(const ExecuteServiceRequest &msg) {
|
void APIServerConnection::on_execute_service_request(const ExecuteServiceRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->execute_service(msg);
|
this->execute_service(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#ifdef USE_API_NOISE
|
#ifdef USE_API_NOISE
|
||||||
void APIServerConnection::on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) {
|
void APIServerConnection::on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
NoiseEncryptionSetKeyResponse ret = this->noise_encryption_set_key(msg);
|
NoiseEncryptionSetKeyResponse ret = this->noise_encryption_set_key(msg);
|
||||||
if (!this->send_message(ret)) {
|
if (!this->send_message(ret)) {
|
||||||
this->on_fatal_error();
|
this->on_fatal_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BUTTON
|
#ifdef USE_BUTTON
|
||||||
void APIServerConnection::on_button_command_request(const ButtonCommandRequest &msg) {
|
void APIServerConnection::on_button_command_request(const ButtonCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->button_command(msg);
|
this->button_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ESP32_CAMERA
|
#ifdef USE_ESP32_CAMERA
|
||||||
void APIServerConnection::on_camera_image_request(const CameraImageRequest &msg) {
|
void APIServerConnection::on_camera_image_request(const CameraImageRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->camera_image(msg);
|
this->camera_image(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_CLIMATE
|
#ifdef USE_CLIMATE
|
||||||
void APIServerConnection::on_climate_command_request(const ClimateCommandRequest &msg) {
|
void APIServerConnection::on_climate_command_request(const ClimateCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->climate_command(msg);
|
this->climate_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_COVER
|
#ifdef USE_COVER
|
||||||
void APIServerConnection::on_cover_command_request(const CoverCommandRequest &msg) {
|
void APIServerConnection::on_cover_command_request(const CoverCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->cover_command(msg);
|
this->cover_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_DATETIME_DATE
|
#ifdef USE_DATETIME_DATE
|
||||||
void APIServerConnection::on_date_command_request(const DateCommandRequest &msg) {
|
void APIServerConnection::on_date_command_request(const DateCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->date_command(msg);
|
this->date_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_DATETIME_DATETIME
|
#ifdef USE_DATETIME_DATETIME
|
||||||
void APIServerConnection::on_date_time_command_request(const DateTimeCommandRequest &msg) {
|
void APIServerConnection::on_date_time_command_request(const DateTimeCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->datetime_command(msg);
|
this->datetime_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_FAN
|
#ifdef USE_FAN
|
||||||
void APIServerConnection::on_fan_command_request(const FanCommandRequest &msg) {
|
void APIServerConnection::on_fan_command_request(const FanCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->fan_command(msg);
|
this->fan_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
void APIServerConnection::on_light_command_request(const LightCommandRequest &msg) {
|
void APIServerConnection::on_light_command_request(const LightCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->light_command(msg);
|
this->light_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_LOCK
|
#ifdef USE_LOCK
|
||||||
void APIServerConnection::on_lock_command_request(const LockCommandRequest &msg) {
|
void APIServerConnection::on_lock_command_request(const LockCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->lock_command(msg);
|
this->lock_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_MEDIA_PLAYER
|
#ifdef USE_MEDIA_PLAYER
|
||||||
void APIServerConnection::on_media_player_command_request(const MediaPlayerCommandRequest &msg) {
|
void APIServerConnection::on_media_player_command_request(const MediaPlayerCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->media_player_command(msg);
|
this->media_player_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_NUMBER
|
#ifdef USE_NUMBER
|
||||||
void APIServerConnection::on_number_command_request(const NumberCommandRequest &msg) {
|
void APIServerConnection::on_number_command_request(const NumberCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->number_command(msg);
|
this->number_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
void APIServerConnection::on_select_command_request(const SelectCommandRequest &msg) {
|
void APIServerConnection::on_select_command_request(const SelectCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->select_command(msg);
|
this->select_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_SIREN
|
#ifdef USE_SIREN
|
||||||
void APIServerConnection::on_siren_command_request(const SirenCommandRequest &msg) {
|
void APIServerConnection::on_siren_command_request(const SirenCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->siren_command(msg);
|
this->siren_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_SWITCH
|
#ifdef USE_SWITCH
|
||||||
void APIServerConnection::on_switch_command_request(const SwitchCommandRequest &msg) {
|
void APIServerConnection::on_switch_command_request(const SwitchCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->switch_command(msg);
|
this->switch_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_TEXT
|
#ifdef USE_TEXT
|
||||||
void APIServerConnection::on_text_command_request(const TextCommandRequest &msg) {
|
void APIServerConnection::on_text_command_request(const TextCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->text_command(msg);
|
this->text_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_DATETIME_TIME
|
#ifdef USE_DATETIME_TIME
|
||||||
void APIServerConnection::on_time_command_request(const TimeCommandRequest &msg) {
|
void APIServerConnection::on_time_command_request(const TimeCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->time_command(msg);
|
this->time_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_UPDATE
|
#ifdef USE_UPDATE
|
||||||
void APIServerConnection::on_update_command_request(const UpdateCommandRequest &msg) {
|
void APIServerConnection::on_update_command_request(const UpdateCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->update_command(msg);
|
this->update_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_VALVE
|
#ifdef USE_VALVE
|
||||||
void APIServerConnection::on_valve_command_request(const ValveCommandRequest &msg) {
|
void APIServerConnection::on_valve_command_request(const ValveCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->valve_command(msg);
|
this->valve_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request(
|
void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request(
|
||||||
const SubscribeBluetoothLEAdvertisementsRequest &msg) {
|
const SubscribeBluetoothLEAdvertisementsRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->subscribe_bluetooth_le_advertisements(msg);
|
this->subscribe_bluetooth_le_advertisements(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_bluetooth_device_request(const BluetoothDeviceRequest &msg) {
|
void APIServerConnection::on_bluetooth_device_request(const BluetoothDeviceRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->bluetooth_device_request(msg);
|
this->bluetooth_device_request(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) {
|
void APIServerConnection::on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->bluetooth_gatt_get_services(msg);
|
this->bluetooth_gatt_get_services(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) {
|
void APIServerConnection::on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->bluetooth_gatt_read(msg);
|
this->bluetooth_gatt_read(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) {
|
void APIServerConnection::on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->bluetooth_gatt_write(msg);
|
this->bluetooth_gatt_write(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) {
|
void APIServerConnection::on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->bluetooth_gatt_read_descriptor(msg);
|
this->bluetooth_gatt_read_descriptor(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) {
|
void APIServerConnection::on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->bluetooth_gatt_write_descriptor(msg);
|
this->bluetooth_gatt_write_descriptor(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) {
|
void APIServerConnection::on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->bluetooth_gatt_notify(msg);
|
this->bluetooth_gatt_notify(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_subscribe_bluetooth_connections_free_request(
|
void APIServerConnection::on_subscribe_bluetooth_connections_free_request(
|
||||||
const SubscribeBluetoothConnectionsFreeRequest &msg) {
|
const SubscribeBluetoothConnectionsFreeRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BluetoothConnectionsFreeResponse ret = this->subscribe_bluetooth_connections_free(msg);
|
BluetoothConnectionsFreeResponse ret = this->subscribe_bluetooth_connections_free(msg);
|
||||||
if (!this->send_message(ret)) {
|
if (!this->send_message(ret)) {
|
||||||
this->on_fatal_error();
|
this->on_fatal_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_unsubscribe_bluetooth_le_advertisements_request(
|
void APIServerConnection::on_unsubscribe_bluetooth_le_advertisements_request(
|
||||||
const UnsubscribeBluetoothLEAdvertisementsRequest &msg) {
|
const UnsubscribeBluetoothLEAdvertisementsRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->unsubscribe_bluetooth_le_advertisements(msg);
|
this->unsubscribe_bluetooth_le_advertisements(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
void APIServerConnection::on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) {
|
void APIServerConnection::on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->bluetooth_scanner_set_mode(msg);
|
this->bluetooth_scanner_set_mode(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_VOICE_ASSISTANT
|
#ifdef USE_VOICE_ASSISTANT
|
||||||
void APIServerConnection::on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) {
|
void APIServerConnection::on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->subscribe_voice_assistant(msg);
|
this->subscribe_voice_assistant(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_VOICE_ASSISTANT
|
#ifdef USE_VOICE_ASSISTANT
|
||||||
void APIServerConnection::on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) {
|
void APIServerConnection::on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
VoiceAssistantConfigurationResponse ret = this->voice_assistant_get_configuration(msg);
|
VoiceAssistantConfigurationResponse ret = this->voice_assistant_get_configuration(msg);
|
||||||
if (!this->send_message(ret)) {
|
if (!this->send_message(ret)) {
|
||||||
this->on_fatal_error();
|
this->on_fatal_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_VOICE_ASSISTANT
|
#ifdef USE_VOICE_ASSISTANT
|
||||||
void APIServerConnection::on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) {
|
void APIServerConnection::on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->voice_assistant_set_configuration(msg);
|
this->voice_assistant_set_configuration(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ALARM_CONTROL_PANEL
|
#ifdef USE_ALARM_CONTROL_PANEL
|
||||||
void APIServerConnection::on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) {
|
void APIServerConnection::on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) {
|
||||||
if (!this->is_connection_setup()) {
|
if (this->check_authenticated_()) {
|
||||||
this->on_no_setup_connection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this->is_authenticated()) {
|
|
||||||
this->on_unauthenticated_access();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->alarm_control_panel_command(msg);
|
this->alarm_control_panel_command(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
|
@@ -106,7 +106,7 @@ void APIServer::setup() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this->last_connected_ = millis();
|
this->last_connected_ = App.get_loop_component_start_time();
|
||||||
|
|
||||||
#ifdef USE_ESP32_CAMERA
|
#ifdef USE_ESP32_CAMERA
|
||||||
if (esp32_camera::global_esp32_camera != nullptr && !esp32_camera::global_esp32_camera->is_internal()) {
|
if (esp32_camera::global_esp32_camera != nullptr && !esp32_camera::global_esp32_camera->is_internal()) {
|
||||||
@@ -164,7 +164,7 @@ void APIServer::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->reboot_timeout_ != 0) {
|
if (this->reboot_timeout_ != 0) {
|
||||||
const uint32_t now = millis();
|
const uint32_t now = App.get_loop_component_start_time();
|
||||||
if (!this->is_connected()) {
|
if (!this->is_connected()) {
|
||||||
if (now - this->last_connected_ > this->reboot_timeout_) {
|
if (now - this->last_connected_ > this->reboot_timeout_) {
|
||||||
ESP_LOGE(TAG, "No client connected; rebooting");
|
ESP_LOGE(TAG, "No client connected; rebooting");
|
||||||
|
@@ -142,19 +142,27 @@ class APIServer : public Component, public Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool shutting_down_ = false;
|
// Pointers and pointer-like types first (4 bytes each)
|
||||||
std::unique_ptr<socket::Socket> socket_ = nullptr;
|
std::unique_ptr<socket::Socket> socket_ = nullptr;
|
||||||
uint16_t port_{6053};
|
Trigger<std::string, std::string> *client_connected_trigger_ = new Trigger<std::string, std::string>();
|
||||||
|
Trigger<std::string, std::string> *client_disconnected_trigger_ = new Trigger<std::string, std::string>();
|
||||||
|
|
||||||
|
// 4-byte aligned types
|
||||||
uint32_t reboot_timeout_{300000};
|
uint32_t reboot_timeout_{300000};
|
||||||
uint32_t batch_delay_{100};
|
uint32_t batch_delay_{100};
|
||||||
uint32_t last_connected_{0};
|
uint32_t last_connected_{0};
|
||||||
|
|
||||||
|
// Vectors and strings (12 bytes each on 32-bit)
|
||||||
std::vector<std::unique_ptr<APIConnection>> clients_;
|
std::vector<std::unique_ptr<APIConnection>> clients_;
|
||||||
std::string password_;
|
std::string password_;
|
||||||
std::vector<uint8_t> shared_write_buffer_; // Shared proto write buffer for all connections
|
std::vector<uint8_t> shared_write_buffer_; // Shared proto write buffer for all connections
|
||||||
std::vector<HomeAssistantStateSubscription> state_subs_;
|
std::vector<HomeAssistantStateSubscription> state_subs_;
|
||||||
std::vector<UserServiceDescriptor *> user_services_;
|
std::vector<UserServiceDescriptor *> user_services_;
|
||||||
Trigger<std::string, std::string> *client_connected_trigger_ = new Trigger<std::string, std::string>();
|
|
||||||
Trigger<std::string, std::string> *client_disconnected_trigger_ = new Trigger<std::string, std::string>();
|
// Group smaller types together
|
||||||
|
uint16_t port_{6053};
|
||||||
|
bool shutting_down_ = false;
|
||||||
|
// 3 bytes used, 1 byte padding
|
||||||
|
|
||||||
#ifdef USE_API_NOISE
|
#ifdef USE_API_NOISE
|
||||||
std::shared_ptr<APINoiseContext> noise_ctx_ = std::make_shared<APINoiseContext>();
|
std::shared_ptr<APINoiseContext> noise_ctx_ = std::make_shared<APINoiseContext>();
|
||||||
|
@@ -327,9 +327,11 @@ class ProtoWriteBuffer {
|
|||||||
class ProtoMessage {
|
class ProtoMessage {
|
||||||
public:
|
public:
|
||||||
virtual ~ProtoMessage() = default;
|
virtual ~ProtoMessage() = default;
|
||||||
virtual void encode(ProtoWriteBuffer buffer) const = 0;
|
// Default implementation for messages with no fields
|
||||||
|
virtual void encode(ProtoWriteBuffer buffer) const {}
|
||||||
void decode(const uint8_t *buffer, size_t length);
|
void decode(const uint8_t *buffer, size_t length);
|
||||||
virtual void calculate_size(uint32_t &total_size) const = 0;
|
// Default implementation for messages with no fields
|
||||||
|
virtual void calculate_size(uint32_t &total_size) const {}
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
std::string dump() const;
|
std::string dump() const;
|
||||||
virtual void dump_to(std::string &out) const = 0;
|
virtual void dump_to(std::string &out) const = 0;
|
||||||
@@ -377,6 +379,26 @@ class ProtoService {
|
|||||||
// Send the buffer
|
// Send the buffer
|
||||||
return this->send_buffer(buffer, message_type);
|
return this->send_buffer(buffer, message_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Authentication helper methods
|
||||||
|
bool check_connection_setup_() {
|
||||||
|
if (!this->is_connection_setup()) {
|
||||||
|
this->on_no_setup_connection();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_authenticated_() {
|
||||||
|
if (!this->check_connection_setup_()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this->is_authenticated()) {
|
||||||
|
this->on_unauthenticated_access();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
|
@@ -86,7 +86,7 @@ bool AudioTransferBuffer::reallocate(size_t new_buffer_size) {
|
|||||||
bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) {
|
bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) {
|
||||||
this->buffer_size_ = buffer_size;
|
this->buffer_size_ = buffer_size;
|
||||||
|
|
||||||
RAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
|
|
||||||
this->buffer_ = allocator.allocate(this->buffer_size_);
|
this->buffer_ = allocator.allocate(this->buffer_size_);
|
||||||
if (this->buffer_ == nullptr) {
|
if (this->buffer_ == nullptr) {
|
||||||
@@ -101,7 +101,7 @@ bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) {
|
|||||||
|
|
||||||
void AudioTransferBuffer::deallocate_buffer_() {
|
void AudioTransferBuffer::deallocate_buffer_() {
|
||||||
if (this->buffer_ != nullptr) {
|
if (this->buffer_ != nullptr) {
|
||||||
RAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
allocator.deallocate(this->buffer_, this->buffer_size_);
|
allocator.deallocate(this->buffer_, this->buffer_size_);
|
||||||
this->buffer_ = nullptr;
|
this->buffer_ = nullptr;
|
||||||
this->data_start_ = nullptr;
|
this->data_start_ = nullptr;
|
||||||
|
@@ -26,10 +26,17 @@ class BluetoothConnection : public esp32_ble_client::BLEClientBase {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class BluetoothProxy;
|
friend class BluetoothProxy;
|
||||||
bool seen_mtu_or_services_{false};
|
|
||||||
|
|
||||||
int16_t send_service_{-2};
|
// Memory optimized layout for 32-bit systems
|
||||||
|
// Group 1: Pointers (4 bytes each, naturally aligned)
|
||||||
BluetoothProxy *proxy_;
|
BluetoothProxy *proxy_;
|
||||||
|
|
||||||
|
// Group 2: 2-byte types
|
||||||
|
int16_t send_service_{-2}; // Needs to handle negative values and service count
|
||||||
|
|
||||||
|
// Group 3: 1-byte types
|
||||||
|
bool seen_mtu_or_services_{false};
|
||||||
|
// 1 byte used, 1 byte padding
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace bluetooth_proxy
|
} // namespace bluetooth_proxy
|
||||||
|
@@ -134,11 +134,17 @@ class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Com
|
|||||||
|
|
||||||
BluetoothConnection *get_connection_(uint64_t address, bool reserve);
|
BluetoothConnection *get_connection_(uint64_t address, bool reserve);
|
||||||
|
|
||||||
bool active_;
|
// Memory optimized layout for 32-bit systems
|
||||||
|
// Group 1: Pointers (4 bytes each, naturally aligned)
|
||||||
std::vector<BluetoothConnection *> connections_{};
|
|
||||||
api::APIConnection *api_connection_{nullptr};
|
api::APIConnection *api_connection_{nullptr};
|
||||||
|
|
||||||
|
// Group 2: Container types (typically 12 bytes on 32-bit)
|
||||||
|
std::vector<BluetoothConnection *> connections_{};
|
||||||
|
|
||||||
|
// Group 3: 1-byte types grouped together
|
||||||
|
bool active_;
|
||||||
bool raw_advertisements_{false};
|
bool raw_advertisements_{false};
|
||||||
|
// 2 bytes used, 2 bytes padding
|
||||||
};
|
};
|
||||||
|
|
||||||
extern BluetoothProxy *global_bluetooth_proxy; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
extern BluetoothProxy *global_bluetooth_proxy; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
|
@@ -41,6 +41,7 @@ async def to_code(config):
|
|||||||
|
|
||||||
if CORE.using_arduino:
|
if CORE.using_arduino:
|
||||||
if CORE.is_esp32:
|
if CORE.is_esp32:
|
||||||
|
cg.add_library("ESP32 Async UDP", None)
|
||||||
cg.add_library("DNSServer", None)
|
cg.add_library("DNSServer", None)
|
||||||
cg.add_library("WiFi", None)
|
cg.add_library("WiFi", None)
|
||||||
if CORE.is_esp8266:
|
if CORE.is_esp8266:
|
||||||
|
@@ -11,7 +11,7 @@ namespace display {
|
|||||||
static const char *const TAG = "display";
|
static const char *const TAG = "display";
|
||||||
|
|
||||||
void DisplayBuffer::init_internal_(uint32_t buffer_length) {
|
void DisplayBuffer::init_internal_(uint32_t buffer_length) {
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
this->buffer_ = allocator.allocate(buffer_length);
|
this->buffer_ = allocator.allocate(buffer_length);
|
||||||
if (this->buffer_ == nullptr) {
|
if (this->buffer_ == nullptr) {
|
||||||
ESP_LOGE(TAG, "Could not allocate buffer for display!");
|
ESP_LOGE(TAG, "Could not allocate buffer for display!");
|
||||||
|
@@ -132,6 +132,8 @@ def set_core_data(config):
|
|||||||
choices = CPU_FREQUENCIES[variant]
|
choices = CPU_FREQUENCIES[variant]
|
||||||
if "160MHZ" in choices:
|
if "160MHZ" in choices:
|
||||||
cpu_frequency = "160MHZ"
|
cpu_frequency = "160MHZ"
|
||||||
|
elif "360MHZ" in choices:
|
||||||
|
cpu_frequency = "360MHZ"
|
||||||
else:
|
else:
|
||||||
cpu_frequency = choices[-1]
|
cpu_frequency = choices[-1]
|
||||||
config[CONF_CPU_FREQUENCY] = cpu_frequency
|
config[CONF_CPU_FREQUENCY] = cpu_frequency
|
||||||
@@ -289,11 +291,8 @@ def add_extra_build_file(filename: str, path: str) -> bool:
|
|||||||
|
|
||||||
def _format_framework_arduino_version(ver: cv.Version) -> str:
|
def _format_framework_arduino_version(ver: cv.Version) -> str:
|
||||||
# format the given arduino (https://github.com/espressif/arduino-esp32/releases) version to
|
# format the given arduino (https://github.com/espressif/arduino-esp32/releases) version to
|
||||||
# a PIO platformio/framework-arduinoespressif32 value
|
# a PIO pioarduino/framework-arduinoespressif32 value
|
||||||
# List of package versions: https://api.registry.platformio.org/v3/packages/platformio/tool/framework-arduinoespressif32
|
return f"pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/{str(ver)}/esp32-{str(ver)}.zip"
|
||||||
if ver <= cv.Version(1, 0, 3):
|
|
||||||
return f"~2.{ver.major}{ver.minor:02d}{ver.patch:02d}.0"
|
|
||||||
return f"~3.{ver.major}{ver.minor:02d}{ver.patch:02d}.0"
|
|
||||||
|
|
||||||
|
|
||||||
def _format_framework_espidf_version(
|
def _format_framework_espidf_version(
|
||||||
@@ -317,12 +316,10 @@ def _format_framework_espidf_version(
|
|||||||
|
|
||||||
# The default/recommended arduino framework version
|
# The default/recommended arduino framework version
|
||||||
# - https://github.com/espressif/arduino-esp32/releases
|
# - https://github.com/espressif/arduino-esp32/releases
|
||||||
# - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-arduinoespressif32
|
RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 1, 3)
|
||||||
RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(2, 0, 5)
|
# The platform-espressif32 version to use for arduino frameworks
|
||||||
# The platformio/espressif32 version to use for arduino frameworks
|
# - https://github.com/pioarduino/platform-espressif32/releases
|
||||||
# - https://github.com/platformio/platform-espressif32/releases
|
ARDUINO_PLATFORM_VERSION = cv.Version(53, 3, 13)
|
||||||
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
|
|
||||||
ARDUINO_PLATFORM_VERSION = cv.Version(5, 4, 0)
|
|
||||||
|
|
||||||
# The default/recommended esp-idf framework version
|
# The default/recommended esp-idf framework version
|
||||||
# - https://github.com/espressif/esp-idf/releases
|
# - https://github.com/espressif/esp-idf/releases
|
||||||
@@ -365,8 +362,8 @@ SUPPORTED_PIOARDUINO_ESP_IDF_5X = [
|
|||||||
def _arduino_check_versions(value):
|
def _arduino_check_versions(value):
|
||||||
value = value.copy()
|
value = value.copy()
|
||||||
lookups = {
|
lookups = {
|
||||||
"dev": (cv.Version(2, 1, 0), "https://github.com/espressif/arduino-esp32.git"),
|
"dev": (cv.Version(3, 1, 3), "https://github.com/espressif/arduino-esp32.git"),
|
||||||
"latest": (cv.Version(2, 0, 9), None),
|
"latest": (cv.Version(3, 1, 3), None),
|
||||||
"recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None),
|
"recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,6 +385,10 @@ def _arduino_check_versions(value):
|
|||||||
CONF_PLATFORM_VERSION, _parse_platform_version(str(ARDUINO_PLATFORM_VERSION))
|
CONF_PLATFORM_VERSION, _parse_platform_version(str(ARDUINO_PLATFORM_VERSION))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if value[CONF_SOURCE].startswith("http"):
|
||||||
|
# prefix is necessary or platformio will complain with a cryptic error
|
||||||
|
value[CONF_SOURCE] = f"framework-arduinoespressif32@{value[CONF_SOURCE]}"
|
||||||
|
|
||||||
if version != RECOMMENDED_ARDUINO_FRAMEWORK_VERSION:
|
if version != RECOMMENDED_ARDUINO_FRAMEWORK_VERSION:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"The selected Arduino framework version is not the recommended one. "
|
"The selected Arduino framework version is not the recommended one. "
|
||||||
@@ -829,10 +830,7 @@ async def to_code(config):
|
|||||||
cg.add_platformio_option("framework", "arduino")
|
cg.add_platformio_option("framework", "arduino")
|
||||||
cg.add_build_flag("-DUSE_ARDUINO")
|
cg.add_build_flag("-DUSE_ARDUINO")
|
||||||
cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ARDUINO")
|
cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ARDUINO")
|
||||||
cg.add_platformio_option(
|
cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]])
|
||||||
"platform_packages",
|
|
||||||
[f"platformio/framework-arduinoespressif32@{conf[CONF_SOURCE]}"],
|
|
||||||
)
|
|
||||||
|
|
||||||
if CONF_PARTITIONS in config:
|
if CONF_PARTITIONS in config:
|
||||||
cg.add_platformio_option("board_build.partitions", config[CONF_PARTITIONS])
|
cg.add_platformio_option("board_build.partitions", config[CONF_PARTITIONS])
|
||||||
|
@@ -324,14 +324,18 @@ void ESP32BLE::loop() {
|
|||||||
}
|
}
|
||||||
case BLEEvent::GAP: {
|
case BLEEvent::GAP: {
|
||||||
esp_gap_ble_cb_event_t gap_event = ble_event->event_.gap.gap_event;
|
esp_gap_ble_cb_event_t gap_event = ble_event->event_.gap.gap_event;
|
||||||
if (gap_event == ESP_GAP_BLE_SCAN_RESULT_EVT) {
|
switch (gap_event) {
|
||||||
|
case ESP_GAP_BLE_SCAN_RESULT_EVT:
|
||||||
// Use the new scan event handler - no memcpy!
|
// Use the new scan event handler - no memcpy!
|
||||||
for (auto *scan_handler : this->gap_scan_event_handlers_) {
|
for (auto *scan_handler : this->gap_scan_event_handlers_) {
|
||||||
scan_handler->gap_scan_event_handler(ble_event->scan_result());
|
scan_handler->gap_scan_event_handler(ble_event->scan_result());
|
||||||
}
|
}
|
||||||
} else if (gap_event == ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT ||
|
break;
|
||||||
gap_event == ESP_GAP_BLE_SCAN_START_COMPLETE_EVT ||
|
|
||||||
gap_event == ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT) {
|
// Scan complete events
|
||||||
|
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
|
||||||
|
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
|
||||||
|
case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
|
||||||
// All three scan complete events have the same structure with just status
|
// All three scan complete events have the same structure with just status
|
||||||
// The scan_complete struct matches ESP-IDF's layout exactly, so this reinterpret_cast is safe
|
// The scan_complete struct matches ESP-IDF's layout exactly, so this reinterpret_cast is safe
|
||||||
// This is verified at compile-time by static_assert checks in ble_event.h
|
// This is verified at compile-time by static_assert checks in ble_event.h
|
||||||
@@ -341,6 +345,48 @@ void ESP32BLE::loop() {
|
|||||||
gap_handler->gap_event_handler(
|
gap_handler->gap_event_handler(
|
||||||
gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.scan_complete));
|
gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.scan_complete));
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Advertising complete events
|
||||||
|
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
|
||||||
|
case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
|
||||||
|
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
|
||||||
|
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
|
||||||
|
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
|
||||||
|
// All advertising complete events have the same structure with just status
|
||||||
|
ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
|
||||||
|
for (auto *gap_handler : this->gap_event_handlers_) {
|
||||||
|
gap_handler->gap_event_handler(
|
||||||
|
gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.adv_complete));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// RSSI complete event
|
||||||
|
case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
|
||||||
|
ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
|
||||||
|
for (auto *gap_handler : this->gap_event_handlers_) {
|
||||||
|
gap_handler->gap_event_handler(
|
||||||
|
gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.read_rssi_complete));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Security events
|
||||||
|
case ESP_GAP_BLE_AUTH_CMPL_EVT:
|
||||||
|
case ESP_GAP_BLE_SEC_REQ_EVT:
|
||||||
|
case ESP_GAP_BLE_PASSKEY_NOTIF_EVT:
|
||||||
|
case ESP_GAP_BLE_PASSKEY_REQ_EVT:
|
||||||
|
case ESP_GAP_BLE_NC_REQ_EVT:
|
||||||
|
ESP_LOGV(TAG, "gap_event_handler - %d", gap_event);
|
||||||
|
for (auto *gap_handler : this->gap_event_handlers_) {
|
||||||
|
gap_handler->gap_event_handler(
|
||||||
|
gap_event, reinterpret_cast<esp_ble_gap_cb_param_t *>(&ble_event->event_.gap.security));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Unknown/unhandled event
|
||||||
|
ESP_LOGW(TAG, "Unhandled GAP event type in loop: %d", gap_event);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -399,11 +445,26 @@ template void enqueue_ble_event(esp_gattc_cb_event_t, esp_gatt_if_t, esp_ble_gat
|
|||||||
|
|
||||||
void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
|
void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
// Only queue the 4 GAP events we actually handle
|
// Queue GAP events that components need to handle
|
||||||
|
// Scanning events - used by esp32_ble_tracker
|
||||||
case ESP_GAP_BLE_SCAN_RESULT_EVT:
|
case ESP_GAP_BLE_SCAN_RESULT_EVT:
|
||||||
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
|
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
|
||||||
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
|
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
|
||||||
case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
|
case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
|
||||||
|
// Advertising events - used by esp32_ble_beacon and esp32_ble server
|
||||||
|
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
|
||||||
|
case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
|
||||||
|
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
|
||||||
|
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
|
||||||
|
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
|
||||||
|
// Connection events - used by ble_client
|
||||||
|
case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
|
||||||
|
// Security events - used by ble_client and bluetooth_proxy
|
||||||
|
case ESP_GAP_BLE_AUTH_CMPL_EVT:
|
||||||
|
case ESP_GAP_BLE_SEC_REQ_EVT:
|
||||||
|
case ESP_GAP_BLE_PASSKEY_NOTIF_EVT:
|
||||||
|
case ESP_GAP_BLE_PASSKEY_REQ_EVT:
|
||||||
|
case ESP_GAP_BLE_NC_REQ_EVT:
|
||||||
enqueue_ble_event(event, param);
|
enqueue_ble_event(event, param);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -24,16 +24,45 @@ static_assert(sizeof(esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param) == si
|
|||||||
"ESP-IDF scan_stop_cmpl structure has unexpected size");
|
"ESP-IDF scan_stop_cmpl structure has unexpected size");
|
||||||
|
|
||||||
// Verify the status field is at offset 0 (first member)
|
// Verify the status field is at offset 0 (first member)
|
||||||
static_assert(offsetof(esp_ble_gap_cb_param_t, scan_param_cmpl.status) ==
|
static_assert(offsetof(esp_ble_gap_cb_param_t, scan_param_cmpl.status) == 0,
|
||||||
offsetof(esp_ble_gap_cb_param_t, scan_param_cmpl),
|
|
||||||
"status must be first member of scan_param_cmpl");
|
"status must be first member of scan_param_cmpl");
|
||||||
static_assert(offsetof(esp_ble_gap_cb_param_t, scan_start_cmpl.status) ==
|
static_assert(offsetof(esp_ble_gap_cb_param_t, scan_start_cmpl.status) == 0,
|
||||||
offsetof(esp_ble_gap_cb_param_t, scan_start_cmpl),
|
|
||||||
"status must be first member of scan_start_cmpl");
|
"status must be first member of scan_start_cmpl");
|
||||||
static_assert(offsetof(esp_ble_gap_cb_param_t, scan_stop_cmpl.status) ==
|
static_assert(offsetof(esp_ble_gap_cb_param_t, scan_stop_cmpl.status) == 0,
|
||||||
offsetof(esp_ble_gap_cb_param_t, scan_stop_cmpl),
|
|
||||||
"status must be first member of scan_stop_cmpl");
|
"status must be first member of scan_stop_cmpl");
|
||||||
|
|
||||||
|
// Compile-time verification for advertising complete events
|
||||||
|
static_assert(sizeof(esp_ble_gap_cb_param_t::ble_adv_data_cmpl_evt_param) == sizeof(esp_bt_status_t),
|
||||||
|
"ESP-IDF adv_data_cmpl structure has unexpected size");
|
||||||
|
static_assert(sizeof(esp_ble_gap_cb_param_t::ble_scan_rsp_data_cmpl_evt_param) == sizeof(esp_bt_status_t),
|
||||||
|
"ESP-IDF scan_rsp_data_cmpl structure has unexpected size");
|
||||||
|
static_assert(sizeof(esp_ble_gap_cb_param_t::ble_adv_data_raw_cmpl_evt_param) == sizeof(esp_bt_status_t),
|
||||||
|
"ESP-IDF adv_data_raw_cmpl structure has unexpected size");
|
||||||
|
static_assert(sizeof(esp_ble_gap_cb_param_t::ble_adv_start_cmpl_evt_param) == sizeof(esp_bt_status_t),
|
||||||
|
"ESP-IDF adv_start_cmpl structure has unexpected size");
|
||||||
|
static_assert(sizeof(esp_ble_gap_cb_param_t::ble_adv_stop_cmpl_evt_param) == sizeof(esp_bt_status_t),
|
||||||
|
"ESP-IDF adv_stop_cmpl structure has unexpected size");
|
||||||
|
|
||||||
|
// Verify the status field is at offset 0 for advertising events
|
||||||
|
static_assert(offsetof(esp_ble_gap_cb_param_t, adv_data_cmpl.status) == 0,
|
||||||
|
"status must be first member of adv_data_cmpl");
|
||||||
|
static_assert(offsetof(esp_ble_gap_cb_param_t, scan_rsp_data_cmpl.status) == 0,
|
||||||
|
"status must be first member of scan_rsp_data_cmpl");
|
||||||
|
static_assert(offsetof(esp_ble_gap_cb_param_t, adv_data_raw_cmpl.status) == 0,
|
||||||
|
"status must be first member of adv_data_raw_cmpl");
|
||||||
|
static_assert(offsetof(esp_ble_gap_cb_param_t, adv_start_cmpl.status) == 0,
|
||||||
|
"status must be first member of adv_start_cmpl");
|
||||||
|
static_assert(offsetof(esp_ble_gap_cb_param_t, adv_stop_cmpl.status) == 0,
|
||||||
|
"status must be first member of adv_stop_cmpl");
|
||||||
|
|
||||||
|
// Compile-time verification for RSSI complete event structure
|
||||||
|
static_assert(offsetof(esp_ble_gap_cb_param_t, read_rssi_cmpl.status) == 0,
|
||||||
|
"status must be first member of read_rssi_cmpl");
|
||||||
|
static_assert(offsetof(esp_ble_gap_cb_param_t, read_rssi_cmpl.rssi) == sizeof(esp_bt_status_t),
|
||||||
|
"rssi must immediately follow status in read_rssi_cmpl");
|
||||||
|
static_assert(offsetof(esp_ble_gap_cb_param_t, read_rssi_cmpl.remote_addr) == sizeof(esp_bt_status_t) + sizeof(int8_t),
|
||||||
|
"remote_addr must follow rssi in read_rssi_cmpl");
|
||||||
|
|
||||||
// Received GAP, GATTC and GATTS events are only queued, and get processed in the main loop().
|
// Received GAP, GATTC and GATTS events are only queued, and get processed in the main loop().
|
||||||
// This class stores each event with minimal memory usage.
|
// This class stores each event with minimal memory usage.
|
||||||
// GAP events (99% of traffic) don't have the vector overhead.
|
// GAP events (99% of traffic) don't have the vector overhead.
|
||||||
@@ -67,6 +96,17 @@ class BLEEvent {
|
|||||||
GATTS,
|
GATTS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Type definitions for cleaner method signatures
|
||||||
|
struct StatusOnlyData {
|
||||||
|
esp_bt_status_t status;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RSSICompleteData {
|
||||||
|
esp_bt_status_t status;
|
||||||
|
int8_t rssi;
|
||||||
|
esp_bd_addr_t remote_addr;
|
||||||
|
};
|
||||||
|
|
||||||
// Constructor for GAP events - no external allocations needed
|
// Constructor for GAP events - no external allocations needed
|
||||||
BLEEvent(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
|
BLEEvent(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
|
||||||
this->type_ = GAP;
|
this->type_ = GAP;
|
||||||
@@ -147,12 +187,21 @@ class BLEEvent {
|
|||||||
struct gap_event {
|
struct gap_event {
|
||||||
esp_gap_ble_cb_event_t gap_event;
|
esp_gap_ble_cb_event_t gap_event;
|
||||||
union {
|
union {
|
||||||
BLEScanResult scan_result; // 73 bytes
|
BLEScanResult scan_result; // 73 bytes - Used by: esp32_ble_tracker
|
||||||
// This matches ESP-IDF's scan complete event structures
|
// This matches ESP-IDF's scan complete event structures
|
||||||
// All three (scan_param_cmpl, scan_start_cmpl, scan_stop_cmpl) have identical layout
|
// All three (scan_param_cmpl, scan_start_cmpl, scan_stop_cmpl) have identical layout
|
||||||
struct {
|
// Used by: esp32_ble_tracker
|
||||||
esp_bt_status_t status;
|
StatusOnlyData scan_complete; // 1 byte
|
||||||
} scan_complete; // 1 byte
|
// Advertising complete events all have same structure
|
||||||
|
// Used by: esp32_ble_beacon, esp32_ble server components
|
||||||
|
// ADV_DATA_SET, SCAN_RSP_DATA_SET, ADV_DATA_RAW_SET, ADV_START, ADV_STOP
|
||||||
|
StatusOnlyData adv_complete; // 1 byte
|
||||||
|
// RSSI complete event
|
||||||
|
// Used by: ble_client (ble_rssi_sensor component)
|
||||||
|
RSSICompleteData read_rssi_complete; // 8 bytes
|
||||||
|
// Security events - we store the full security union
|
||||||
|
// Used by: ble_client (automation), bluetooth_proxy, esp32_ble_client
|
||||||
|
esp_ble_sec_t security; // Variable size, but fits within scan_result size
|
||||||
};
|
};
|
||||||
} gap; // 80 bytes total
|
} gap; // 80 bytes total
|
||||||
|
|
||||||
@@ -180,6 +229,9 @@ class BLEEvent {
|
|||||||
esp_gap_ble_cb_event_t gap_event_type() const { return event_.gap.gap_event; }
|
esp_gap_ble_cb_event_t gap_event_type() const { return event_.gap.gap_event; }
|
||||||
const BLEScanResult &scan_result() const { return event_.gap.scan_result; }
|
const BLEScanResult &scan_result() const { return event_.gap.scan_result; }
|
||||||
esp_bt_status_t scan_complete_status() const { return event_.gap.scan_complete.status; }
|
esp_bt_status_t scan_complete_status() const { return event_.gap.scan_complete.status; }
|
||||||
|
esp_bt_status_t adv_complete_status() const { return event_.gap.adv_complete.status; }
|
||||||
|
const RSSICompleteData &read_rssi_complete() const { return event_.gap.read_rssi_complete; }
|
||||||
|
const esp_ble_sec_t &security() const { return event_.gap.security; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Initialize GAP event data
|
// Initialize GAP event data
|
||||||
@@ -215,8 +267,47 @@ class BLEEvent {
|
|||||||
this->event_.gap.scan_complete.status = p->scan_stop_cmpl.status;
|
this->event_.gap.scan_complete.status = p->scan_stop_cmpl.status;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Advertising complete events - all have same structure with just status
|
||||||
|
// Used by: esp32_ble_beacon, esp32_ble server components
|
||||||
|
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
|
||||||
|
this->event_.gap.adv_complete.status = p->adv_data_cmpl.status;
|
||||||
|
break;
|
||||||
|
case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
|
||||||
|
this->event_.gap.adv_complete.status = p->scan_rsp_data_cmpl.status;
|
||||||
|
break;
|
||||||
|
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: // Used by: esp32_ble_beacon
|
||||||
|
this->event_.gap.adv_complete.status = p->adv_data_raw_cmpl.status;
|
||||||
|
break;
|
||||||
|
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: // Used by: esp32_ble_beacon
|
||||||
|
this->event_.gap.adv_complete.status = p->adv_start_cmpl.status;
|
||||||
|
break;
|
||||||
|
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: // Used by: esp32_ble_beacon
|
||||||
|
this->event_.gap.adv_complete.status = p->adv_stop_cmpl.status;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// RSSI complete event
|
||||||
|
// Used by: ble_client (ble_rssi_sensor)
|
||||||
|
case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
|
||||||
|
this->event_.gap.read_rssi_complete.status = p->read_rssi_cmpl.status;
|
||||||
|
this->event_.gap.read_rssi_complete.rssi = p->read_rssi_cmpl.rssi;
|
||||||
|
memcpy(this->event_.gap.read_rssi_complete.remote_addr, p->read_rssi_cmpl.remote_addr, sizeof(esp_bd_addr_t));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Security events - copy the entire security union
|
||||||
|
// Used by: ble_client, bluetooth_proxy, esp32_ble_client
|
||||||
|
case ESP_GAP_BLE_AUTH_CMPL_EVT: // Used by: bluetooth_proxy, esp32_ble_client
|
||||||
|
case ESP_GAP_BLE_SEC_REQ_EVT: // Used by: esp32_ble_client
|
||||||
|
case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: // Used by: ble_client automation
|
||||||
|
case ESP_GAP_BLE_PASSKEY_REQ_EVT: // Used by: ble_client automation
|
||||||
|
case ESP_GAP_BLE_NC_REQ_EVT: // Used by: ble_client automation
|
||||||
|
memcpy(&this->event_.gap.security, &p->ble_security, sizeof(esp_ble_sec_t));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// We only handle 4 GAP event types, others are dropped
|
// We only store data for GAP events that components currently use
|
||||||
|
// Unknown events still get queued and logged in ble.cpp:375 as
|
||||||
|
// "Unhandled GAP event type in loop" - this helps identify new events
|
||||||
|
// that components might need in the future
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,6 +386,13 @@ class BLEEvent {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Verify the gap_event struct hasn't grown beyond expected size
|
||||||
|
// The gap member in the union should be 80 bytes (including the gap_event enum)
|
||||||
|
static_assert(sizeof(decltype(((BLEEvent *) nullptr)->event_.gap)) <= 80, "gap_event struct has grown beyond 80 bytes");
|
||||||
|
|
||||||
|
// Verify esp_ble_sec_t fits within our union
|
||||||
|
static_assert(sizeof(esp_ble_sec_t) <= 73, "esp_ble_sec_t is larger than BLEScanResult");
|
||||||
|
|
||||||
// BLEEvent total size: 84 bytes (80 byte union + 1 byte type + 3 bytes padding)
|
// BLEEvent total size: 84 bytes (80 byte union + 1 byte type + 3 bytes padding)
|
||||||
|
|
||||||
} // namespace esp32_ble
|
} // namespace esp32_ble
|
||||||
|
@@ -96,21 +96,34 @@ class BLEClientBase : public espbt::ESPBTClient, public Component {
|
|||||||
void set_state(espbt::ClientState st) override;
|
void set_state(espbt::ClientState st) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int gattc_if_;
|
// Memory optimized layout for 32-bit systems
|
||||||
esp_bd_addr_t remote_bda_;
|
// Group 1: 8-byte types
|
||||||
esp_ble_addr_type_t remote_addr_type_{BLE_ADDR_TYPE_PUBLIC};
|
|
||||||
uint16_t conn_id_{UNSET_CONN_ID};
|
|
||||||
uint64_t address_{0};
|
uint64_t address_{0};
|
||||||
bool auto_connect_{false};
|
|
||||||
|
// Group 2: Container types (grouped for memory optimization)
|
||||||
std::string address_str_{};
|
std::string address_str_{};
|
||||||
uint8_t connection_index_;
|
|
||||||
int16_t service_count_{0};
|
|
||||||
uint16_t mtu_{23};
|
|
||||||
bool paired_{false};
|
|
||||||
espbt::ConnectionType connection_type_{espbt::ConnectionType::V1};
|
|
||||||
std::vector<BLEService *> services_;
|
std::vector<BLEService *> services_;
|
||||||
|
|
||||||
|
// Group 3: 4-byte types
|
||||||
|
int gattc_if_;
|
||||||
esp_gatt_status_t status_{ESP_GATT_OK};
|
esp_gatt_status_t status_{ESP_GATT_OK};
|
||||||
|
|
||||||
|
// Group 4: Arrays (6 bytes)
|
||||||
|
esp_bd_addr_t remote_bda_;
|
||||||
|
|
||||||
|
// Group 5: 2-byte types
|
||||||
|
uint16_t conn_id_{UNSET_CONN_ID};
|
||||||
|
uint16_t mtu_{23};
|
||||||
|
|
||||||
|
// Group 6: 1-byte types and small enums
|
||||||
|
esp_ble_addr_type_t remote_addr_type_{BLE_ADDR_TYPE_PUBLIC};
|
||||||
|
espbt::ConnectionType connection_type_{espbt::ConnectionType::V1};
|
||||||
|
uint8_t connection_index_;
|
||||||
|
uint8_t service_count_{0}; // ESP32 has max handles < 255, typical devices have < 50 services
|
||||||
|
bool auto_connect_{false};
|
||||||
|
bool paired_{false};
|
||||||
|
// 6 bytes used, 2 bytes padding
|
||||||
|
|
||||||
void log_event_(const char *name);
|
void log_event_(const char *name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -122,10 +122,10 @@ void ESP32BLETracker::loop() {
|
|||||||
// Consumer side: This runs in the main loop thread
|
// Consumer side: This runs in the main loop thread
|
||||||
if (this->scanner_state_ == ScannerState::RUNNING) {
|
if (this->scanner_state_ == ScannerState::RUNNING) {
|
||||||
// Load our own index with relaxed ordering (we're the only writer)
|
// Load our own index with relaxed ordering (we're the only writer)
|
||||||
size_t read_idx = this->ring_read_index_.load(std::memory_order_relaxed);
|
uint8_t read_idx = this->ring_read_index_.load(std::memory_order_relaxed);
|
||||||
|
|
||||||
// Load producer's index with acquire to see their latest writes
|
// Load producer's index with acquire to see their latest writes
|
||||||
size_t write_idx = this->ring_write_index_.load(std::memory_order_acquire);
|
uint8_t write_idx = this->ring_write_index_.load(std::memory_order_acquire);
|
||||||
|
|
||||||
while (read_idx != write_idx) {
|
while (read_idx != write_idx) {
|
||||||
// Process one result at a time directly from ring buffer
|
// Process one result at a time directly from ring buffer
|
||||||
@@ -409,11 +409,11 @@ void ESP32BLETracker::gap_scan_event_handler(const BLEScanResult &scan_result) {
|
|||||||
// IMPORTANT: Only this thread writes to ring_write_index_
|
// IMPORTANT: Only this thread writes to ring_write_index_
|
||||||
|
|
||||||
// Load our own index with relaxed ordering (we're the only writer)
|
// Load our own index with relaxed ordering (we're the only writer)
|
||||||
size_t write_idx = this->ring_write_index_.load(std::memory_order_relaxed);
|
uint8_t write_idx = this->ring_write_index_.load(std::memory_order_relaxed);
|
||||||
size_t next_write_idx = (write_idx + 1) % SCAN_RESULT_BUFFER_SIZE;
|
uint8_t next_write_idx = (write_idx + 1) % SCAN_RESULT_BUFFER_SIZE;
|
||||||
|
|
||||||
// Load consumer's index with acquire to see their latest updates
|
// Load consumer's index with acquire to see their latest updates
|
||||||
size_t read_idx = this->ring_read_index_.load(std::memory_order_acquire);
|
uint8_t read_idx = this->ring_read_index_.load(std::memory_order_acquire);
|
||||||
|
|
||||||
// Check if buffer is full
|
// Check if buffer is full
|
||||||
if (next_write_idx != read_idx) {
|
if (next_write_idx != read_idx) {
|
||||||
|
@@ -129,7 +129,7 @@ class ESPBTDeviceListener {
|
|||||||
ESP32BLETracker *parent_{nullptr};
|
ESP32BLETracker *parent_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ClientState {
|
enum class ClientState : uint8_t {
|
||||||
// Connection is allocated
|
// Connection is allocated
|
||||||
INIT,
|
INIT,
|
||||||
// Client is disconnecting
|
// Client is disconnecting
|
||||||
@@ -165,7 +165,7 @@ enum class ScannerState {
|
|||||||
STOPPED,
|
STOPPED,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ConnectionType {
|
enum class ConnectionType : uint8_t {
|
||||||
// The default connection type, we hold all the services in ram
|
// The default connection type, we hold all the services in ram
|
||||||
// for the duration of the connection.
|
// for the duration of the connection.
|
||||||
V1,
|
V1,
|
||||||
@@ -193,15 +193,19 @@ class ESPBTClient : public ESPBTDeviceListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClientState state() const { return state_; }
|
ClientState state() const { return state_; }
|
||||||
int app_id;
|
|
||||||
|
// Memory optimized layout
|
||||||
|
uint8_t app_id; // App IDs are small integers assigned sequentially
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Group 1: 1-byte types
|
||||||
ClientState state_{ClientState::INIT};
|
ClientState state_{ClientState::INIT};
|
||||||
// want_disconnect_ is set to true when a disconnect is requested
|
// want_disconnect_ is set to true when a disconnect is requested
|
||||||
// while the client is connecting. This is used to disconnect the
|
// while the client is connecting. This is used to disconnect the
|
||||||
// client as soon as we get the connection id (conn_id_) from the
|
// client as soon as we get the connection id (conn_id_) from the
|
||||||
// ESP_GATTC_OPEN_EVT event.
|
// ESP_GATTC_OPEN_EVT event.
|
||||||
bool want_disconnect_{false};
|
bool want_disconnect_{false};
|
||||||
|
// 2 bytes used, 2 bytes padding
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESP32BLETracker : public Component,
|
class ESP32BLETracker : public Component,
|
||||||
@@ -262,7 +266,7 @@ class ESP32BLETracker : public Component,
|
|||||||
/// Called to set the scanner state. Will also call callbacks to let listeners know when state is changed.
|
/// Called to set the scanner state. Will also call callbacks to let listeners know when state is changed.
|
||||||
void set_scanner_state_(ScannerState state);
|
void set_scanner_state_(ScannerState state);
|
||||||
|
|
||||||
int app_id_{0};
|
uint8_t app_id_{0};
|
||||||
|
|
||||||
/// Vector of addresses that have already been printed in print_bt_device_info
|
/// Vector of addresses that have already been printed in print_bt_device_info
|
||||||
std::vector<uint64_t> already_discovered_;
|
std::vector<uint64_t> already_discovered_;
|
||||||
@@ -289,9 +293,9 @@ class ESP32BLETracker : public Component,
|
|||||||
// Consumer: ESPHome main loop (loop() method)
|
// Consumer: ESPHome main loop (loop() method)
|
||||||
// This design ensures zero blocking in the BT callback and prevents scan result loss
|
// This design ensures zero blocking in the BT callback and prevents scan result loss
|
||||||
BLEScanResult *scan_ring_buffer_;
|
BLEScanResult *scan_ring_buffer_;
|
||||||
std::atomic<size_t> ring_write_index_{0}; // Written only by BT callback (producer)
|
std::atomic<uint8_t> ring_write_index_{0}; // Written only by BT callback (producer)
|
||||||
std::atomic<size_t> ring_read_index_{0}; // Written only by main loop (consumer)
|
std::atomic<uint8_t> ring_read_index_{0}; // Written only by main loop (consumer)
|
||||||
std::atomic<size_t> scan_results_dropped_{0}; // Tracks buffer overflow events
|
std::atomic<uint16_t> scan_results_dropped_{0}; // Tracks buffer overflow events
|
||||||
|
|
||||||
esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS};
|
esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS};
|
||||||
esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS};
|
esp_bt_status_t scan_set_param_failed_{ESP_BT_STATUS_SUCCESS};
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
from esphome import automation, pins
|
from esphome import automation, pins
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import i2c
|
||||||
from esphome.components.esp32 import add_idf_component
|
from esphome.components.esp32 import add_idf_component
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
@@ -7,6 +8,7 @@ from esphome.const import (
|
|||||||
CONF_CONTRAST,
|
CONF_CONTRAST,
|
||||||
CONF_DATA_PINS,
|
CONF_DATA_PINS,
|
||||||
CONF_FREQUENCY,
|
CONF_FREQUENCY,
|
||||||
|
CONF_I2C_ID,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_PIN,
|
CONF_PIN,
|
||||||
CONF_RESET_PIN,
|
CONF_RESET_PIN,
|
||||||
@@ -149,7 +151,8 @@ CONF_ON_IMAGE = "on_image"
|
|||||||
|
|
||||||
camera_range_param = cv.int_range(min=-2, max=2)
|
camera_range_param = cv.int_range(min=-2, max=2)
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
cv.ENTITY_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(ESP32Camera),
|
cv.GenerateID(): cv.declare_id(ESP32Camera),
|
||||||
# pin assignment
|
# pin assignment
|
||||||
@@ -167,12 +170,16 @@ CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Required(CONF_I2C_PINS): cv.Schema(
|
cv.Optional(CONF_I2C_PINS): cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_SDA): pins.internal_gpio_output_pin_number,
|
cv.Required(CONF_SDA): pins.internal_gpio_output_pin_number,
|
||||||
cv.Required(CONF_SCL): pins.internal_gpio_output_pin_number,
|
cv.Required(CONF_SCL): pins.internal_gpio_output_pin_number,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_I2C_ID): cv.Any(
|
||||||
|
cv.use_id(i2c.InternalI2CBus),
|
||||||
|
msg="I2C bus must be an internal ESP32 I2C bus",
|
||||||
|
),
|
||||||
cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number,
|
cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number,
|
||||||
cv.Optional(CONF_POWER_DOWN_PIN): pins.internal_gpio_output_pin_number,
|
cv.Optional(CONF_POWER_DOWN_PIN): pins.internal_gpio_output_pin_number,
|
||||||
# image
|
# image
|
||||||
@@ -204,7 +211,9 @@ CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
|||||||
ENUM_GAIN_CEILING, upper=True
|
ENUM_GAIN_CEILING, upper=True
|
||||||
),
|
),
|
||||||
# white balance
|
# white balance
|
||||||
cv.Optional(CONF_WB_MODE, default="AUTO"): cv.enum(ENUM_WB_MODE, upper=True),
|
cv.Optional(CONF_WB_MODE, default="AUTO"): cv.enum(
|
||||||
|
ENUM_WB_MODE, upper=True
|
||||||
|
),
|
||||||
# test pattern
|
# test pattern
|
||||||
cv.Optional(CONF_TEST_PATTERN, default=False): cv.boolean,
|
cv.Optional(CONF_TEST_PATTERN, default=False): cv.boolean,
|
||||||
# framerates
|
# framerates
|
||||||
@@ -231,11 +240,15 @@ CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
|||||||
),
|
),
|
||||||
cv.Optional(CONF_ON_IMAGE): automation.validate_automation(
|
cv.Optional(CONF_ON_IMAGE): automation.validate_automation(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESP32CameraImageTrigger),
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
ESP32CameraImageTrigger
|
||||||
|
),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA),
|
||||||
|
cv.has_exactly_one_key(CONF_I2C_PINS, CONF_I2C_ID),
|
||||||
|
)
|
||||||
|
|
||||||
SETTERS = {
|
SETTERS = {
|
||||||
# pin assignment
|
# pin assignment
|
||||||
@@ -280,6 +293,10 @@ async def to_code(config):
|
|||||||
|
|
||||||
extclk = config[CONF_EXTERNAL_CLOCK]
|
extclk = config[CONF_EXTERNAL_CLOCK]
|
||||||
cg.add(var.set_external_clock(extclk[CONF_PIN], extclk[CONF_FREQUENCY]))
|
cg.add(var.set_external_clock(extclk[CONF_PIN], extclk[CONF_FREQUENCY]))
|
||||||
|
if i2c_id := config.get(CONF_I2C_ID):
|
||||||
|
i2c_hub = await cg.get_variable(i2c_id)
|
||||||
|
cg.add(var.set_i2c_id(i2c_hub))
|
||||||
|
else:
|
||||||
i2c_pins = config[CONF_I2C_PINS]
|
i2c_pins = config[CONF_I2C_PINS]
|
||||||
cg.add(var.set_i2c_pins(i2c_pins[CONF_SDA], i2c_pins[CONF_SCL]))
|
cg.add(var.set_i2c_pins(i2c_pins[CONF_SDA], i2c_pins[CONF_SCL]))
|
||||||
cg.add(var.set_max_update_interval(1000 / config[CONF_MAX_FRAMERATE]))
|
cg.add(var.set_max_update_interval(1000 / config[CONF_MAX_FRAMERATE]))
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include "esp32_camera.h"
|
#include "esp32_camera.h"
|
||||||
#include "esphome/core/log.h"
|
|
||||||
#include "esphome/core/hal.h"
|
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
|
|
||||||
@@ -16,6 +16,12 @@ static const char *const TAG = "esp32_camera";
|
|||||||
void ESP32Camera::setup() {
|
void ESP32Camera::setup() {
|
||||||
global_esp32_camera = this;
|
global_esp32_camera = this;
|
||||||
|
|
||||||
|
#ifdef USE_I2C
|
||||||
|
if (this->i2c_bus_ != nullptr) {
|
||||||
|
this->config_.sccb_i2c_port = this->i2c_bus_->get_port();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* initialize time to now */
|
/* initialize time to now */
|
||||||
this->last_update_ = millis();
|
this->last_update_ = millis();
|
||||||
|
|
||||||
@@ -246,6 +252,13 @@ void ESP32Camera::set_i2c_pins(uint8_t sda, uint8_t scl) {
|
|||||||
this->config_.pin_sccb_sda = sda;
|
this->config_.pin_sccb_sda = sda;
|
||||||
this->config_.pin_sccb_scl = scl;
|
this->config_.pin_sccb_scl = scl;
|
||||||
}
|
}
|
||||||
|
#ifdef USE_I2C
|
||||||
|
void ESP32Camera::set_i2c_id(i2c::InternalI2CBus *i2c_bus) {
|
||||||
|
this->i2c_bus_ = i2c_bus;
|
||||||
|
this->config_.pin_sccb_sda = -1;
|
||||||
|
this->config_.pin_sccb_scl = -1;
|
||||||
|
}
|
||||||
|
#endif // USE_I2C
|
||||||
void ESP32Camera::set_reset_pin(uint8_t pin) { this->config_.pin_reset = pin; }
|
void ESP32Camera::set_reset_pin(uint8_t pin) { this->config_.pin_reset = pin; }
|
||||||
void ESP32Camera::set_power_down_pin(uint8_t pin) { this->config_.pin_pwdn = pin; }
|
void ESP32Camera::set_power_down_pin(uint8_t pin) { this->config_.pin_pwdn = pin; }
|
||||||
|
|
||||||
|
@@ -2,13 +2,17 @@
|
|||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
#include <esp_camera.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/queue.h>
|
||||||
#include "esphome/core/automation.h"
|
#include "esphome/core/automation.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/entity_base.h"
|
#include "esphome/core/entity_base.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include <esp_camera.h>
|
|
||||||
#include <freertos/FreeRTOS.h>
|
#ifdef USE_I2C
|
||||||
#include <freertos/queue.h>
|
#include "esphome/components/i2c/i2c_bus.h"
|
||||||
|
#endif // USE_I2C
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32_camera {
|
namespace esp32_camera {
|
||||||
@@ -118,6 +122,9 @@ class ESP32Camera : public EntityBase, public Component {
|
|||||||
void set_pixel_clock_pin(uint8_t pin);
|
void set_pixel_clock_pin(uint8_t pin);
|
||||||
void set_external_clock(uint8_t pin, uint32_t frequency);
|
void set_external_clock(uint8_t pin, uint32_t frequency);
|
||||||
void set_i2c_pins(uint8_t sda, uint8_t scl);
|
void set_i2c_pins(uint8_t sda, uint8_t scl);
|
||||||
|
#ifdef USE_I2C
|
||||||
|
void set_i2c_id(i2c::InternalI2CBus *i2c_bus);
|
||||||
|
#endif // USE_I2C
|
||||||
void set_reset_pin(uint8_t pin);
|
void set_reset_pin(uint8_t pin);
|
||||||
void set_power_down_pin(uint8_t pin);
|
void set_power_down_pin(uint8_t pin);
|
||||||
/* -- image */
|
/* -- image */
|
||||||
@@ -210,6 +217,9 @@ class ESP32Camera : public EntityBase, public Component {
|
|||||||
|
|
||||||
uint32_t last_idle_request_{0};
|
uint32_t last_idle_request_{0};
|
||||||
uint32_t last_update_{0};
|
uint32_t last_update_{0};
|
||||||
|
#ifdef USE_I2C
|
||||||
|
i2c::InternalI2CBus *i2c_bus_{nullptr};
|
||||||
|
#endif // USE_I2C
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
|
@@ -3,7 +3,7 @@ import esphome.config_validation as cv
|
|||||||
from esphome.const import CONF_ID, CONF_MODE, CONF_PORT
|
from esphome.const import CONF_ID, CONF_MODE, CONF_PORT
|
||||||
|
|
||||||
CODEOWNERS = ["@ayufan"]
|
CODEOWNERS = ["@ayufan"]
|
||||||
DEPENDENCIES = ["esp32_camera"]
|
DEPENDENCIES = ["esp32_camera", "network"]
|
||||||
MULTI_CONF = True
|
MULTI_CONF = True
|
||||||
|
|
||||||
esp32_camera_web_server_ns = cg.esphome_ns.namespace("esp32_camera_web_server")
|
esp32_camera_web_server_ns = cg.esphome_ns.namespace("esp32_camera_web_server")
|
||||||
|
@@ -1,48 +1,8 @@
|
|||||||
import esphome.codegen as cg
|
|
||||||
from esphome.components import esp32
|
from esphome.components import esp32
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import KEY_CORE, KEY_FRAMEWORK_VERSION
|
|
||||||
from esphome.core import CORE
|
|
||||||
|
|
||||||
CODEOWNERS = ["@jesserockz"]
|
CODEOWNERS = ["@jesserockz"]
|
||||||
|
|
||||||
RMT_TX_CHANNELS = {
|
|
||||||
esp32.const.VARIANT_ESP32: [0, 1, 2, 3, 4, 5, 6, 7],
|
|
||||||
esp32.const.VARIANT_ESP32S2: [0, 1, 2, 3],
|
|
||||||
esp32.const.VARIANT_ESP32S3: [0, 1, 2, 3],
|
|
||||||
esp32.const.VARIANT_ESP32C3: [0, 1],
|
|
||||||
esp32.const.VARIANT_ESP32C6: [0, 1],
|
|
||||||
esp32.const.VARIANT_ESP32H2: [0, 1],
|
|
||||||
}
|
|
||||||
|
|
||||||
RMT_RX_CHANNELS = {
|
|
||||||
esp32.const.VARIANT_ESP32: [0, 1, 2, 3, 4, 5, 6, 7],
|
|
||||||
esp32.const.VARIANT_ESP32S2: [0, 1, 2, 3],
|
|
||||||
esp32.const.VARIANT_ESP32S3: [4, 5, 6, 7],
|
|
||||||
esp32.const.VARIANT_ESP32C3: [2, 3],
|
|
||||||
esp32.const.VARIANT_ESP32C6: [2, 3],
|
|
||||||
esp32.const.VARIANT_ESP32H2: [2, 3],
|
|
||||||
}
|
|
||||||
|
|
||||||
rmt_channel_t = cg.global_ns.enum("rmt_channel_t")
|
|
||||||
RMT_CHANNEL_ENUMS = {
|
|
||||||
0: rmt_channel_t.RMT_CHANNEL_0,
|
|
||||||
1: rmt_channel_t.RMT_CHANNEL_1,
|
|
||||||
2: rmt_channel_t.RMT_CHANNEL_2,
|
|
||||||
3: rmt_channel_t.RMT_CHANNEL_3,
|
|
||||||
4: rmt_channel_t.RMT_CHANNEL_4,
|
|
||||||
5: rmt_channel_t.RMT_CHANNEL_5,
|
|
||||||
6: rmt_channel_t.RMT_CHANNEL_6,
|
|
||||||
7: rmt_channel_t.RMT_CHANNEL_7,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def use_new_rmt_driver():
|
|
||||||
framework_version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]
|
|
||||||
if CORE.using_esp_idf and framework_version >= cv.Version(5, 0, 0):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def validate_clock_resolution():
|
def validate_clock_resolution():
|
||||||
def _validator(value):
|
def _validator(value):
|
||||||
@@ -60,21 +20,3 @@ def validate_clock_resolution():
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
return _validator
|
return _validator
|
||||||
|
|
||||||
|
|
||||||
def validate_rmt_channel(*, tx: bool):
|
|
||||||
rmt_channels = RMT_TX_CHANNELS if tx else RMT_RX_CHANNELS
|
|
||||||
|
|
||||||
def _validator(value):
|
|
||||||
cv.only_on_esp32(value)
|
|
||||||
value = cv.int_(value)
|
|
||||||
variant = esp32.get_esp32_variant()
|
|
||||||
if variant not in rmt_channels:
|
|
||||||
raise cv.Invalid(f"ESP32 variant {variant} does not support RMT.")
|
|
||||||
if value not in rmt_channels[variant]:
|
|
||||||
raise cv.Invalid(
|
|
||||||
f"RMT channel {value} does not support {'transmitting' if tx else 'receiving'} for ESP32 variant {variant}."
|
|
||||||
)
|
|
||||||
return cv.enum(RMT_CHANNEL_ENUMS)(value)
|
|
||||||
|
|
||||||
return _validator
|
|
||||||
|
@@ -42,7 +42,6 @@ void ESP32RMTLEDStripLightOutput::setup() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
RAMAllocator<rmt_symbol_word_t> rmt_allocator(this->use_psram_ ? 0 : RAMAllocator<rmt_symbol_word_t>::ALLOC_INTERNAL);
|
RAMAllocator<rmt_symbol_word_t> rmt_allocator(this->use_psram_ ? 0 : RAMAllocator<rmt_symbol_word_t>::ALLOC_INTERNAL);
|
||||||
|
|
||||||
// 8 bits per byte, 1 rmt_symbol_word_t per bit + 1 rmt_symbol_word_t for reset
|
// 8 bits per byte, 1 rmt_symbol_word_t per bit + 1 rmt_symbol_word_t for reset
|
||||||
@@ -79,36 +78,6 @@ void ESP32RMTLEDStripLightOutput::setup() {
|
|||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
RAMAllocator<rmt_item32_t> rmt_allocator(this->use_psram_ ? 0 : RAMAllocator<rmt_item32_t>::ALLOC_INTERNAL);
|
|
||||||
|
|
||||||
// 8 bits per byte, 1 rmt_item32_t per bit + 1 rmt_item32_t for reset
|
|
||||||
this->rmt_buf_ = rmt_allocator.allocate(buffer_size * 8 + 1);
|
|
||||||
|
|
||||||
rmt_config_t config;
|
|
||||||
memset(&config, 0, sizeof(config));
|
|
||||||
config.channel = this->channel_;
|
|
||||||
config.rmt_mode = RMT_MODE_TX;
|
|
||||||
config.gpio_num = gpio_num_t(this->pin_);
|
|
||||||
config.mem_block_num = 1;
|
|
||||||
config.clk_div = RMT_CLK_DIV;
|
|
||||||
config.tx_config.loop_en = false;
|
|
||||||
config.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
|
|
||||||
config.tx_config.carrier_en = false;
|
|
||||||
config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
|
|
||||||
config.tx_config.idle_output_en = true;
|
|
||||||
|
|
||||||
if (rmt_config(&config) != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Cannot initialize RMT!");
|
|
||||||
this->mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (rmt_driver_install(config.channel, 0, 0) != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Cannot install RMT driver!");
|
|
||||||
this->mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32RMTLEDStripLightOutput::set_led_params(uint32_t bit0_high, uint32_t bit0_low, uint32_t bit1_high,
|
void ESP32RMTLEDStripLightOutput::set_led_params(uint32_t bit0_high, uint32_t bit0_low, uint32_t bit1_high,
|
||||||
@@ -145,11 +114,7 @@ void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) {
|
|||||||
|
|
||||||
ESP_LOGVV(TAG, "Writing RGB values to bus");
|
ESP_LOGVV(TAG, "Writing RGB values to bus");
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
esp_err_t error = rmt_tx_wait_all_done(this->channel_, 1000);
|
esp_err_t error = rmt_tx_wait_all_done(this->channel_, 1000);
|
||||||
#else
|
|
||||||
esp_err_t error = rmt_wait_tx_done(this->channel_, pdMS_TO_TICKS(1000));
|
|
||||||
#endif
|
|
||||||
if (error != ESP_OK) {
|
if (error != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "RMT TX timeout");
|
ESP_LOGE(TAG, "RMT TX timeout");
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
@@ -162,11 +127,7 @@ void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) {
|
|||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
uint8_t *psrc = this->buf_;
|
uint8_t *psrc = this->buf_;
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
rmt_symbol_word_t *pdest = this->rmt_buf_;
|
rmt_symbol_word_t *pdest = this->rmt_buf_;
|
||||||
#else
|
|
||||||
rmt_item32_t *pdest = this->rmt_buf_;
|
|
||||||
#endif
|
|
||||||
while (size < buffer_size) {
|
while (size < buffer_size) {
|
||||||
uint8_t b = *psrc;
|
uint8_t b = *psrc;
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
@@ -184,15 +145,11 @@ void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) {
|
|||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
rmt_transmit_config_t config;
|
rmt_transmit_config_t config;
|
||||||
memset(&config, 0, sizeof(config));
|
memset(&config, 0, sizeof(config));
|
||||||
config.loop_count = 0;
|
config.loop_count = 0;
|
||||||
config.flags.eot_level = 0;
|
config.flags.eot_level = 0;
|
||||||
error = rmt_transmit(this->channel_, this->encoder_, this->rmt_buf_, len * sizeof(rmt_symbol_word_t), &config);
|
error = rmt_transmit(this->channel_, this->encoder_, this->rmt_buf_, len * sizeof(rmt_symbol_word_t), &config);
|
||||||
#else
|
|
||||||
error = rmt_write_items(this->channel_, this->rmt_buf_, len, false);
|
|
||||||
#endif
|
|
||||||
if (error != ESP_OK) {
|
if (error != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "RMT TX error");
|
ESP_LOGE(TAG, "RMT TX error");
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
@@ -251,11 +208,7 @@ void ESP32RMTLEDStripLightOutput::dump_config() {
|
|||||||
"ESP32 RMT LED Strip:\n"
|
"ESP32 RMT LED Strip:\n"
|
||||||
" Pin: %u",
|
" Pin: %u",
|
||||||
this->pin_);
|
this->pin_);
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
ESP_LOGCONFIG(TAG, " RMT Symbols: %" PRIu32, this->rmt_symbols_);
|
ESP_LOGCONFIG(TAG, " RMT Symbols: %" PRIu32, this->rmt_symbols_);
|
||||||
#else
|
|
||||||
ESP_LOGCONFIG(TAG, " Channel: %u", this->channel_);
|
|
||||||
#endif
|
|
||||||
const char *rgb_order;
|
const char *rgb_order;
|
||||||
switch (this->rgb_order_) {
|
switch (this->rgb_order_) {
|
||||||
case ORDER_RGB:
|
case ORDER_RGB:
|
||||||
|
@@ -11,12 +11,7 @@
|
|||||||
#include <driver/gpio.h>
|
#include <driver/gpio.h>
|
||||||
#include <esp_err.h>
|
#include <esp_err.h>
|
||||||
#include <esp_idf_version.h>
|
#include <esp_idf_version.h>
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
#include <driver/rmt_tx.h>
|
#include <driver/rmt_tx.h>
|
||||||
#else
|
|
||||||
#include <driver/rmt.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32_rmt_led_strip {
|
namespace esp32_rmt_led_strip {
|
||||||
@@ -61,11 +56,7 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight {
|
|||||||
uint32_t reset_time_high, uint32_t reset_time_low);
|
uint32_t reset_time_high, uint32_t reset_time_low);
|
||||||
|
|
||||||
void set_rgb_order(RGBOrder rgb_order) { this->rgb_order_ = rgb_order; }
|
void set_rgb_order(RGBOrder rgb_order) { this->rgb_order_ = rgb_order; }
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
void set_rmt_symbols(uint32_t rmt_symbols) { this->rmt_symbols_ = rmt_symbols; }
|
void set_rmt_symbols(uint32_t rmt_symbols) { this->rmt_symbols_ = rmt_symbols; }
|
||||||
#else
|
|
||||||
void set_rmt_channel(rmt_channel_t channel) { this->channel_ = channel; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void clear_effect_data() override {
|
void clear_effect_data() override {
|
||||||
for (int i = 0; i < this->size(); i++)
|
for (int i = 0; i < this->size(); i++)
|
||||||
@@ -81,17 +72,11 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight {
|
|||||||
|
|
||||||
uint8_t *buf_{nullptr};
|
uint8_t *buf_{nullptr};
|
||||||
uint8_t *effect_data_{nullptr};
|
uint8_t *effect_data_{nullptr};
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
rmt_channel_handle_t channel_{nullptr};
|
rmt_channel_handle_t channel_{nullptr};
|
||||||
rmt_encoder_handle_t encoder_{nullptr};
|
rmt_encoder_handle_t encoder_{nullptr};
|
||||||
rmt_symbol_word_t *rmt_buf_{nullptr};
|
rmt_symbol_word_t *rmt_buf_{nullptr};
|
||||||
rmt_symbol_word_t bit0_, bit1_, reset_;
|
rmt_symbol_word_t bit0_, bit1_, reset_;
|
||||||
uint32_t rmt_symbols_{48};
|
uint32_t rmt_symbols_{48};
|
||||||
#else
|
|
||||||
rmt_item32_t *rmt_buf_{nullptr};
|
|
||||||
rmt_item32_t bit0_, bit1_, reset_;
|
|
||||||
rmt_channel_t channel_{RMT_CHANNEL_0};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t pin_;
|
uint8_t pin_;
|
||||||
uint16_t num_leds_;
|
uint16_t num_leds_;
|
||||||
|
@@ -3,7 +3,7 @@ import logging
|
|||||||
|
|
||||||
from esphome import pins
|
from esphome import pins
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
from esphome.components import esp32, esp32_rmt, light
|
from esphome.components import esp32, light
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_CHIPSET,
|
CONF_CHIPSET,
|
||||||
@@ -13,11 +13,9 @@ from esphome.const import (
|
|||||||
CONF_OUTPUT_ID,
|
CONF_OUTPUT_ID,
|
||||||
CONF_PIN,
|
CONF_PIN,
|
||||||
CONF_RGB_ORDER,
|
CONF_RGB_ORDER,
|
||||||
CONF_RMT_CHANNEL,
|
|
||||||
CONF_RMT_SYMBOLS,
|
CONF_RMT_SYMBOLS,
|
||||||
CONF_USE_DMA,
|
CONF_USE_DMA,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -69,53 +67,6 @@ CONF_RESET_HIGH = "reset_high"
|
|||||||
CONF_RESET_LOW = "reset_low"
|
CONF_RESET_LOW = "reset_low"
|
||||||
|
|
||||||
|
|
||||||
class OptionalForIDF5(cv.SplitDefault):
|
|
||||||
@property
|
|
||||||
def default(self):
|
|
||||||
if not esp32_rmt.use_new_rmt_driver():
|
|
||||||
return cv.UNDEFINED
|
|
||||||
return super().default
|
|
||||||
|
|
||||||
@default.setter
|
|
||||||
def default(self, value):
|
|
||||||
# Ignore default set from vol.Optional
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def only_with_new_rmt_driver(obj):
|
|
||||||
if not esp32_rmt.use_new_rmt_driver():
|
|
||||||
raise cv.Invalid(
|
|
||||||
"This feature is only available for the IDF framework version 5."
|
|
||||||
)
|
|
||||||
return obj
|
|
||||||
|
|
||||||
|
|
||||||
def not_with_new_rmt_driver(obj):
|
|
||||||
if esp32_rmt.use_new_rmt_driver():
|
|
||||||
raise cv.Invalid(
|
|
||||||
"This feature is not available for the IDF framework version 5."
|
|
||||||
)
|
|
||||||
return obj
|
|
||||||
|
|
||||||
|
|
||||||
def final_validation(config):
|
|
||||||
if not esp32_rmt.use_new_rmt_driver():
|
|
||||||
if CONF_RMT_CHANNEL not in config:
|
|
||||||
if CORE.using_esp_idf:
|
|
||||||
raise cv.Invalid(
|
|
||||||
"rmt_channel is a required option for IDF version < 5."
|
|
||||||
)
|
|
||||||
raise cv.Invalid(
|
|
||||||
"rmt_channel is a required option for the Arduino framework."
|
|
||||||
)
|
|
||||||
_LOGGER.warning(
|
|
||||||
"RMT_LED_STRIP support for IDF version < 5 is deprecated and will be removed soon."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
FINAL_VALIDATE_SCHEMA = final_validation
|
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.All(
|
CONFIG_SCHEMA = cv.All(
|
||||||
light.ADDRESSABLE_LIGHT_SCHEMA.extend(
|
light.ADDRESSABLE_LIGHT_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
@@ -123,20 +74,17 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
cv.Required(CONF_PIN): pins.internal_gpio_output_pin_number,
|
cv.Required(CONF_PIN): pins.internal_gpio_output_pin_number,
|
||||||
cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int,
|
cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int,
|
||||||
cv.Required(CONF_RGB_ORDER): cv.enum(RGB_ORDERS, upper=True),
|
cv.Required(CONF_RGB_ORDER): cv.enum(RGB_ORDERS, upper=True),
|
||||||
cv.Optional(CONF_RMT_CHANNEL): cv.All(
|
cv.SplitDefault(
|
||||||
not_with_new_rmt_driver, esp32_rmt.validate_rmt_channel(tx=True)
|
|
||||||
),
|
|
||||||
OptionalForIDF5(
|
|
||||||
CONF_RMT_SYMBOLS,
|
CONF_RMT_SYMBOLS,
|
||||||
esp32_idf=192,
|
esp32=192,
|
||||||
esp32_s2_idf=192,
|
esp32_s2=192,
|
||||||
esp32_s3_idf=192,
|
esp32_s3=192,
|
||||||
esp32_p4_idf=192,
|
esp32_p4=192,
|
||||||
esp32_c3_idf=96,
|
esp32_c3=96,
|
||||||
esp32_c5_idf=96,
|
esp32_c5=96,
|
||||||
esp32_c6_idf=96,
|
esp32_c6=96,
|
||||||
esp32_h2_idf=96,
|
esp32_h2=96,
|
||||||
): cv.All(only_with_new_rmt_driver, cv.int_range(min=2)),
|
): cv.int_range(min=2),
|
||||||
cv.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds,
|
cv.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds,
|
||||||
cv.Optional(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True),
|
cv.Optional(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True),
|
||||||
cv.Optional(CONF_IS_RGBW, default=False): cv.boolean,
|
cv.Optional(CONF_IS_RGBW, default=False): cv.boolean,
|
||||||
@@ -145,7 +93,6 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
esp32.only_on_variant(
|
esp32.only_on_variant(
|
||||||
supported=[esp32.const.VARIANT_ESP32S3, esp32.const.VARIANT_ESP32P4]
|
supported=[esp32.const.VARIANT_ESP32S3, esp32.const.VARIANT_ESP32P4]
|
||||||
),
|
),
|
||||||
cv.only_with_esp_idf,
|
|
||||||
cv.boolean,
|
cv.boolean,
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_USE_PSRAM, default=True): cv.boolean,
|
cv.Optional(CONF_USE_PSRAM, default=True): cv.boolean,
|
||||||
@@ -218,15 +165,6 @@ async def to_code(config):
|
|||||||
cg.add(var.set_is_rgbw(config[CONF_IS_RGBW]))
|
cg.add(var.set_is_rgbw(config[CONF_IS_RGBW]))
|
||||||
cg.add(var.set_is_wrgb(config[CONF_IS_WRGB]))
|
cg.add(var.set_is_wrgb(config[CONF_IS_WRGB]))
|
||||||
cg.add(var.set_use_psram(config[CONF_USE_PSRAM]))
|
cg.add(var.set_use_psram(config[CONF_USE_PSRAM]))
|
||||||
|
|
||||||
if esp32_rmt.use_new_rmt_driver():
|
|
||||||
cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS]))
|
cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS]))
|
||||||
if CONF_USE_DMA in config:
|
if CONF_USE_DMA in config:
|
||||||
cg.add(var.set_use_dma(config[CONF_USE_DMA]))
|
cg.add(var.set_use_dma(config[CONF_USE_DMA]))
|
||||||
else:
|
|
||||||
rmt_channel_t = cg.global_ns.enum("rmt_channel_t")
|
|
||||||
cg.add(
|
|
||||||
var.set_rmt_channel(
|
|
||||||
getattr(rmt_channel_t, f"RMT_CHANNEL_{config[CONF_RMT_CHANNEL]}")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
@@ -26,19 +26,19 @@ void ESPHomeOTAComponent::setup() {
|
|||||||
ota::register_ota_platform(this);
|
ota::register_ota_platform(this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0); // monitored for incoming connections
|
this->server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0); // monitored for incoming connections
|
||||||
if (server_ == nullptr) {
|
if (this->server_ == nullptr) {
|
||||||
ESP_LOGW(TAG, "Could not create socket");
|
ESP_LOGW(TAG, "Could not create socket");
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int enable = 1;
|
int enable = 1;
|
||||||
int err = server_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
|
int err = this->server_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err);
|
ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err);
|
||||||
// we can still continue
|
// we can still continue
|
||||||
}
|
}
|
||||||
err = server_->setblocking(false);
|
err = this->server_->setblocking(false);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err);
|
ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err);
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
@@ -54,14 +54,14 @@ void ESPHomeOTAComponent::setup() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = server_->bind((struct sockaddr *) &server, sizeof(server));
|
err = this->server_->bind((struct sockaddr *) &server, sizeof(server));
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
|
ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = server_->listen(4);
|
err = this->server_->listen(4);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
ESP_LOGW(TAG, "Socket unable to listen: errno %d", errno);
|
ESP_LOGW(TAG, "Socket unable to listen: errno %d", errno);
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
@@ -82,7 +82,14 @@ void ESPHomeOTAComponent::dump_config() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESPHomeOTAComponent::loop() { this->handle_(); }
|
void ESPHomeOTAComponent::loop() {
|
||||||
|
// Skip handle_() call if no client connected and no incoming connections
|
||||||
|
// This optimization reduces idle loop overhead when OTA is not active
|
||||||
|
// Note: No need to check server_ for null as the component is marked failed in setup() if server_ creation fails
|
||||||
|
if (this->client_ != nullptr || this->server_->ready()) {
|
||||||
|
this->handle_();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01;
|
static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01;
|
||||||
|
|
||||||
@@ -101,23 +108,21 @@ void ESPHomeOTAComponent::handle_() {
|
|||||||
size_t size_acknowledged = 0;
|
size_t size_acknowledged = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (client_ == nullptr) {
|
if (this->client_ == nullptr) {
|
||||||
// Check if the server socket is ready before accepting
|
// We already checked server_->ready() in loop(), so we can accept directly
|
||||||
if (this->server_->ready()) {
|
|
||||||
struct sockaddr_storage source_addr;
|
struct sockaddr_storage source_addr;
|
||||||
socklen_t addr_len = sizeof(source_addr);
|
socklen_t addr_len = sizeof(source_addr);
|
||||||
client_ = server_->accept((struct sockaddr *) &source_addr, &addr_len);
|
this->client_ = this->server_->accept((struct sockaddr *) &source_addr, &addr_len);
|
||||||
}
|
if (this->client_ == nullptr)
|
||||||
}
|
|
||||||
if (client_ == nullptr)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int enable = 1;
|
int enable = 1;
|
||||||
int err = client_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int));
|
int err = this->client_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int));
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
ESP_LOGW(TAG, "Socket could not enable TCP nodelay, errno %d", errno);
|
ESP_LOGW(TAG, "Socket could not enable TCP nodelay, errno %d", errno);
|
||||||
client_->close();
|
this->client_->close();
|
||||||
client_ = nullptr;
|
this->client_ = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -106,7 +106,7 @@ void EthernetComponent::setup() {
|
|||||||
.post_cb = nullptr,
|
.post_cb = nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if USE_ESP_IDF && (ESP_IDF_VERSION_MAJOR >= 5)
|
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||||
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(host, &devcfg);
|
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(host, &devcfg);
|
||||||
#else
|
#else
|
||||||
spi_device_handle_t spi_handle = nullptr;
|
spi_device_handle_t spi_handle = nullptr;
|
||||||
@@ -274,6 +274,9 @@ void EthernetComponent::loop() {
|
|||||||
ESP_LOGW(TAG, "Connection lost; reconnecting");
|
ESP_LOGW(TAG, "Connection lost; reconnecting");
|
||||||
this->state_ = EthernetComponentState::CONNECTING;
|
this->state_ = EthernetComponentState::CONNECTING;
|
||||||
this->start_connect_();
|
this->start_connect_();
|
||||||
|
} else {
|
||||||
|
// When connected and stable, disable the loop to save CPU cycles
|
||||||
|
this->disable_loop();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -397,11 +400,13 @@ void EthernetComponent::eth_event_handler(void *arg, esp_event_base_t event_base
|
|||||||
case ETHERNET_EVENT_START:
|
case ETHERNET_EVENT_START:
|
||||||
event_name = "ETH started";
|
event_name = "ETH started";
|
||||||
global_eth_component->started_ = true;
|
global_eth_component->started_ = true;
|
||||||
|
global_eth_component->enable_loop_soon_any_context();
|
||||||
break;
|
break;
|
||||||
case ETHERNET_EVENT_STOP:
|
case ETHERNET_EVENT_STOP:
|
||||||
event_name = "ETH stopped";
|
event_name = "ETH stopped";
|
||||||
global_eth_component->started_ = false;
|
global_eth_component->started_ = false;
|
||||||
global_eth_component->connected_ = false;
|
global_eth_component->connected_ = false;
|
||||||
|
global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes
|
||||||
break;
|
break;
|
||||||
case ETHERNET_EVENT_CONNECTED:
|
case ETHERNET_EVENT_CONNECTED:
|
||||||
event_name = "ETH connected";
|
event_name = "ETH connected";
|
||||||
@@ -409,6 +414,7 @@ void EthernetComponent::eth_event_handler(void *arg, esp_event_base_t event_base
|
|||||||
case ETHERNET_EVENT_DISCONNECTED:
|
case ETHERNET_EVENT_DISCONNECTED:
|
||||||
event_name = "ETH disconnected";
|
event_name = "ETH disconnected";
|
||||||
global_eth_component->connected_ = false;
|
global_eth_component->connected_ = false;
|
||||||
|
global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
@@ -425,8 +431,10 @@ void EthernetComponent::got_ip_event_handler(void *arg, esp_event_base_t event_b
|
|||||||
global_eth_component->got_ipv4_address_ = true;
|
global_eth_component->got_ipv4_address_ = true;
|
||||||
#if USE_NETWORK_IPV6 && (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0)
|
#if USE_NETWORK_IPV6 && (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0)
|
||||||
global_eth_component->connected_ = global_eth_component->ipv6_count_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT;
|
global_eth_component->connected_ = global_eth_component->ipv6_count_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT;
|
||||||
|
global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes
|
||||||
#else
|
#else
|
||||||
global_eth_component->connected_ = true;
|
global_eth_component->connected_ = true;
|
||||||
|
global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes
|
||||||
#endif /* USE_NETWORK_IPV6 */
|
#endif /* USE_NETWORK_IPV6 */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,8 +447,10 @@ void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_
|
|||||||
#if (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0)
|
#if (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0)
|
||||||
global_eth_component->connected_ =
|
global_eth_component->connected_ =
|
||||||
global_eth_component->got_ipv4_address_ && (global_eth_component->ipv6_count_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT);
|
global_eth_component->got_ipv4_address_ && (global_eth_component->ipv6_count_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT);
|
||||||
|
global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes
|
||||||
#else
|
#else
|
||||||
global_eth_component->connected_ = global_eth_component->got_ipv4_address_;
|
global_eth_component->connected_ = global_eth_component->got_ipv4_address_;
|
||||||
|
global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* USE_NETWORK_IPV6 */
|
#endif /* USE_NETWORK_IPV6 */
|
||||||
@@ -620,6 +630,7 @@ bool EthernetComponent::powerdown() {
|
|||||||
}
|
}
|
||||||
this->connected_ = false;
|
this->connected_ = false;
|
||||||
this->started_ = false;
|
this->started_ = false;
|
||||||
|
// No need to enable_loop() here as this is only called during shutdown/reboot
|
||||||
if (this->phy_->pwrctl(this->phy_, false) != ESP_OK) {
|
if (this->phy_->pwrctl(this->phy_, false) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Error powering down ethernet PHY");
|
ESP_LOGE(TAG, "Error powering down ethernet PHY");
|
||||||
return false;
|
return false;
|
||||||
|
@@ -67,10 +67,10 @@ class Font
|
|||||||
inline int get_height() { return this->height_; }
|
inline int get_height() { return this->height_; }
|
||||||
inline int get_bpp() { return this->bpp_; }
|
inline int get_bpp() { return this->bpp_; }
|
||||||
|
|
||||||
const std::vector<Glyph, ExternalRAMAllocator<Glyph>> &get_glyphs() const { return glyphs_; }
|
const std::vector<Glyph, RAMAllocator<Glyph>> &get_glyphs() const { return glyphs_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<Glyph, ExternalRAMAllocator<Glyph>> glyphs_;
|
std::vector<Glyph, RAMAllocator<Glyph>> glyphs_;
|
||||||
int baseline_;
|
int baseline_;
|
||||||
int height_;
|
int height_;
|
||||||
uint8_t bpp_; // bits per pixel
|
uint8_t bpp_; // bits per pixel
|
||||||
|
@@ -175,7 +175,7 @@ async def to_code(config):
|
|||||||
not config.get(CONF_VERIFY_SSL),
|
not config.get(CONF_VERIFY_SSL),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
cg.add_library("WiFiClientSecure", None)
|
cg.add_library("NetworkClientSecure", None)
|
||||||
cg.add_library("HTTPClient", None)
|
cg.add_library("HTTPClient", None)
|
||||||
if CORE.is_esp8266:
|
if CORE.is_esp8266:
|
||||||
cg.add_library("ESP8266HTTPClient", None)
|
cg.add_library("ESP8266HTTPClient", None)
|
||||||
|
@@ -239,7 +239,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
|||||||
|
|
||||||
std::string response_body;
|
std::string response_body;
|
||||||
if (this->capture_response_.value(x...)) {
|
if (this->capture_response_.value(x...)) {
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
uint8_t *buf = allocator.allocate(max_length);
|
uint8_t *buf = allocator.allocate(max_length);
|
||||||
if (buf != nullptr) {
|
if (buf != nullptr) {
|
||||||
size_t read_index = 0;
|
size_t read_index = 0;
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#if defined(USE_ESP32) || defined(USE_RP2040)
|
#if defined(USE_ESP32) || defined(USE_RP2040)
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
|
#include <WiFiClient.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ESP8266
|
#ifdef USE_ESP8266
|
||||||
#include <ESP8266HTTPClient.h>
|
#include <ESP8266HTTPClient.h>
|
||||||
|
@@ -54,7 +54,7 @@ void HttpRequestUpdate::update_task(void *params) {
|
|||||||
UPDATE_RETURN;
|
UPDATE_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
uint8_t *data = allocator.allocate(container->content_length);
|
uint8_t *data = allocator.allocate(container->content_length);
|
||||||
if (data == nullptr) {
|
if (data == nullptr) {
|
||||||
std::string msg = str_sprintf("Failed to allocate %d bytes for manifest", container->content_length);
|
std::string msg = str_sprintf("Failed to allocate %d bytes for manifest", container->content_length);
|
||||||
|
@@ -22,8 +22,9 @@ import esphome.final_validate as fv
|
|||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
i2c_ns = cg.esphome_ns.namespace("i2c")
|
i2c_ns = cg.esphome_ns.namespace("i2c")
|
||||||
I2CBus = i2c_ns.class_("I2CBus")
|
I2CBus = i2c_ns.class_("I2CBus")
|
||||||
ArduinoI2CBus = i2c_ns.class_("ArduinoI2CBus", I2CBus, cg.Component)
|
InternalI2CBus = i2c_ns.class_("InternalI2CBus", I2CBus)
|
||||||
IDFI2CBus = i2c_ns.class_("IDFI2CBus", I2CBus, cg.Component)
|
ArduinoI2CBus = i2c_ns.class_("ArduinoI2CBus", InternalI2CBus, cg.Component)
|
||||||
|
IDFI2CBus = i2c_ns.class_("IDFI2CBus", InternalI2CBus, cg.Component)
|
||||||
I2CDevice = i2c_ns.class_("I2CDevice")
|
I2CDevice = i2c_ns.class_("I2CDevice")
|
||||||
|
|
||||||
|
|
||||||
@@ -71,6 +72,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
@coroutine_with_priority(1.0)
|
@coroutine_with_priority(1.0)
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
cg.add_global(i2c_ns.using)
|
cg.add_global(i2c_ns.using)
|
||||||
|
cg.add_define("USE_I2C")
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -108,5 +108,12 @@ class I2CBus {
|
|||||||
bool scan_{false}; ///< Should we scan ? Can be set in the yaml
|
bool scan_{false}; ///< Should we scan ? Can be set in the yaml
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class InternalI2CBus : public I2CBus {
|
||||||
|
public:
|
||||||
|
/// @brief Returns the I2C port number.
|
||||||
|
/// @return the port number of the internal I2C bus
|
||||||
|
virtual int get_port() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace i2c
|
} // namespace i2c
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
|
|
||||||
#include "i2c_bus_arduino.h"
|
#include "i2c_bus_arduino.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <cstring>
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include <Arduino.h>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace i2c {
|
namespace i2c {
|
||||||
@@ -23,6 +23,7 @@ void ArduinoI2CBus::setup() {
|
|||||||
} else {
|
} else {
|
||||||
wire_ = new TwoWire(next_bus_num); // NOLINT(cppcoreguidelines-owning-memory)
|
wire_ = new TwoWire(next_bus_num); // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
|
this->port_ = next_bus_num;
|
||||||
next_bus_num++;
|
next_bus_num++;
|
||||||
#elif defined(USE_ESP8266)
|
#elif defined(USE_ESP8266)
|
||||||
wire_ = new TwoWire(); // NOLINT(cppcoreguidelines-owning-memory)
|
wire_ = new TwoWire(); // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
@@ -125,7 +126,7 @@ ErrorCode ArduinoI2CBus::readv(uint8_t address, ReadBuffer *buffers, size_t cnt)
|
|||||||
size_t to_request = 0;
|
size_t to_request = 0;
|
||||||
for (size_t i = 0; i < cnt; i++)
|
for (size_t i = 0; i < cnt; i++)
|
||||||
to_request += buffers[i].len;
|
to_request += buffers[i].len;
|
||||||
size_t ret = wire_->requestFrom((int) address, (int) to_request, 1);
|
size_t ret = wire_->requestFrom(address, to_request, true);
|
||||||
if (ret != to_request) {
|
if (ret != to_request) {
|
||||||
ESP_LOGVV(TAG, "RX %u from %02X failed with error %u", to_request, address, ret);
|
ESP_LOGVV(TAG, "RX %u from %02X failed with error %u", to_request, address, ret);
|
||||||
return ERROR_TIMEOUT;
|
return ERROR_TIMEOUT;
|
||||||
|
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
|
|
||||||
#include "i2c_bus.h"
|
|
||||||
#include "esphome/core/component.h"
|
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "i2c_bus.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace i2c {
|
namespace i2c {
|
||||||
@@ -15,7 +15,7 @@ enum RecoveryCode {
|
|||||||
RECOVERY_COMPLETED,
|
RECOVERY_COMPLETED,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ArduinoI2CBus : public I2CBus, public Component {
|
class ArduinoI2CBus : public InternalI2CBus, public Component {
|
||||||
public:
|
public:
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
@@ -29,12 +29,15 @@ class ArduinoI2CBus : public I2CBus, public Component {
|
|||||||
void set_frequency(uint32_t frequency) { frequency_ = frequency; }
|
void set_frequency(uint32_t frequency) { frequency_ = frequency; }
|
||||||
void set_timeout(uint32_t timeout) { timeout_ = timeout; }
|
void set_timeout(uint32_t timeout) { timeout_ = timeout; }
|
||||||
|
|
||||||
|
int get_port() const override { return this->port_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void recover_();
|
void recover_();
|
||||||
void set_pins_and_clock_();
|
void set_pins_and_clock_();
|
||||||
RecoveryCode recovery_result_;
|
RecoveryCode recovery_result_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
int8_t port_{-1};
|
||||||
TwoWire *wire_;
|
TwoWire *wire_;
|
||||||
uint8_t sda_pin_;
|
uint8_t sda_pin_;
|
||||||
uint8_t scl_pin_;
|
uint8_t scl_pin_;
|
||||||
|
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP_IDF
|
||||||
|
|
||||||
#include "i2c_bus.h"
|
|
||||||
#include "esphome/core/component.h"
|
|
||||||
#include <driver/i2c.h>
|
#include <driver/i2c.h>
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "i2c_bus.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace i2c {
|
namespace i2c {
|
||||||
@@ -15,7 +15,7 @@ enum RecoveryCode {
|
|||||||
RECOVERY_COMPLETED,
|
RECOVERY_COMPLETED,
|
||||||
};
|
};
|
||||||
|
|
||||||
class IDFI2CBus : public I2CBus, public Component {
|
class IDFI2CBus : public InternalI2CBus, public Component {
|
||||||
public:
|
public:
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
@@ -31,6 +31,8 @@ class IDFI2CBus : public I2CBus, public Component {
|
|||||||
void set_frequency(uint32_t frequency) { frequency_ = frequency; }
|
void set_frequency(uint32_t frequency) { frequency_ = frequency; }
|
||||||
void set_timeout(uint32_t timeout) { timeout_ = timeout; }
|
void set_timeout(uint32_t timeout) { timeout_ = timeout; }
|
||||||
|
|
||||||
|
int get_port() const override { return static_cast<int>(this->port_); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void recover_();
|
void recover_();
|
||||||
RecoveryCode recovery_result_;
|
RecoveryCode recovery_result_;
|
||||||
|
@@ -9,7 +9,7 @@ namespace i2s_audio {
|
|||||||
|
|
||||||
static const char *const TAG = "i2s_audio";
|
static const char *const TAG = "i2s_audio";
|
||||||
|
|
||||||
#if defined(USE_ESP_IDF) && (ESP_IDF_VERSION_MAJOR >= 5)
|
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||||
static const uint8_t I2S_NUM_MAX = SOC_I2S_NUM; // because IDF 5+ took this away :(
|
static const uint8_t I2S_NUM_MAX = SOC_I2S_NUM; // because IDF 5+ took this away :(
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -114,7 +114,7 @@ async def to_code(config):
|
|||||||
cg.add(var.set_external_dac_channels(2 if config[CONF_MODE] == "stereo" else 1))
|
cg.add(var.set_external_dac_channels(2 if config[CONF_MODE] == "stereo" else 1))
|
||||||
cg.add(var.set_i2s_comm_fmt_lsb(config[CONF_I2S_COMM_FMT] == "lsb"))
|
cg.add(var.set_i2s_comm_fmt_lsb(config[CONF_I2S_COMM_FMT] == "lsb"))
|
||||||
|
|
||||||
cg.add_library("WiFiClientSecure", None)
|
cg.add_library("NetworkClientSecure", None)
|
||||||
cg.add_library("HTTPClient", None)
|
cg.add_library("HTTPClient", None)
|
||||||
cg.add_library("esphome/ESP32-audioI2S", "2.3.0")
|
cg.add_library("esphome/ESP32-audioI2S", "2.3.0")
|
||||||
cg.add_build_flag("-DAUDIO_NO_SD_FS")
|
cg.add_build_flag("-DAUDIO_NO_SD_FS")
|
||||||
|
@@ -484,7 +484,7 @@ bool I2SAudioSpeaker::send_esp_err_to_event_group_(esp_err_t err) {
|
|||||||
esp_err_t I2SAudioSpeaker::allocate_buffers_(size_t data_buffer_size, size_t ring_buffer_size) {
|
esp_err_t I2SAudioSpeaker::allocate_buffers_(size_t data_buffer_size, size_t ring_buffer_size) {
|
||||||
if (this->data_buffer_ == nullptr) {
|
if (this->data_buffer_ == nullptr) {
|
||||||
// Allocate data buffer for temporarily storing audio from the ring buffer before writing to the I2S bus
|
// Allocate data buffer for temporarily storing audio from the ring buffer before writing to the I2S bus
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
this->data_buffer_ = allocator.allocate(data_buffer_size);
|
this->data_buffer_ = allocator.allocate(data_buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,7 +698,7 @@ void I2SAudioSpeaker::delete_task_(size_t buffer_size) {
|
|||||||
this->audio_ring_buffer_.reset(); // Releases ownership of the shared_ptr
|
this->audio_ring_buffer_.reset(); // Releases ownership of the shared_ptr
|
||||||
|
|
||||||
if (this->data_buffer_ != nullptr) {
|
if (this->data_buffer_ != nullptr) {
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
allocator.deallocate(this->data_buffer_, buffer_size);
|
allocator.deallocate(this->data_buffer_, buffer_size);
|
||||||
this->data_buffer_ = nullptr;
|
this->data_buffer_ = nullptr;
|
||||||
}
|
}
|
||||||
|
@@ -57,8 +57,8 @@ void Inkplate6::setup() {
|
|||||||
* Allocate buffers. May be called after setup to re-initialise if e.g. greyscale is changed.
|
* Allocate buffers. May be called after setup to re-initialise if e.g. greyscale is changed.
|
||||||
*/
|
*/
|
||||||
void Inkplate6::initialize_() {
|
void Inkplate6::initialize_() {
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
ExternalRAMAllocator<uint32_t> allocator32(ExternalRAMAllocator<uint32_t>::ALLOW_FAILURE);
|
RAMAllocator<uint32_t> allocator32;
|
||||||
uint32_t buffer_size = this->get_buffer_length_();
|
uint32_t buffer_size = this->get_buffer_length_();
|
||||||
if (buffer_size == 0)
|
if (buffer_size == 0)
|
||||||
return;
|
return;
|
||||||
|
@@ -3,28 +3,16 @@
|
|||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#ifdef USE_ARDUINO
|
|
||||||
#include <esp32-hal-ledc.h>
|
|
||||||
#endif
|
|
||||||
#include <driver/ledc.h>
|
#include <driver/ledc.h>
|
||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
|
||||||
#define CLOCK_FREQUENCY 80e6f
|
#define CLOCK_FREQUENCY 80e6f
|
||||||
|
|
||||||
#ifdef USE_ARDUINO
|
|
||||||
#ifdef SOC_LEDC_SUPPORT_XTAL_CLOCK
|
|
||||||
#undef CLOCK_FREQUENCY
|
|
||||||
// starting with ESP32 Arduino 2.0.2, the 40MHz crystal is used as clock by default if supported
|
|
||||||
#define CLOCK_FREQUENCY 40e6f
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifdef SOC_LEDC_SUPPORT_APB_CLOCK
|
#ifdef SOC_LEDC_SUPPORT_APB_CLOCK
|
||||||
#define DEFAULT_CLK LEDC_USE_APB_CLK
|
#define DEFAULT_CLK LEDC_USE_APB_CLK
|
||||||
#else
|
#else
|
||||||
#define DEFAULT_CLK LEDC_AUTO_CLK
|
#define DEFAULT_CLK LEDC_AUTO_CLK
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
static const uint8_t SETUP_ATTEMPT_COUNT_MAX = 5;
|
static const uint8_t SETUP_ATTEMPT_COUNT_MAX = 5;
|
||||||
|
|
||||||
@@ -34,7 +22,6 @@ namespace ledc {
|
|||||||
static const char *const TAG = "ledc.output";
|
static const char *const TAG = "ledc.output";
|
||||||
|
|
||||||
static const int MAX_RES_BITS = LEDC_TIMER_BIT_MAX - 1;
|
static const int MAX_RES_BITS = LEDC_TIMER_BIT_MAX - 1;
|
||||||
#ifdef USE_ESP_IDF
|
|
||||||
#if SOC_LEDC_SUPPORT_HS_MODE
|
#if SOC_LEDC_SUPPORT_HS_MODE
|
||||||
// Only ESP32 has LEDC_HIGH_SPEED_MODE
|
// Only ESP32 has LEDC_HIGH_SPEED_MODE
|
||||||
inline ledc_mode_t get_speed_mode(uint8_t channel) { return channel < 8 ? LEDC_HIGH_SPEED_MODE : LEDC_LOW_SPEED_MODE; }
|
inline ledc_mode_t get_speed_mode(uint8_t channel) { return channel < 8 ? LEDC_HIGH_SPEED_MODE : LEDC_LOW_SPEED_MODE; }
|
||||||
@@ -44,7 +31,6 @@ inline ledc_mode_t get_speed_mode(uint8_t channel) { return channel < 8 ? LEDC_H
|
|||||||
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/ledc.html#functionality-overview
|
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/ledc.html#functionality-overview
|
||||||
inline ledc_mode_t get_speed_mode(uint8_t) { return LEDC_LOW_SPEED_MODE; }
|
inline ledc_mode_t get_speed_mode(uint8_t) { return LEDC_LOW_SPEED_MODE; }
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
float ledc_max_frequency_for_bit_depth(uint8_t bit_depth) {
|
float ledc_max_frequency_for_bit_depth(uint8_t bit_depth) {
|
||||||
return static_cast<float>(CLOCK_FREQUENCY) / static_cast<float>(1 << bit_depth);
|
return static_cast<float>(CLOCK_FREQUENCY) / static_cast<float>(1 << bit_depth);
|
||||||
@@ -68,7 +54,6 @@ optional<uint8_t> ledc_bit_depth_for_frequency(float frequency) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_ESP_IDF
|
|
||||||
esp_err_t configure_timer_frequency(ledc_mode_t speed_mode, ledc_timer_t timer_num, ledc_channel_t chan_num,
|
esp_err_t configure_timer_frequency(ledc_mode_t speed_mode, ledc_timer_t timer_num, ledc_channel_t chan_num,
|
||||||
uint8_t channel, uint8_t &bit_depth, float frequency) {
|
uint8_t channel, uint8_t &bit_depth, float frequency) {
|
||||||
bit_depth = *ledc_bit_depth_for_frequency(frequency);
|
bit_depth = *ledc_bit_depth_for_frequency(frequency);
|
||||||
@@ -98,13 +83,10 @@ esp_err_t configure_timer_frequency(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
|||||||
|
|
||||||
return init_result;
|
return init_result;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_ESP_IDF
|
|
||||||
constexpr int ledc_angle_to_htop(float angle, uint8_t bit_depth) {
|
constexpr int ledc_angle_to_htop(float angle, uint8_t bit_depth) {
|
||||||
return static_cast<int>(angle * ((1U << bit_depth) - 1) / 360.0f);
|
return static_cast<int>(angle * ((1U << bit_depth) - 1) / 360.0f);
|
||||||
}
|
}
|
||||||
#endif // USE_ESP_IDF
|
|
||||||
|
|
||||||
void LEDCOutput::write_state(float state) {
|
void LEDCOutput::write_state(float state) {
|
||||||
if (!this->initialized_) {
|
if (!this->initialized_) {
|
||||||
@@ -120,10 +102,6 @@ void LEDCOutput::write_state(float state) {
|
|||||||
const float duty_rounded = roundf(state * max_duty);
|
const float duty_rounded = roundf(state * max_duty);
|
||||||
auto duty = static_cast<uint32_t>(duty_rounded);
|
auto duty = static_cast<uint32_t>(duty_rounded);
|
||||||
ESP_LOGV(TAG, "Setting duty: %" PRIu32 " on channel %u", duty, this->channel_);
|
ESP_LOGV(TAG, "Setting duty: %" PRIu32 " on channel %u", duty, this->channel_);
|
||||||
#ifdef USE_ARDUINO
|
|
||||||
ledcWrite(this->channel_, duty);
|
|
||||||
#endif
|
|
||||||
#ifdef USE_ESP_IDF
|
|
||||||
auto speed_mode = get_speed_mode(this->channel_);
|
auto speed_mode = get_speed_mode(this->channel_);
|
||||||
auto chan_num = static_cast<ledc_channel_t>(this->channel_ % 8);
|
auto chan_num = static_cast<ledc_channel_t>(this->channel_ % 8);
|
||||||
int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_);
|
int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_);
|
||||||
@@ -135,18 +113,10 @@ void LEDCOutput::write_state(float state) {
|
|||||||
ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint);
|
ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint);
|
||||||
ledc_update_duty(speed_mode, chan_num);
|
ledc_update_duty(speed_mode, chan_num);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LEDCOutput::setup() {
|
void LEDCOutput::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Running setup");
|
ESP_LOGCONFIG(TAG, "Running setup");
|
||||||
#ifdef USE_ARDUINO
|
|
||||||
this->update_frequency(this->frequency_);
|
|
||||||
this->turn_off();
|
|
||||||
// Attach pin after setting default value
|
|
||||||
ledcAttachPin(this->pin_->get_pin(), this->channel_);
|
|
||||||
#endif
|
|
||||||
#ifdef USE_ESP_IDF
|
|
||||||
auto speed_mode = get_speed_mode(this->channel_);
|
auto speed_mode = get_speed_mode(this->channel_);
|
||||||
auto timer_num = static_cast<ledc_timer_t>((this->channel_ % 8) / 2);
|
auto timer_num = static_cast<ledc_timer_t>((this->channel_ % 8) / 2);
|
||||||
auto chan_num = static_cast<ledc_channel_t>(this->channel_ % 8);
|
auto chan_num = static_cast<ledc_channel_t>(this->channel_ % 8);
|
||||||
@@ -175,7 +145,6 @@ void LEDCOutput::setup() {
|
|||||||
ledc_channel_config(&chan_conf);
|
ledc_channel_config(&chan_conf);
|
||||||
this->initialized_ = true;
|
this->initialized_ = true;
|
||||||
this->status_clear_error();
|
this->status_clear_error();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LEDCOutput::dump_config() {
|
void LEDCOutput::dump_config() {
|
||||||
@@ -208,38 +177,7 @@ void LEDCOutput::update_frequency(float frequency) {
|
|||||||
}
|
}
|
||||||
this->bit_depth_ = bit_depth_opt.value_or(8);
|
this->bit_depth_ = bit_depth_opt.value_or(8);
|
||||||
this->frequency_ = frequency;
|
this->frequency_ = frequency;
|
||||||
#ifdef USE_ARDUINO
|
|
||||||
ESP_LOGV(TAG, "Using Arduino API - Trying to define channel, frequency and bit depth");
|
|
||||||
u_int32_t configured_frequency = 0;
|
|
||||||
|
|
||||||
// Configure LEDC channel, frequency and bit depth with fallback
|
|
||||||
int attempt_count_max = SETUP_ATTEMPT_COUNT_MAX;
|
|
||||||
while (attempt_count_max > 0 && configured_frequency == 0) {
|
|
||||||
ESP_LOGV(TAG, "Initializing channel %u with frequency %.1f and bit depth of %u", this->channel_, this->frequency_,
|
|
||||||
this->bit_depth_);
|
|
||||||
configured_frequency = ledcSetup(this->channel_, frequency, this->bit_depth_);
|
|
||||||
if (configured_frequency != 0) {
|
|
||||||
this->initialized_ = true;
|
|
||||||
this->status_clear_error();
|
|
||||||
ESP_LOGV(TAG, "Configured frequency: %u with bit depth: %u", configured_frequency, this->bit_depth_);
|
|
||||||
} else {
|
|
||||||
ESP_LOGW(TAG, "Unable to initialize channel %u with frequency %.1f and bit depth of %u", this->channel_,
|
|
||||||
this->frequency_, this->bit_depth_);
|
|
||||||
// try again with a lower bit depth
|
|
||||||
this->bit_depth_--;
|
|
||||||
}
|
|
||||||
attempt_count_max--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configured_frequency == 0) {
|
|
||||||
ESP_LOGE(TAG, "Permanently failed to initialize channel %u with frequency %.1f and bit depth of %u", this->channel_,
|
|
||||||
this->frequency_, this->bit_depth_);
|
|
||||||
this->status_set_error();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // USE_ARDUINO
|
|
||||||
#ifdef USE_ESP_IDF
|
|
||||||
if (!this->initialized_) {
|
if (!this->initialized_) {
|
||||||
ESP_LOGW(TAG, "Not yet initialized");
|
ESP_LOGW(TAG, "Not yet initialized");
|
||||||
return;
|
return;
|
||||||
@@ -259,7 +197,7 @@ void LEDCOutput::update_frequency(float frequency) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->status_clear_error();
|
this->status_clear_error();
|
||||||
#endif
|
|
||||||
// re-apply duty
|
// re-apply duty
|
||||||
this->write_state(this->duty_);
|
this->write_state(this->duty_);
|
||||||
}
|
}
|
||||||
|
@@ -324,7 +324,10 @@ async def to_code(config):
|
|||||||
if CORE.using_arduino:
|
if CORE.using_arduino:
|
||||||
if config[CONF_HARDWARE_UART] == USB_CDC:
|
if config[CONF_HARDWARE_UART] == USB_CDC:
|
||||||
cg.add_build_flag("-DARDUINO_USB_CDC_ON_BOOT=1")
|
cg.add_build_flag("-DARDUINO_USB_CDC_ON_BOOT=1")
|
||||||
if CORE.is_esp32 and get_esp32_variant() == VARIANT_ESP32C3:
|
if CORE.is_esp32 and get_esp32_variant() in (
|
||||||
|
VARIANT_ESP32C3,
|
||||||
|
VARIANT_ESP32C6,
|
||||||
|
):
|
||||||
cg.add_build_flag("-DARDUINO_USB_MODE=1")
|
cg.add_build_flag("-DARDUINO_USB_MODE=1")
|
||||||
|
|
||||||
if CORE.using_esp_idf:
|
if CORE.using_esp_idf:
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace md5 {
|
namespace md5 {
|
||||||
|
|
||||||
#if defined(USE_ARDUINO) && !defined(USE_RP2040)
|
#if defined(USE_ARDUINO) && !defined(USE_RP2040) && !defined(USE_ESP32)
|
||||||
void MD5Digest::init() {
|
void MD5Digest::init() {
|
||||||
memset(this->digest_, 0, 16);
|
memset(this->digest_, 0, 16);
|
||||||
MD5Init(&this->ctx_);
|
MD5Init(&this->ctx_);
|
||||||
@@ -18,7 +18,7 @@ void MD5Digest::add(const uint8_t *data, size_t len) { MD5Update(&this->ctx_, da
|
|||||||
void MD5Digest::calculate() { MD5Final(this->digest_, &this->ctx_); }
|
void MD5Digest::calculate() { MD5Final(this->digest_, &this->ctx_); }
|
||||||
#endif // USE_ARDUINO && !USE_RP2040
|
#endif // USE_ARDUINO && !USE_RP2040
|
||||||
|
|
||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP32
|
||||||
void MD5Digest::init() {
|
void MD5Digest::init() {
|
||||||
memset(this->digest_, 0, 16);
|
memset(this->digest_, 0, 16);
|
||||||
esp_rom_md5_init(&this->ctx_);
|
esp_rom_md5_init(&this->ctx_);
|
||||||
@@ -27,7 +27,7 @@ void MD5Digest::init() {
|
|||||||
void MD5Digest::add(const uint8_t *data, size_t len) { esp_rom_md5_update(&this->ctx_, data, len); }
|
void MD5Digest::add(const uint8_t *data, size_t len) { esp_rom_md5_update(&this->ctx_, data, len); }
|
||||||
|
|
||||||
void MD5Digest::calculate() { esp_rom_md5_final(this->digest_, &this->ctx_); }
|
void MD5Digest::calculate() { esp_rom_md5_final(this->digest_, &this->ctx_); }
|
||||||
#endif // USE_ESP_IDF
|
#endif // USE_ESP32
|
||||||
|
|
||||||
#ifdef USE_RP2040
|
#ifdef USE_RP2040
|
||||||
void MD5Digest::init() {
|
void MD5Digest::init() {
|
||||||
|
@@ -3,16 +3,11 @@
|
|||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#ifdef USE_MD5
|
#ifdef USE_MD5
|
||||||
|
|
||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP32
|
||||||
#include "esp_rom_md5.h"
|
#include "esp_rom_md5.h"
|
||||||
#define MD5_CTX_TYPE md5_context_t
|
#define MD5_CTX_TYPE md5_context_t
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_ARDUINO) && defined(USE_ESP32)
|
|
||||||
#include "rom/md5_hash.h"
|
|
||||||
#define MD5_CTX_TYPE MD5Context
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_ARDUINO) && defined(USE_ESP8266)
|
#if defined(USE_ARDUINO) && defined(USE_ESP8266)
|
||||||
#include <md5.h>
|
#include <md5.h>
|
||||||
#define MD5_CTX_TYPE md5_context_t
|
#define MD5_CTX_TYPE md5_context_t
|
||||||
|
@@ -27,7 +27,7 @@ void VADModel::log_model_config() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool StreamingModel::load_model_() {
|
bool StreamingModel::load_model_() {
|
||||||
RAMAllocator<uint8_t> arena_allocator(RAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> arena_allocator;
|
||||||
|
|
||||||
if (this->tensor_arena_ == nullptr) {
|
if (this->tensor_arena_ == nullptr) {
|
||||||
this->tensor_arena_ = arena_allocator.allocate(this->tensor_arena_size_);
|
this->tensor_arena_ = arena_allocator.allocate(this->tensor_arena_size_);
|
||||||
@@ -96,7 +96,7 @@ bool StreamingModel::load_model_() {
|
|||||||
void StreamingModel::unload_model() {
|
void StreamingModel::unload_model() {
|
||||||
this->interpreter_.reset();
|
this->interpreter_.reset();
|
||||||
|
|
||||||
RAMAllocator<uint8_t> arena_allocator(RAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> arena_allocator;
|
||||||
|
|
||||||
if (this->tensor_arena_ != nullptr) {
|
if (this->tensor_arena_ != nullptr) {
|
||||||
arena_allocator.deallocate(this->tensor_arena_, this->tensor_arena_size_);
|
arena_allocator.deallocate(this->tensor_arena_, this->tensor_arena_size_);
|
||||||
|
@@ -215,4 +215,7 @@ async def to_code(config):
|
|||||||
|
|
||||||
# https://github.com/Makuna/NeoPixelBus/blob/master/library.json
|
# https://github.com/Makuna/NeoPixelBus/blob/master/library.json
|
||||||
# Version Listed Here: https://registry.platformio.org/libraries/makuna/NeoPixelBus/versions
|
# Version Listed Here: https://registry.platformio.org/libraries/makuna/NeoPixelBus/versions
|
||||||
|
if CORE.is_esp32:
|
||||||
|
cg.add_library("makuna/NeoPixelBus", "2.8.0")
|
||||||
|
else:
|
||||||
cg.add_library("makuna/NeoPixelBus", "2.7.3")
|
cg.add_library("makuna/NeoPixelBus", "2.7.3")
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef USE_ARDUINO
|
#if defined(USE_ARDUINO) && !defined(CLANG_TIDY)
|
||||||
|
|
||||||
#include "esphome/core/color.h"
|
#include "esphome/core/color.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
|
@@ -2,7 +2,7 @@ import esphome.codegen as cg
|
|||||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT
|
from esphome.const import CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT
|
||||||
from esphome.core import CORE
|
from esphome.core import CORE, coroutine_with_priority
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
AUTO_LOAD = ["mdns"]
|
AUTO_LOAD = ["mdns"]
|
||||||
@@ -36,8 +36,11 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@coroutine_with_priority(201.0)
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
cg.add_define("USE_NETWORK")
|
cg.add_define("USE_NETWORK")
|
||||||
|
if CORE.using_arduino and CORE.is_esp32:
|
||||||
|
cg.add_library("Networking", None)
|
||||||
if (enable_ipv6 := config.get(CONF_ENABLE_IPV6, None)) is not None:
|
if (enable_ipv6 := config.get(CONF_ENABLE_IPV6, None)) is not None:
|
||||||
cg.add_define("USE_NETWORK_IPV6", enable_ipv6)
|
cg.add_define("USE_NETWORK_IPV6", enable_ipv6)
|
||||||
if enable_ipv6:
|
if enable_ipv6:
|
||||||
|
@@ -56,6 +56,7 @@ struct IPAddress {
|
|||||||
IP_ADDR4(&ip_addr_, first, second, third, fourth);
|
IP_ADDR4(&ip_addr_, first, second, third, fourth);
|
||||||
}
|
}
|
||||||
IPAddress(const ip_addr_t *other_ip) { ip_addr_copy(ip_addr_, *other_ip); }
|
IPAddress(const ip_addr_t *other_ip) { ip_addr_copy(ip_addr_, *other_ip); }
|
||||||
|
IPAddress(const char *in_address) { ipaddr_aton(in_address, &ip_addr_); }
|
||||||
IPAddress(const std::string &in_address) { ipaddr_aton(in_address.c_str(), &ip_addr_); }
|
IPAddress(const std::string &in_address) { ipaddr_aton(in_address.c_str(), &ip_addr_); }
|
||||||
IPAddress(ip4_addr_t *other_ip) {
|
IPAddress(ip4_addr_t *other_ip) {
|
||||||
memcpy((void *) &ip_addr_, (void *) other_ip, sizeof(ip4_addr_t));
|
memcpy((void *) &ip_addr_, (void *) other_ip, sizeof(ip4_addr_t));
|
||||||
|
@@ -150,7 +150,7 @@ async def to_code(config):
|
|||||||
cg.add_define("USE_NEXTION_TFT_UPLOAD")
|
cg.add_define("USE_NEXTION_TFT_UPLOAD")
|
||||||
cg.add(var.set_tft_url(config[CONF_TFT_URL]))
|
cg.add(var.set_tft_url(config[CONF_TFT_URL]))
|
||||||
if CORE.is_esp32 and CORE.using_arduino:
|
if CORE.is_esp32 and CORE.using_arduino:
|
||||||
cg.add_library("WiFiClientSecure", None)
|
cg.add_library("NetworkClientSecure", None)
|
||||||
cg.add_library("HTTPClient", None)
|
cg.add_library("HTTPClient", None)
|
||||||
elif CORE.is_esp32 and CORE.using_esp_idf:
|
elif CORE.is_esp32 and CORE.using_esp_idf:
|
||||||
esp32.add_idf_sdkconfig_option("CONFIG_ESP_TLS_INSECURE", True)
|
esp32.add_idf_sdkconfig_option("CONFIG_ESP_TLS_INSECURE", True)
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
#include "nextion.h"
|
#include "nextion.h"
|
||||||
#include "esphome/core/util.h"
|
|
||||||
#include "esphome/core/log.h"
|
|
||||||
#include "esphome/core/application.h"
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
#include "esphome/core/application.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace nextion {
|
namespace nextion {
|
||||||
@@ -33,6 +33,7 @@ bool Nextion::send_command_(const std::string &command) {
|
|||||||
|
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||||
if (!this->ignore_is_setup_ && !this->command_pacer_.can_send()) {
|
if (!this->ignore_is_setup_ && !this->command_pacer_.can_send()) {
|
||||||
|
ESP_LOGN(TAG, "Command spacing: delaying command '%s'", command.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif // USE_NEXTION_COMMAND_SPACING
|
#endif // USE_NEXTION_COMMAND_SPACING
|
||||||
@@ -43,10 +44,6 @@ bool Nextion::send_command_(const std::string &command) {
|
|||||||
const uint8_t to_send[3] = {0xFF, 0xFF, 0xFF};
|
const uint8_t to_send[3] = {0xFF, 0xFF, 0xFF};
|
||||||
this->write_array(to_send, sizeof(to_send));
|
this->write_array(to_send, sizeof(to_send));
|
||||||
|
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
|
||||||
this->command_pacer_.mark_sent();
|
|
||||||
#endif // USE_NEXTION_COMMAND_SPACING
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,12 +374,6 @@ void Nextion::process_nextion_commands_() {
|
|||||||
size_t commands_processed = 0;
|
size_t commands_processed = 0;
|
||||||
#endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
#endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||||
|
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
|
||||||
if (!this->command_pacer_.can_send()) {
|
|
||||||
return; // Will try again in next loop iteration
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t to_process_length = 0;
|
size_t to_process_length = 0;
|
||||||
std::string to_process;
|
std::string to_process;
|
||||||
|
|
||||||
@@ -430,6 +421,7 @@ void Nextion::process_nextion_commands_() {
|
|||||||
}
|
}
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||||
this->command_pacer_.mark_sent(); // Here is where we should mark the command as sent
|
this->command_pacer_.mark_sent(); // Here is where we should mark the command as sent
|
||||||
|
ESP_LOGN(TAG, "Command spacing: marked command sent at %u ms", millis());
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 0x02: // invalid Component ID or name was used
|
case 0x02: // invalid Component ID or name was used
|
||||||
@@ -1011,7 +1003,7 @@ void Nextion::add_no_result_to_queue_(const std::string &variable_name) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
RAMAllocator<nextion::NextionQueue> allocator;
|
||||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||||
if (nextion_queue == nullptr) {
|
if (nextion_queue == nullptr) {
|
||||||
ESP_LOGW(TAG, "Queue alloc failed");
|
ESP_LOGW(TAG, "Queue alloc failed");
|
||||||
@@ -1167,7 +1159,7 @@ void Nextion::add_to_get_queue(NextionComponentBase *component) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
RAMAllocator<nextion::NextionQueue> allocator;
|
||||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||||
if (nextion_queue == nullptr) {
|
if (nextion_queue == nullptr) {
|
||||||
ESP_LOGW(TAG, "Queue alloc failed");
|
ESP_LOGW(TAG, "Queue alloc failed");
|
||||||
@@ -1199,7 +1191,7 @@ void Nextion::add_addt_command_to_queue(NextionComponentBase *component) {
|
|||||||
if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping())
|
if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
RAMAllocator<nextion::NextionQueue> allocator;
|
||||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||||
if (nextion_queue == nullptr) {
|
if (nextion_queue == nullptr) {
|
||||||
ESP_LOGW(TAG, "Queue alloc failed");
|
ESP_LOGW(TAG, "Queue alloc failed");
|
||||||
|
@@ -3,12 +3,12 @@
|
|||||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
#include "esphome/components/network/util.h"
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/core/util.h"
|
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "esphome/components/network/util.h"
|
#include "esphome/core/util.h"
|
||||||
#include <cinttypes>
|
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
#include <esp_heap_caps.h>
|
#include <esp_heap_caps.h>
|
||||||
@@ -52,7 +52,7 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate the buffer dynamically
|
// Allocate the buffer dynamically
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
uint8_t *buffer = allocator.allocate(4096);
|
uint8_t *buffer = allocator.allocate(4096);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
ESP_LOGE(TAG, "Buffer alloc failed");
|
ESP_LOGE(TAG, "Buffer alloc failed");
|
||||||
|
@@ -3,14 +3,14 @@
|
|||||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP_IDF
|
||||||
|
|
||||||
#include "esphome/core/application.h"
|
|
||||||
#include "esphome/core/defines.h"
|
|
||||||
#include "esphome/core/util.h"
|
|
||||||
#include "esphome/core/log.h"
|
|
||||||
#include "esphome/components/network/util.h"
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <esp_heap_caps.h>
|
#include <esp_heap_caps.h>
|
||||||
#include <esp_http_client.h>
|
#include <esp_http_client.h>
|
||||||
|
#include <cinttypes>
|
||||||
|
#include "esphome/components/network/util.h"
|
||||||
|
#include "esphome/core/application.h"
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace nextion {
|
namespace nextion {
|
||||||
@@ -51,7 +51,7 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate the buffer dynamically
|
// Allocate the buffer dynamically
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
uint8_t *buffer = allocator.allocate(4096);
|
uint8_t *buffer = allocator.allocate(4096);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
ESP_LOGE(TAG, "Buffer alloc failed");
|
ESP_LOGE(TAG, "Buffer alloc failed");
|
||||||
|
@@ -224,7 +224,7 @@ void OnlineImage::loop() {
|
|||||||
this->height_ = buffer_height_;
|
this->height_ = buffer_height_;
|
||||||
ESP_LOGD(TAG, "Image fully downloaded, read %zu bytes, width/height = %d/%d", this->downloader_->get_bytes_read(),
|
ESP_LOGD(TAG, "Image fully downloaded, read %zu bytes, width/height = %d/%d", this->downloader_->get_bytes_read(),
|
||||||
this->width_, this->height_);
|
this->width_, this->height_);
|
||||||
ESP_LOGD(TAG, "Total time: %lds", ::time(nullptr) - this->start_time_);
|
ESP_LOGD(TAG, "Total time: %" PRIu32 "s", (uint32_t) (::time(nullptr) - this->start_time_));
|
||||||
this->etag_ = this->downloader_->get_response_header(ETAG_HEADER_NAME);
|
this->etag_ = this->downloader_->get_response_header(ETAG_HEADER_NAME);
|
||||||
this->last_modified_ = this->downloader_->get_response_header(LAST_MODIFIED_HEADER_NAME);
|
this->last_modified_ = this->downloader_->get_response_header(LAST_MODIFIED_HEADER_NAME);
|
||||||
this->download_finished_callback_.call(false);
|
this->download_finished_callback_.call(false);
|
||||||
|
@@ -8,27 +8,6 @@ namespace remote_base {
|
|||||||
|
|
||||||
static const char *const TAG = "remote_base";
|
static const char *const TAG = "remote_base";
|
||||||
|
|
||||||
#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
RemoteRMTChannel::RemoteRMTChannel(uint8_t mem_block_num) : mem_block_num_(mem_block_num) {
|
|
||||||
static rmt_channel_t next_rmt_channel = RMT_CHANNEL_0;
|
|
||||||
this->channel_ = next_rmt_channel;
|
|
||||||
next_rmt_channel = rmt_channel_t(int(next_rmt_channel) + mem_block_num);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteRMTChannel::RemoteRMTChannel(rmt_channel_t channel, uint8_t mem_block_num)
|
|
||||||
: channel_(channel), mem_block_num_(mem_block_num) {}
|
|
||||||
|
|
||||||
void RemoteRMTChannel::config_rmt(rmt_config_t &rmt) {
|
|
||||||
if (rmt_channel_t(int(this->channel_) + this->mem_block_num_) > RMT_CHANNEL_MAX) {
|
|
||||||
this->mem_block_num_ = int(RMT_CHANNEL_MAX) - int(this->channel_);
|
|
||||||
ESP_LOGW(TAG, "Not enough RMT memory blocks available, reduced to %i blocks.", this->mem_block_num_);
|
|
||||||
}
|
|
||||||
rmt.channel = this->channel_;
|
|
||||||
rmt.clk_div = this->clock_divider_;
|
|
||||||
rmt.mem_block_num = this->mem_block_num_;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* RemoteReceiveData */
|
/* RemoteReceiveData */
|
||||||
|
|
||||||
bool RemoteReceiveData::peek_mark(uint32_t length, uint32_t offset) const {
|
bool RemoteReceiveData::peek_mark(uint32_t length, uint32_t offset) const {
|
||||||
|
@@ -8,10 +8,6 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/hal.h"
|
#include "esphome/core/hal.h"
|
||||||
|
|
||||||
#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
#include <driver/rmt.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace remote_base {
|
namespace remote_base {
|
||||||
|
|
||||||
@@ -112,43 +108,21 @@ class RemoteComponentBase {
|
|||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
class RemoteRMTChannel {
|
class RemoteRMTChannel {
|
||||||
public:
|
public:
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
void set_clock_resolution(uint32_t clock_resolution) { this->clock_resolution_ = clock_resolution; }
|
void set_clock_resolution(uint32_t clock_resolution) { this->clock_resolution_ = clock_resolution; }
|
||||||
void set_rmt_symbols(uint32_t rmt_symbols) { this->rmt_symbols_ = rmt_symbols; }
|
void set_rmt_symbols(uint32_t rmt_symbols) { this->rmt_symbols_ = rmt_symbols; }
|
||||||
#else
|
|
||||||
explicit RemoteRMTChannel(uint8_t mem_block_num = 1);
|
|
||||||
explicit RemoteRMTChannel(rmt_channel_t channel, uint8_t mem_block_num = 1);
|
|
||||||
|
|
||||||
void config_rmt(rmt_config_t &rmt);
|
|
||||||
void set_clock_divider(uint8_t clock_divider) { this->clock_divider_ = clock_divider; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t from_microseconds_(uint32_t us) {
|
uint32_t from_microseconds_(uint32_t us) {
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
const uint32_t ticks_per_ten_us = this->clock_resolution_ / 100000u;
|
const uint32_t ticks_per_ten_us = this->clock_resolution_ / 100000u;
|
||||||
#else
|
|
||||||
const uint32_t ticks_per_ten_us = 80000000u / this->clock_divider_ / 100000u;
|
|
||||||
#endif
|
|
||||||
return us * ticks_per_ten_us / 10;
|
return us * ticks_per_ten_us / 10;
|
||||||
}
|
}
|
||||||
uint32_t to_microseconds_(uint32_t ticks) {
|
uint32_t to_microseconds_(uint32_t ticks) {
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
const uint32_t ticks_per_ten_us = this->clock_resolution_ / 100000u;
|
const uint32_t ticks_per_ten_us = this->clock_resolution_ / 100000u;
|
||||||
#else
|
|
||||||
const uint32_t ticks_per_ten_us = 80000000u / this->clock_divider_ / 100000u;
|
|
||||||
#endif
|
|
||||||
return (ticks * 10) / ticks_per_ten_us;
|
return (ticks * 10) / ticks_per_ten_us;
|
||||||
}
|
}
|
||||||
RemoteComponentBase *remote_base_;
|
RemoteComponentBase *remote_base_;
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
uint32_t clock_resolution_{1000000};
|
uint32_t clock_resolution_{1000000};
|
||||||
uint32_t rmt_symbols_;
|
uint32_t rmt_symbols_;
|
||||||
#else
|
|
||||||
rmt_channel_t channel_{RMT_CHANNEL_0};
|
|
||||||
uint8_t mem_block_num_;
|
|
||||||
uint8_t clock_divider_{80};
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -4,15 +4,12 @@ from esphome.components import esp32, esp32_rmt, remote_base
|
|||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_BUFFER_SIZE,
|
CONF_BUFFER_SIZE,
|
||||||
CONF_CLOCK_DIVIDER,
|
|
||||||
CONF_CLOCK_RESOLUTION,
|
CONF_CLOCK_RESOLUTION,
|
||||||
CONF_DUMP,
|
CONF_DUMP,
|
||||||
CONF_FILTER,
|
CONF_FILTER,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_IDLE,
|
CONF_IDLE,
|
||||||
CONF_MEMORY_BLOCKS,
|
|
||||||
CONF_PIN,
|
CONF_PIN,
|
||||||
CONF_RMT_CHANNEL,
|
|
||||||
CONF_RMT_SYMBOLS,
|
CONF_RMT_SYMBOLS,
|
||||||
CONF_TOLERANCE,
|
CONF_TOLERANCE,
|
||||||
CONF_TYPE,
|
CONF_TYPE,
|
||||||
@@ -103,49 +100,36 @@ CONFIG_SCHEMA = remote_base.validate_triggers(
|
|||||||
cv.positive_time_period_microseconds,
|
cv.positive_time_period_microseconds,
|
||||||
cv.Range(max=TimePeriod(microseconds=4294967295)),
|
cv.Range(max=TimePeriod(microseconds=4294967295)),
|
||||||
),
|
),
|
||||||
cv.SplitDefault(CONF_CLOCK_DIVIDER, esp32_arduino=80): cv.All(
|
|
||||||
cv.only_on_esp32,
|
|
||||||
cv.only_with_arduino,
|
|
||||||
cv.int_range(min=1, max=255),
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_CLOCK_RESOLUTION): cv.All(
|
cv.Optional(CONF_CLOCK_RESOLUTION): cv.All(
|
||||||
cv.only_on_esp32,
|
cv.only_on_esp32,
|
||||||
cv.only_with_esp_idf,
|
|
||||||
esp32_rmt.validate_clock_resolution(),
|
esp32_rmt.validate_clock_resolution(),
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_IDLE, default="10ms"): cv.All(
|
cv.Optional(CONF_IDLE, default="10ms"): cv.All(
|
||||||
cv.positive_time_period_microseconds,
|
cv.positive_time_period_microseconds,
|
||||||
cv.Range(max=TimePeriod(microseconds=4294967295)),
|
cv.Range(max=TimePeriod(microseconds=4294967295)),
|
||||||
),
|
),
|
||||||
cv.SplitDefault(CONF_MEMORY_BLOCKS, esp32_arduino=3): cv.All(
|
|
||||||
cv.only_with_arduino, cv.int_range(min=1, max=8)
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_RMT_CHANNEL): cv.All(
|
|
||||||
cv.only_with_arduino, esp32_rmt.validate_rmt_channel(tx=False)
|
|
||||||
),
|
|
||||||
cv.SplitDefault(
|
cv.SplitDefault(
|
||||||
CONF_RMT_SYMBOLS,
|
CONF_RMT_SYMBOLS,
|
||||||
esp32_idf=192,
|
esp32=192,
|
||||||
esp32_s2_idf=192,
|
esp32_s2=192,
|
||||||
esp32_s3_idf=192,
|
esp32_s3=192,
|
||||||
esp32_p4_idf=192,
|
esp32_p4=192,
|
||||||
esp32_c3_idf=96,
|
esp32_c3=96,
|
||||||
esp32_c5_idf=96,
|
esp32_c5=96,
|
||||||
esp32_c6_idf=96,
|
esp32_c6=96,
|
||||||
esp32_h2_idf=96,
|
esp32_h2=96,
|
||||||
): cv.All(cv.only_with_esp_idf, cv.int_range(min=2)),
|
): cv.All(cv.only_on_esp32, cv.int_range(min=2)),
|
||||||
cv.Optional(CONF_FILTER_SYMBOLS): cv.All(
|
cv.Optional(CONF_FILTER_SYMBOLS): cv.All(
|
||||||
cv.only_with_esp_idf, cv.int_range(min=0)
|
cv.only_on_esp32, cv.int_range(min=0)
|
||||||
),
|
),
|
||||||
cv.SplitDefault(
|
cv.SplitDefault(
|
||||||
CONF_RECEIVE_SYMBOLS,
|
CONF_RECEIVE_SYMBOLS,
|
||||||
esp32_idf=192,
|
esp32=192,
|
||||||
): cv.All(cv.only_with_esp_idf, cv.int_range(min=2)),
|
): cv.All(cv.only_on_esp32, cv.int_range(min=2)),
|
||||||
cv.Optional(CONF_USE_DMA): cv.All(
|
cv.Optional(CONF_USE_DMA): cv.All(
|
||||||
esp32.only_on_variant(
|
esp32.only_on_variant(
|
||||||
supported=[esp32.const.VARIANT_ESP32S3, esp32.const.VARIANT_ESP32P4]
|
supported=[esp32.const.VARIANT_ESP32S3, esp32.const.VARIANT_ESP32P4]
|
||||||
),
|
),
|
||||||
cv.only_with_esp_idf,
|
|
||||||
cv.boolean,
|
cv.boolean,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -156,7 +140,6 @@ CONFIG_SCHEMA = remote_base.validate_triggers(
|
|||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
pin = await cg.gpio_pin_expression(config[CONF_PIN])
|
pin = await cg.gpio_pin_expression(config[CONF_PIN])
|
||||||
if CORE.is_esp32:
|
if CORE.is_esp32:
|
||||||
if esp32_rmt.use_new_rmt_driver():
|
|
||||||
var = cg.new_Pvariable(config[CONF_ID], pin)
|
var = cg.new_Pvariable(config[CONF_ID], pin)
|
||||||
cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS]))
|
cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS]))
|
||||||
cg.add(var.set_receive_symbols(config[CONF_RECEIVE_SYMBOLS]))
|
cg.add(var.set_receive_symbols(config[CONF_RECEIVE_SYMBOLS]))
|
||||||
@@ -166,14 +149,6 @@ async def to_code(config):
|
|||||||
cg.add(var.set_clock_resolution(config[CONF_CLOCK_RESOLUTION]))
|
cg.add(var.set_clock_resolution(config[CONF_CLOCK_RESOLUTION]))
|
||||||
if CONF_FILTER_SYMBOLS in config:
|
if CONF_FILTER_SYMBOLS in config:
|
||||||
cg.add(var.set_filter_symbols(config[CONF_FILTER_SYMBOLS]))
|
cg.add(var.set_filter_symbols(config[CONF_FILTER_SYMBOLS]))
|
||||||
else:
|
|
||||||
if (rmt_channel := config.get(CONF_RMT_CHANNEL, None)) is not None:
|
|
||||||
var = cg.new_Pvariable(
|
|
||||||
config[CONF_ID], pin, rmt_channel, config[CONF_MEMORY_BLOCKS]
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
var = cg.new_Pvariable(config[CONF_ID], pin, config[CONF_MEMORY_BLOCKS])
|
|
||||||
cg.add(var.set_clock_divider(config[CONF_CLOCK_DIVIDER]))
|
|
||||||
else:
|
else:
|
||||||
var = cg.new_Pvariable(config[CONF_ID], pin)
|
var = cg.new_Pvariable(config[CONF_ID], pin)
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
|
||||||
#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
#if defined(USE_ESP32)
|
||||||
#include <driver/rmt_rx.h>
|
#include <driver/rmt_rx.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ struct RemoteReceiverComponentStore {
|
|||||||
uint32_t filter_us{10};
|
uint32_t filter_us{10};
|
||||||
ISRInternalGPIOPin pin;
|
ISRInternalGPIOPin pin;
|
||||||
};
|
};
|
||||||
#elif defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
#elif defined(USE_ESP32)
|
||||||
struct RemoteReceiverComponentStore {
|
struct RemoteReceiverComponentStore {
|
||||||
/// Stores RMT symbols and rx done event data
|
/// Stores RMT symbols and rx done event data
|
||||||
volatile uint8_t *buffer{nullptr};
|
volatile uint8_t *buffer{nullptr};
|
||||||
@@ -55,21 +55,13 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase,
|
|||||||
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
RemoteReceiverComponent(InternalGPIOPin *pin, uint8_t mem_block_num = 1)
|
|
||||||
: RemoteReceiverBase(pin), remote_base::RemoteRMTChannel(mem_block_num) {}
|
|
||||||
|
|
||||||
RemoteReceiverComponent(InternalGPIOPin *pin, rmt_channel_t channel, uint8_t mem_block_num = 1)
|
|
||||||
: RemoteReceiverBase(pin), remote_base::RemoteRMTChannel(channel, mem_block_num) {}
|
|
||||||
#else
|
|
||||||
RemoteReceiverComponent(InternalGPIOPin *pin) : RemoteReceiverBase(pin) {}
|
RemoteReceiverComponent(InternalGPIOPin *pin) : RemoteReceiverBase(pin) {}
|
||||||
#endif
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
void loop() override;
|
void loop() override;
|
||||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
|
|
||||||
#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
#ifdef USE_ESP32
|
||||||
void set_filter_symbols(uint32_t filter_symbols) { this->filter_symbols_ = filter_symbols; }
|
void set_filter_symbols(uint32_t filter_symbols) { this->filter_symbols_ = filter_symbols; }
|
||||||
void set_receive_symbols(uint32_t receive_symbols) { this->receive_symbols_ = receive_symbols; }
|
void set_receive_symbols(uint32_t receive_symbols) { this->receive_symbols_ = receive_symbols; }
|
||||||
void set_with_dma(bool with_dma) { this->with_dma_ = with_dma; }
|
void set_with_dma(bool with_dma) { this->with_dma_ = with_dma; }
|
||||||
@@ -80,21 +72,16 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase,
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
void decode_rmt_(rmt_symbol_word_t *item, size_t item_count);
|
void decode_rmt_(rmt_symbol_word_t *item, size_t item_count);
|
||||||
rmt_channel_handle_t channel_{NULL};
|
rmt_channel_handle_t channel_{NULL};
|
||||||
uint32_t filter_symbols_{0};
|
uint32_t filter_symbols_{0};
|
||||||
uint32_t receive_symbols_{0};
|
uint32_t receive_symbols_{0};
|
||||||
bool with_dma_{false};
|
bool with_dma_{false};
|
||||||
#else
|
|
||||||
void decode_rmt_(rmt_item32_t *item, size_t item_count);
|
|
||||||
RingbufHandle_t ringbuf_;
|
|
||||||
#endif
|
|
||||||
esp_err_t error_code_{ESP_OK};
|
esp_err_t error_code_{ESP_OK};
|
||||||
std::string error_string_{""};
|
std::string error_string_{""};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || (defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5)
|
#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_ESP32)
|
||||||
RemoteReceiverComponentStore store_;
|
RemoteReceiverComponentStore store_;
|
||||||
HighFrequencyLoopRequester high_freq_;
|
HighFrequencyLoopRequester high_freq_;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -14,7 +14,6 @@ static const uint32_t RMT_CLK_FREQ = 32000000;
|
|||||||
static const uint32_t RMT_CLK_FREQ = 80000000;
|
static const uint32_t RMT_CLK_FREQ = 80000000;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
static bool IRAM_ATTR HOT rmt_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *event, void *arg) {
|
static bool IRAM_ATTR HOT rmt_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *event, void *arg) {
|
||||||
RemoteReceiverComponentStore *store = (RemoteReceiverComponentStore *) arg;
|
RemoteReceiverComponentStore *store = (RemoteReceiverComponentStore *) arg;
|
||||||
rmt_rx_done_event_data_t *event_buffer = (rmt_rx_done_event_data_t *) (store->buffer + store->buffer_write);
|
rmt_rx_done_event_data_t *event_buffer = (rmt_rx_done_event_data_t *) (store->buffer + store->buffer_write);
|
||||||
@@ -37,11 +36,9 @@ static bool IRAM_ATTR HOT rmt_callback(rmt_channel_handle_t channel, const rmt_r
|
|||||||
store->buffer_write = next_write;
|
store->buffer_write = next_write;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void RemoteReceiverComponent::setup() {
|
void RemoteReceiverComponent::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Running setup");
|
ESP_LOGCONFIG(TAG, "Running setup");
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
rmt_rx_channel_config_t channel;
|
rmt_rx_channel_config_t channel;
|
||||||
memset(&channel, 0, sizeof(channel));
|
memset(&channel, 0, sizeof(channel));
|
||||||
channel.clk_src = RMT_CLK_SRC_DEFAULT;
|
channel.clk_src = RMT_CLK_SRC_DEFAULT;
|
||||||
@@ -105,62 +102,11 @@ void RemoteReceiverComponent::setup() {
|
|||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
this->pin_->setup();
|
|
||||||
rmt_config_t rmt{};
|
|
||||||
this->config_rmt(rmt);
|
|
||||||
rmt.gpio_num = gpio_num_t(this->pin_->get_pin());
|
|
||||||
rmt.rmt_mode = RMT_MODE_RX;
|
|
||||||
if (this->filter_us_ == 0) {
|
|
||||||
rmt.rx_config.filter_en = false;
|
|
||||||
} else {
|
|
||||||
rmt.rx_config.filter_en = true;
|
|
||||||
rmt.rx_config.filter_ticks_thresh = static_cast<uint8_t>(
|
|
||||||
std::min(this->from_microseconds_(this->filter_us_) * this->clock_divider_, (uint32_t) 255));
|
|
||||||
}
|
|
||||||
rmt.rx_config.idle_threshold =
|
|
||||||
static_cast<uint16_t>(std::min(this->from_microseconds_(this->idle_us_), (uint32_t) 65535));
|
|
||||||
|
|
||||||
esp_err_t error = rmt_config(&rmt);
|
|
||||||
if (error != ESP_OK) {
|
|
||||||
this->error_code_ = error;
|
|
||||||
this->error_string_ = "in rmt_config";
|
|
||||||
this->mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = rmt_driver_install(this->channel_, this->buffer_size_, 0);
|
|
||||||
if (error != ESP_OK) {
|
|
||||||
this->error_code_ = error;
|
|
||||||
if (error == ESP_ERR_INVALID_STATE) {
|
|
||||||
this->error_string_ = str_sprintf("RMT channel %i is already in use by another component", this->channel_);
|
|
||||||
} else {
|
|
||||||
this->error_string_ = "in rmt_driver_install";
|
|
||||||
}
|
|
||||||
this->mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
error = rmt_get_ringbuf_handle(this->channel_, &this->ringbuf_);
|
|
||||||
if (error != ESP_OK) {
|
|
||||||
this->error_code_ = error;
|
|
||||||
this->error_string_ = "in rmt_get_ringbuf_handle";
|
|
||||||
this->mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
error = rmt_rx_start(this->channel_, true);
|
|
||||||
if (error != ESP_OK) {
|
|
||||||
this->error_code_ = error;
|
|
||||||
this->error_string_ = "in rmt_rx_start";
|
|
||||||
this->mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteReceiverComponent::dump_config() {
|
void RemoteReceiverComponent::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "Remote Receiver:");
|
ESP_LOGCONFIG(TAG, "Remote Receiver:");
|
||||||
LOG_PIN(" Pin: ", this->pin_);
|
LOG_PIN(" Pin: ", this->pin_);
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
ESP_LOGCONFIG(TAG,
|
ESP_LOGCONFIG(TAG,
|
||||||
" Clock resolution: %" PRIu32 " hz\n"
|
" Clock resolution: %" PRIu32 " hz\n"
|
||||||
" RMT symbols: %" PRIu32 "\n"
|
" RMT symbols: %" PRIu32 "\n"
|
||||||
@@ -172,22 +118,6 @@ void RemoteReceiverComponent::dump_config() {
|
|||||||
this->clock_resolution_, this->rmt_symbols_, this->filter_symbols_, this->receive_symbols_,
|
this->clock_resolution_, this->rmt_symbols_, this->filter_symbols_, this->receive_symbols_,
|
||||||
this->tolerance_, (this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%",
|
this->tolerance_, (this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%",
|
||||||
this->filter_us_, this->idle_us_);
|
this->filter_us_, this->idle_us_);
|
||||||
#else
|
|
||||||
if (this->pin_->digital_read()) {
|
|
||||||
ESP_LOGW(TAG, "Remote Receiver Signal starts with a HIGH value. Usually this means you have to "
|
|
||||||
"invert the signal using 'inverted: True' in the pin schema!");
|
|
||||||
}
|
|
||||||
ESP_LOGCONFIG(TAG,
|
|
||||||
" Channel: %d\n"
|
|
||||||
" RMT memory blocks: %d\n"
|
|
||||||
" Clock divider: %u\n"
|
|
||||||
" Tolerance: %" PRIu32 "%s\n"
|
|
||||||
" Filter out pulses shorter than: %" PRIu32 " us\n"
|
|
||||||
" Signal is done after %" PRIu32 " us of no changes",
|
|
||||||
this->channel_, this->mem_block_num_, this->clock_divider_, this->tolerance_,
|
|
||||||
(this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%", this->filter_us_,
|
|
||||||
this->idle_us_);
|
|
||||||
#endif
|
|
||||||
if (this->is_failed()) {
|
if (this->is_failed()) {
|
||||||
ESP_LOGE(TAG, "Configuring RMT driver failed: %s (%s)", esp_err_to_name(this->error_code_),
|
ESP_LOGE(TAG, "Configuring RMT driver failed: %s (%s)", esp_err_to_name(this->error_code_),
|
||||||
this->error_string_.c_str());
|
this->error_string_.c_str());
|
||||||
@@ -195,7 +125,6 @@ void RemoteReceiverComponent::dump_config() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RemoteReceiverComponent::loop() {
|
void RemoteReceiverComponent::loop() {
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
if (this->store_.error != ESP_OK) {
|
if (this->store_.error != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Receive error");
|
ESP_LOGE(TAG, "Receive error");
|
||||||
this->error_code_ = this->store_.error;
|
this->error_code_ = this->store_.error;
|
||||||
@@ -221,25 +150,9 @@ void RemoteReceiverComponent::loop() {
|
|||||||
this->call_listeners_dumpers_();
|
this->call_listeners_dumpers_();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
size_t len = 0;
|
|
||||||
auto *item = (rmt_item32_t *) xRingbufferReceive(this->ringbuf_, &len, 0);
|
|
||||||
if (item != nullptr) {
|
|
||||||
this->decode_rmt_(item, len / sizeof(rmt_item32_t));
|
|
||||||
vRingbufferReturnItem(this->ringbuf_, item);
|
|
||||||
|
|
||||||
if (!this->temp_.empty()) {
|
|
||||||
this->call_listeners_dumpers_();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
void RemoteReceiverComponent::decode_rmt_(rmt_symbol_word_t *item, size_t item_count) {
|
void RemoteReceiverComponent::decode_rmt_(rmt_symbol_word_t *item, size_t item_count) {
|
||||||
#else
|
|
||||||
void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t item_count) {
|
|
||||||
#endif
|
|
||||||
bool prev_level = false;
|
bool prev_level = false;
|
||||||
bool idle_level = false;
|
bool idle_level = false;
|
||||||
uint32_t prev_length = 0;
|
uint32_t prev_length = 0;
|
||||||
|
@@ -4,14 +4,12 @@ from esphome.components import esp32, esp32_rmt, remote_base
|
|||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_CARRIER_DUTY_PERCENT,
|
CONF_CARRIER_DUTY_PERCENT,
|
||||||
CONF_CLOCK_DIVIDER,
|
|
||||||
CONF_CLOCK_RESOLUTION,
|
CONF_CLOCK_RESOLUTION,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_INVERTED,
|
CONF_INVERTED,
|
||||||
CONF_MODE,
|
CONF_MODE,
|
||||||
CONF_OPEN_DRAIN,
|
CONF_OPEN_DRAIN,
|
||||||
CONF_PIN,
|
CONF_PIN,
|
||||||
CONF_RMT_CHANNEL,
|
|
||||||
CONF_RMT_SYMBOLS,
|
CONF_RMT_SYMBOLS,
|
||||||
CONF_USE_DMA,
|
CONF_USE_DMA,
|
||||||
)
|
)
|
||||||
@@ -38,34 +36,26 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
),
|
),
|
||||||
cv.Optional(CONF_CLOCK_RESOLUTION): cv.All(
|
cv.Optional(CONF_CLOCK_RESOLUTION): cv.All(
|
||||||
cv.only_on_esp32,
|
cv.only_on_esp32,
|
||||||
cv.only_with_esp_idf,
|
|
||||||
esp32_rmt.validate_clock_resolution(),
|
esp32_rmt.validate_clock_resolution(),
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_CLOCK_DIVIDER): cv.All(
|
cv.Optional(CONF_EOT_LEVEL): cv.All(cv.only_on_esp32, cv.boolean),
|
||||||
cv.only_on_esp32, cv.only_with_arduino, cv.int_range(min=1, max=255)
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_EOT_LEVEL): cv.All(cv.only_with_esp_idf, cv.boolean),
|
|
||||||
cv.Optional(CONF_USE_DMA): cv.All(
|
cv.Optional(CONF_USE_DMA): cv.All(
|
||||||
esp32.only_on_variant(
|
esp32.only_on_variant(
|
||||||
supported=[esp32.const.VARIANT_ESP32S3, esp32.const.VARIANT_ESP32P4]
|
supported=[esp32.const.VARIANT_ESP32S3, esp32.const.VARIANT_ESP32P4]
|
||||||
),
|
),
|
||||||
cv.only_with_esp_idf,
|
|
||||||
cv.boolean,
|
cv.boolean,
|
||||||
),
|
),
|
||||||
cv.SplitDefault(
|
cv.SplitDefault(
|
||||||
CONF_RMT_SYMBOLS,
|
CONF_RMT_SYMBOLS,
|
||||||
esp32_idf=64,
|
esp32=64,
|
||||||
esp32_s2_idf=64,
|
esp32_s2=64,
|
||||||
esp32_s3_idf=48,
|
esp32_s3=48,
|
||||||
esp32_p4_idf=48,
|
esp32_p4=48,
|
||||||
esp32_c3_idf=48,
|
esp32_c3=48,
|
||||||
esp32_c5_idf=48,
|
esp32_c5=48,
|
||||||
esp32_c6_idf=48,
|
esp32_c6=48,
|
||||||
esp32_h2_idf=48,
|
esp32_h2=48,
|
||||||
): cv.All(cv.only_with_esp_idf, cv.int_range(min=2)),
|
): cv.All(cv.only_on_esp32, cv.int_range(min=2)),
|
||||||
cv.Optional(CONF_RMT_CHANNEL): cv.All(
|
|
||||||
cv.only_with_arduino, esp32_rmt.validate_rmt_channel(tx=True)
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_ON_TRANSMIT): automation.validate_automation(single=True),
|
cv.Optional(CONF_ON_TRANSMIT): automation.validate_automation(single=True),
|
||||||
cv.Optional(CONF_ON_COMPLETE): automation.validate_automation(single=True),
|
cv.Optional(CONF_ON_COMPLETE): automation.validate_automation(single=True),
|
||||||
}
|
}
|
||||||
@@ -75,7 +65,6 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
pin = await cg.gpio_pin_expression(config[CONF_PIN])
|
pin = await cg.gpio_pin_expression(config[CONF_PIN])
|
||||||
if CORE.is_esp32:
|
if CORE.is_esp32:
|
||||||
if esp32_rmt.use_new_rmt_driver():
|
|
||||||
var = cg.new_Pvariable(config[CONF_ID], pin)
|
var = cg.new_Pvariable(config[CONF_ID], pin)
|
||||||
cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS]))
|
cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS]))
|
||||||
if CONF_CLOCK_RESOLUTION in config:
|
if CONF_CLOCK_RESOLUTION in config:
|
||||||
@@ -91,14 +80,6 @@ async def to_code(config):
|
|||||||
or config[CONF_PIN][CONF_INVERTED]
|
or config[CONF_PIN][CONF_INVERTED]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
if (rmt_channel := config.get(CONF_RMT_CHANNEL, None)) is not None:
|
|
||||||
var = cg.new_Pvariable(config[CONF_ID], pin, rmt_channel)
|
|
||||||
else:
|
|
||||||
var = cg.new_Pvariable(config[CONF_ID], pin)
|
|
||||||
if CONF_CLOCK_DIVIDER in config:
|
|
||||||
cg.add(var.set_clock_divider(config[CONF_CLOCK_DIVIDER]))
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
var = cg.new_Pvariable(config[CONF_ID], pin)
|
var = cg.new_Pvariable(config[CONF_ID], pin)
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
#if defined(USE_ESP32)
|
||||||
#include <driver/rmt_tx.h>
|
#include <driver/rmt_tx.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -20,15 +20,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
RemoteTransmitterComponent(InternalGPIOPin *pin, uint8_t mem_block_num = 1)
|
|
||||||
: remote_base::RemoteTransmitterBase(pin), remote_base::RemoteRMTChannel(mem_block_num) {}
|
|
||||||
|
|
||||||
RemoteTransmitterComponent(InternalGPIOPin *pin, rmt_channel_t channel, uint8_t mem_block_num = 1)
|
|
||||||
: remote_base::RemoteTransmitterBase(pin), remote_base::RemoteRMTChannel(channel, mem_block_num) {}
|
|
||||||
#else
|
|
||||||
explicit RemoteTransmitterComponent(InternalGPIOPin *pin) : remote_base::RemoteTransmitterBase(pin) {}
|
explicit RemoteTransmitterComponent(InternalGPIOPin *pin) : remote_base::RemoteTransmitterBase(pin) {}
|
||||||
#endif
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
|
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
@@ -38,7 +30,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
|
|||||||
|
|
||||||
void set_carrier_duty_percent(uint8_t carrier_duty_percent) { this->carrier_duty_percent_ = carrier_duty_percent; }
|
void set_carrier_duty_percent(uint8_t carrier_duty_percent) { this->carrier_duty_percent_ = carrier_duty_percent; }
|
||||||
|
|
||||||
#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
#if defined(USE_ESP32)
|
||||||
void set_with_dma(bool with_dma) { this->with_dma_ = with_dma; }
|
void set_with_dma(bool with_dma) { this->with_dma_ = with_dma; }
|
||||||
void set_eot_level(bool eot_level) { this->eot_level_ = eot_level; }
|
void set_eot_level(bool eot_level) { this->eot_level_ = eot_level; }
|
||||||
void digital_write(bool value);
|
void digital_write(bool value);
|
||||||
@@ -65,15 +57,11 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
|
|||||||
|
|
||||||
uint32_t current_carrier_frequency_{38000};
|
uint32_t current_carrier_frequency_{38000};
|
||||||
bool initialized_{false};
|
bool initialized_{false};
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
std::vector<rmt_symbol_word_t> rmt_temp_;
|
std::vector<rmt_symbol_word_t> rmt_temp_;
|
||||||
bool with_dma_{false};
|
bool with_dma_{false};
|
||||||
bool eot_level_{false};
|
bool eot_level_{false};
|
||||||
rmt_channel_handle_t channel_{NULL};
|
rmt_channel_handle_t channel_{NULL};
|
||||||
rmt_encoder_handle_t encoder_{NULL};
|
rmt_encoder_handle_t encoder_{NULL};
|
||||||
#else
|
|
||||||
std::vector<rmt_item32_t> rmt_temp_;
|
|
||||||
#endif
|
|
||||||
esp_err_t error_code_{ESP_OK};
|
esp_err_t error_code_{ESP_OK};
|
||||||
std::string error_string_{""};
|
std::string error_string_{""};
|
||||||
bool inverted_{false};
|
bool inverted_{false};
|
||||||
|
@@ -18,18 +18,10 @@ void RemoteTransmitterComponent::setup() {
|
|||||||
|
|
||||||
void RemoteTransmitterComponent::dump_config() {
|
void RemoteTransmitterComponent::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "Remote Transmitter:");
|
ESP_LOGCONFIG(TAG, "Remote Transmitter:");
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
ESP_LOGCONFIG(TAG,
|
ESP_LOGCONFIG(TAG,
|
||||||
" Clock resolution: %" PRIu32 " hz\n"
|
" Clock resolution: %" PRIu32 " hz\n"
|
||||||
" RMT symbols: %" PRIu32,
|
" RMT symbols: %" PRIu32,
|
||||||
this->clock_resolution_, this->rmt_symbols_);
|
this->clock_resolution_, this->rmt_symbols_);
|
||||||
#else
|
|
||||||
ESP_LOGCONFIG(TAG,
|
|
||||||
" Channel: %d\n"
|
|
||||||
" RMT memory blocks: %d\n"
|
|
||||||
" Clock divider: %u",
|
|
||||||
this->channel_, this->mem_block_num_, this->clock_divider_);
|
|
||||||
#endif
|
|
||||||
LOG_PIN(" Pin: ", this->pin_);
|
LOG_PIN(" Pin: ", this->pin_);
|
||||||
|
|
||||||
if (this->current_carrier_frequency_ != 0 && this->carrier_duty_percent_ != 100) {
|
if (this->current_carrier_frequency_ != 0 && this->carrier_duty_percent_ != 100) {
|
||||||
@@ -42,7 +34,6 @@ void RemoteTransmitterComponent::dump_config() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
void RemoteTransmitterComponent::digital_write(bool value) {
|
void RemoteTransmitterComponent::digital_write(bool value) {
|
||||||
rmt_symbol_word_t symbol = {
|
rmt_symbol_word_t symbol = {
|
||||||
.duration0 = 1,
|
.duration0 = 1,
|
||||||
@@ -65,10 +56,8 @@ void RemoteTransmitterComponent::digital_write(bool value) {
|
|||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void RemoteTransmitterComponent::configure_rmt_() {
|
void RemoteTransmitterComponent::configure_rmt_() {
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
esp_err_t error;
|
esp_err_t error;
|
||||||
|
|
||||||
if (!this->initialized_) {
|
if (!this->initialized_) {
|
||||||
@@ -140,54 +129,6 @@ void RemoteTransmitterComponent::configure_rmt_() {
|
|||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
rmt_config_t c{};
|
|
||||||
|
|
||||||
this->config_rmt(c);
|
|
||||||
c.rmt_mode = RMT_MODE_TX;
|
|
||||||
c.gpio_num = gpio_num_t(this->pin_->get_pin());
|
|
||||||
c.tx_config.loop_en = false;
|
|
||||||
|
|
||||||
if (this->current_carrier_frequency_ == 0 || this->carrier_duty_percent_ == 100) {
|
|
||||||
c.tx_config.carrier_en = false;
|
|
||||||
} else {
|
|
||||||
c.tx_config.carrier_en = true;
|
|
||||||
c.tx_config.carrier_freq_hz = this->current_carrier_frequency_;
|
|
||||||
c.tx_config.carrier_duty_percent = this->carrier_duty_percent_;
|
|
||||||
}
|
|
||||||
|
|
||||||
c.tx_config.idle_output_en = true;
|
|
||||||
if (!this->inverted_) {
|
|
||||||
c.tx_config.carrier_level = RMT_CARRIER_LEVEL_HIGH;
|
|
||||||
c.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
|
|
||||||
} else {
|
|
||||||
c.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
|
|
||||||
c.tx_config.idle_level = RMT_IDLE_LEVEL_HIGH;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t error = rmt_config(&c);
|
|
||||||
if (error != ESP_OK) {
|
|
||||||
this->error_code_ = error;
|
|
||||||
this->error_string_ = "in rmt_config";
|
|
||||||
this->mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this->initialized_) {
|
|
||||||
error = rmt_driver_install(this->channel_, 0, 0);
|
|
||||||
if (error != ESP_OK) {
|
|
||||||
this->error_code_ = error;
|
|
||||||
if (error == ESP_ERR_INVALID_STATE) {
|
|
||||||
this->error_string_ = str_sprintf("RMT channel %i is already in use by another component", this->channel_);
|
|
||||||
} else {
|
|
||||||
this->error_string_ = "in rmt_driver_install";
|
|
||||||
}
|
|
||||||
this->mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->initialized_ = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t send_wait) {
|
void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t send_wait) {
|
||||||
@@ -202,11 +143,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|||||||
this->rmt_temp_.clear();
|
this->rmt_temp_.clear();
|
||||||
this->rmt_temp_.reserve((this->temp_.get_data().size() + 1) / 2);
|
this->rmt_temp_.reserve((this->temp_.get_data().size() + 1) / 2);
|
||||||
uint32_t rmt_i = 0;
|
uint32_t rmt_i = 0;
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
rmt_symbol_word_t rmt_item;
|
rmt_symbol_word_t rmt_item;
|
||||||
#else
|
|
||||||
rmt_item32_t rmt_item;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int32_t val : this->temp_.get_data()) {
|
for (int32_t val : this->temp_.get_data()) {
|
||||||
bool level = val >= 0;
|
bool level = val >= 0;
|
||||||
@@ -241,7 +178,6 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->transmit_trigger_->trigger();
|
this->transmit_trigger_->trigger();
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
|
||||||
for (uint32_t i = 0; i < send_times; i++) {
|
for (uint32_t i = 0; i < send_times; i++) {
|
||||||
rmt_transmit_config_t config;
|
rmt_transmit_config_t config;
|
||||||
memset(&config, 0, sizeof(config));
|
memset(&config, 0, sizeof(config));
|
||||||
@@ -263,19 +199,6 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|||||||
if (i + 1 < send_times)
|
if (i + 1 < send_times)
|
||||||
delayMicroseconds(send_wait);
|
delayMicroseconds(send_wait);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
for (uint32_t i = 0; i < send_times; i++) {
|
|
||||||
esp_err_t error = rmt_write_items(this->channel_, this->rmt_temp_.data(), this->rmt_temp_.size(), true);
|
|
||||||
if (error != ESP_OK) {
|
|
||||||
ESP_LOGW(TAG, "rmt_write_items failed: %s", esp_err_to_name(error));
|
|
||||||
this->status_set_warning();
|
|
||||||
} else {
|
|
||||||
this->status_clear_warning();
|
|
||||||
}
|
|
||||||
if (i + 1 < send_times)
|
|
||||||
delayMicroseconds(send_wait);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
this->complete_trigger_->trigger();
|
this->complete_trigger_->trigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#include "sntp_component.h"
|
#include "sntp_component.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP32
|
||||||
#include "esp_sntp.h"
|
#include "esp_sntp.h"
|
||||||
#elif USE_ESP8266
|
#elif USE_ESP8266
|
||||||
#include "sntp.h"
|
#include "sntp.h"
|
||||||
@@ -16,7 +16,7 @@ static const char *const TAG = "sntp";
|
|||||||
|
|
||||||
void SNTPComponent::setup() {
|
void SNTPComponent::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Running setup");
|
ESP_LOGCONFIG(TAG, "Running setup");
|
||||||
#if defined(USE_ESP_IDF)
|
#if defined(USE_ESP32)
|
||||||
if (esp_sntp_enabled()) {
|
if (esp_sntp_enabled()) {
|
||||||
esp_sntp_stop();
|
esp_sntp_stop();
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ void SNTPComponent::dump_config() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void SNTPComponent::update() {
|
void SNTPComponent::update() {
|
||||||
#if !defined(USE_ESP_IDF)
|
#if !defined(USE_ESP32)
|
||||||
// force resync
|
// force resync
|
||||||
if (sntp_enabled()) {
|
if (sntp_enabled()) {
|
||||||
sntp_stop();
|
sntp_stop();
|
||||||
|
@@ -85,7 +85,7 @@ bool VoiceAssistant::start_udp_socket_() {
|
|||||||
bool VoiceAssistant::allocate_buffers_() {
|
bool VoiceAssistant::allocate_buffers_() {
|
||||||
#ifdef USE_SPEAKER
|
#ifdef USE_SPEAKER
|
||||||
if ((this->speaker_ != nullptr) && (this->speaker_buffer_ == nullptr)) {
|
if ((this->speaker_ != nullptr) && (this->speaker_buffer_ == nullptr)) {
|
||||||
ExternalRAMAllocator<uint8_t> speaker_allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> speaker_allocator;
|
||||||
this->speaker_buffer_ = speaker_allocator.allocate(SPEAKER_BUFFER_SIZE);
|
this->speaker_buffer_ = speaker_allocator.allocate(SPEAKER_BUFFER_SIZE);
|
||||||
if (this->speaker_buffer_ == nullptr) {
|
if (this->speaker_buffer_ == nullptr) {
|
||||||
ESP_LOGW(TAG, "Could not allocate speaker buffer");
|
ESP_LOGW(TAG, "Could not allocate speaker buffer");
|
||||||
@@ -103,7 +103,7 @@ bool VoiceAssistant::allocate_buffers_() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->send_buffer_ == nullptr) {
|
if (this->send_buffer_ == nullptr) {
|
||||||
ExternalRAMAllocator<uint8_t> send_allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> send_allocator;
|
||||||
this->send_buffer_ = send_allocator.allocate(SEND_BUFFER_SIZE);
|
this->send_buffer_ = send_allocator.allocate(SEND_BUFFER_SIZE);
|
||||||
if (send_buffer_ == nullptr) {
|
if (send_buffer_ == nullptr) {
|
||||||
ESP_LOGW(TAG, "Could not allocate send buffer");
|
ESP_LOGW(TAG, "Could not allocate send buffer");
|
||||||
@@ -136,7 +136,7 @@ void VoiceAssistant::clear_buffers_() {
|
|||||||
|
|
||||||
void VoiceAssistant::deallocate_buffers_() {
|
void VoiceAssistant::deallocate_buffers_() {
|
||||||
if (this->send_buffer_ != nullptr) {
|
if (this->send_buffer_ != nullptr) {
|
||||||
ExternalRAMAllocator<uint8_t> send_deallocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> send_deallocator;
|
||||||
send_deallocator.deallocate(this->send_buffer_, SEND_BUFFER_SIZE);
|
send_deallocator.deallocate(this->send_buffer_, SEND_BUFFER_SIZE);
|
||||||
this->send_buffer_ = nullptr;
|
this->send_buffer_ = nullptr;
|
||||||
}
|
}
|
||||||
@@ -147,7 +147,7 @@ void VoiceAssistant::deallocate_buffers_() {
|
|||||||
|
|
||||||
#ifdef USE_SPEAKER
|
#ifdef USE_SPEAKER
|
||||||
if ((this->speaker_ != nullptr) && (this->speaker_buffer_ != nullptr)) {
|
if ((this->speaker_ != nullptr) && (this->speaker_buffer_ != nullptr)) {
|
||||||
ExternalRAMAllocator<uint8_t> speaker_deallocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> speaker_deallocator;
|
||||||
speaker_deallocator.deallocate(this->speaker_buffer_, SPEAKER_BUFFER_SIZE);
|
speaker_deallocator.deallocate(this->speaker_buffer_, SPEAKER_BUFFER_SIZE);
|
||||||
this->speaker_buffer_ = nullptr;
|
this->speaker_buffer_ = nullptr;
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
#include "waveshare_epaper.h"
|
#include "waveshare_epaper.h"
|
||||||
|
#include <bitset>
|
||||||
|
#include <cinttypes>
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include <cinttypes>
|
|
||||||
#include <bitset>
|
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace waveshare_epaper {
|
namespace waveshare_epaper {
|
||||||
@@ -185,7 +185,7 @@ void WaveshareEPaper7C::setup() {
|
|||||||
this->initialize();
|
this->initialize();
|
||||||
}
|
}
|
||||||
void WaveshareEPaper7C::init_internal_7c_(uint32_t buffer_length) {
|
void WaveshareEPaper7C::init_internal_7c_(uint32_t buffer_length) {
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
uint32_t small_buffer_length = buffer_length / NUM_BUFFERS;
|
uint32_t small_buffer_length = buffer_length / NUM_BUFFERS;
|
||||||
|
|
||||||
for (int i = 0; i < NUM_BUFFERS; i++) {
|
for (int i = 0; i < NUM_BUFFERS; i++) {
|
||||||
@@ -2054,7 +2054,7 @@ void GDEW029T5::initialize() {
|
|||||||
this->deep_sleep_between_updates_ = true;
|
this->deep_sleep_between_updates_ = true;
|
||||||
|
|
||||||
// old buffer for partial update
|
// old buffer for partial update
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
this->old_buffer_ = allocator.allocate(this->get_buffer_length_());
|
this->old_buffer_ = allocator.allocate(this->get_buffer_length_());
|
||||||
if (this->old_buffer_ == nullptr) {
|
if (this->old_buffer_ == nullptr) {
|
||||||
ESP_LOGE(TAG, "Could not allocate old buffer for display!");
|
ESP_LOGE(TAG, "Could not allocate old buffer for display!");
|
||||||
@@ -2199,7 +2199,7 @@ void GDEW029T5::dump_config() {
|
|||||||
|
|
||||||
void GDEW0154M09::initialize() {
|
void GDEW0154M09::initialize() {
|
||||||
this->init_internal_();
|
this->init_internal_();
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
this->lastbuff_ = allocator.allocate(this->get_buffer_length_());
|
this->lastbuff_ = allocator.allocate(this->get_buffer_length_());
|
||||||
if (this->lastbuff_ != nullptr) {
|
if (this->lastbuff_ != nullptr) {
|
||||||
memset(this->lastbuff_, 0xff, sizeof(uint8_t) * this->get_buffer_length_());
|
memset(this->lastbuff_, 0xff, sizeof(uint8_t) * this->get_buffer_length_());
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#ifdef USE_WIFI_WPA2_EAP
|
#ifdef USE_WIFI_WPA2_EAP
|
||||||
#include <esp_wpa2.h>
|
#include <esp_eap_client.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_WIFI_AP
|
#ifdef USE_WIFI_AP
|
||||||
@@ -228,43 +228,43 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
|
|||||||
if (ap.get_eap().has_value()) {
|
if (ap.get_eap().has_value()) {
|
||||||
// note: all certificates and keys have to be null terminated. Lengths are appended by +1 to include \0.
|
// note: all certificates and keys have to be null terminated. Lengths are appended by +1 to include \0.
|
||||||
EAPAuth eap = ap.get_eap().value();
|
EAPAuth eap = ap.get_eap().value();
|
||||||
err = esp_wifi_sta_wpa2_ent_set_identity((uint8_t *) eap.identity.c_str(), eap.identity.length());
|
err = esp_eap_client_set_identity((uint8_t *) eap.identity.c_str(), eap.identity.length());
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_identity failed! %d", err);
|
ESP_LOGV(TAG, "esp_eap_client_set_identity failed! %d", err);
|
||||||
}
|
}
|
||||||
int ca_cert_len = strlen(eap.ca_cert);
|
int ca_cert_len = strlen(eap.ca_cert);
|
||||||
int client_cert_len = strlen(eap.client_cert);
|
int client_cert_len = strlen(eap.client_cert);
|
||||||
int client_key_len = strlen(eap.client_key);
|
int client_key_len = strlen(eap.client_key);
|
||||||
if (ca_cert_len) {
|
if (ca_cert_len) {
|
||||||
err = esp_wifi_sta_wpa2_ent_set_ca_cert((uint8_t *) eap.ca_cert, ca_cert_len + 1);
|
err = esp_eap_client_set_ca_cert((uint8_t *) eap.ca_cert, ca_cert_len + 1);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_ca_cert failed! %d", err);
|
ESP_LOGV(TAG, "esp_eap_client_set_ca_cert failed! %d", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// workout what type of EAP this is
|
// workout what type of EAP this is
|
||||||
// validation is not required as the config tool has already validated it
|
// validation is not required as the config tool has already validated it
|
||||||
if (client_cert_len && client_key_len) {
|
if (client_cert_len && client_key_len) {
|
||||||
// if we have certs, this must be EAP-TLS
|
// if we have certs, this must be EAP-TLS
|
||||||
err = esp_wifi_sta_wpa2_ent_set_cert_key((uint8_t *) eap.client_cert, client_cert_len + 1,
|
err = esp_eap_client_set_certificate_and_key((uint8_t *) eap.client_cert, client_cert_len + 1,
|
||||||
(uint8_t *) eap.client_key, client_key_len + 1,
|
(uint8_t *) eap.client_key, client_key_len + 1,
|
||||||
(uint8_t *) eap.password.c_str(), strlen(eap.password.c_str()));
|
(uint8_t *) eap.password.c_str(), strlen(eap.password.c_str()));
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_cert_key failed! %d", err);
|
ESP_LOGV(TAG, "esp_eap_client_set_certificate_and_key failed! %d", err);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// in the absence of certs, assume this is username/password based
|
// in the absence of certs, assume this is username/password based
|
||||||
err = esp_wifi_sta_wpa2_ent_set_username((uint8_t *) eap.username.c_str(), eap.username.length());
|
err = esp_eap_client_set_username((uint8_t *) eap.username.c_str(), eap.username.length());
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_username failed! %d", err);
|
ESP_LOGV(TAG, "esp_eap_client_set_username failed! %d", err);
|
||||||
}
|
}
|
||||||
err = esp_wifi_sta_wpa2_ent_set_password((uint8_t *) eap.password.c_str(), eap.password.length());
|
err = esp_eap_client_set_password((uint8_t *) eap.password.c_str(), eap.password.length());
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_password failed! %d", err);
|
ESP_LOGV(TAG, "esp_eap_client_set_password failed! %d", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = esp_wifi_sta_wpa2_ent_enable();
|
err = esp_wifi_sta_enterprise_enable();
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_enable failed! %d", err);
|
ESP_LOGV(TAG, "esp_wifi_sta_enterprise_enable failed! %d", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // USE_WIFI_WPA2_EAP
|
#endif // USE_WIFI_WPA2_EAP
|
||||||
@@ -552,7 +552,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
|
|||||||
ESP_LOGV(TAG, "Event: Connected ssid='%s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", buf,
|
ESP_LOGV(TAG, "Event: Connected ssid='%s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", buf,
|
||||||
format_mac_addr(it.bssid).c_str(), it.channel, get_auth_mode_str(it.authmode));
|
format_mac_addr(it.bssid).c_str(), it.channel, get_auth_mode_str(it.authmode));
|
||||||
#if USE_NETWORK_IPV6
|
#if USE_NETWORK_IPV6
|
||||||
this->set_timeout(100, [] { WiFi.enableIpV6(); });
|
this->set_timeout(100, [] { WiFi.enableIPv6(); });
|
||||||
#endif /* USE_NETWORK_IPV6 */
|
#endif /* USE_NETWORK_IPV6 */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -662,12 +662,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
|
|||||||
}
|
}
|
||||||
|
|
||||||
WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() {
|
WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() {
|
||||||
#if USE_ARDUINO_VERSION_CODE < VERSION_CODE(3, 1, 0)
|
|
||||||
const auto status = WiFiClass::status();
|
|
||||||
#else
|
|
||||||
const auto status = WiFi.status();
|
const auto status = WiFi.status();
|
||||||
#endif
|
|
||||||
|
|
||||||
if (status == WL_CONNECT_FAILED || status == WL_CONNECTION_LOST) {
|
if (status == WL_CONNECT_FAILED || status == WL_CONNECTION_LOST) {
|
||||||
return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED;
|
return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED;
|
||||||
}
|
}
|
||||||
|
@@ -136,6 +136,7 @@
|
|||||||
#define USE_ESP32_BLE_CLIENT
|
#define USE_ESP32_BLE_CLIENT
|
||||||
#define USE_ESP32_BLE_SERVER
|
#define USE_ESP32_BLE_SERVER
|
||||||
#define USE_ESP32_CAMERA
|
#define USE_ESP32_CAMERA
|
||||||
|
#define USE_I2C
|
||||||
#define USE_IMPROV
|
#define USE_IMPROV
|
||||||
#define USE_MICROPHONE
|
#define USE_MICROPHONE
|
||||||
#define USE_PSRAM
|
#define USE_PSRAM
|
||||||
@@ -149,7 +150,7 @@
|
|||||||
#define USE_WIFI_11KV_SUPPORT
|
#define USE_WIFI_11KV_SUPPORT
|
||||||
|
|
||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
#define USE_ARDUINO_VERSION_CODE VERSION_CODE(2, 0, 5)
|
#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 1, 3)
|
||||||
#define USE_ETHERNET
|
#define USE_ETHERNET
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -179,6 +180,7 @@
|
|||||||
#define USE_CAPTIVE_PORTAL
|
#define USE_CAPTIVE_PORTAL
|
||||||
#define USE_ESP8266_PREFERENCES_FLASH
|
#define USE_ESP8266_PREFERENCES_FLASH
|
||||||
#define USE_HTTP_REQUEST_ESP8266_HTTPS
|
#define USE_HTTP_REQUEST_ESP8266_HTTPS
|
||||||
|
#define USE_I2C
|
||||||
#define USE_SOCKET_IMPL_LWIP_TCP
|
#define USE_SOCKET_IMPL_LWIP_TCP
|
||||||
|
|
||||||
#define USE_SPI
|
#define USE_SPI
|
||||||
@@ -195,6 +197,7 @@
|
|||||||
|
|
||||||
#ifdef USE_RP2040
|
#ifdef USE_RP2040
|
||||||
#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 0)
|
#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 0)
|
||||||
|
#define USE_I2C
|
||||||
#define USE_LOGGER_USB_CDC
|
#define USE_LOGGER_USB_CDC
|
||||||
#define USE_SOCKET_IMPL_LWIP_TCP
|
#define USE_SOCKET_IMPL_LWIP_TCP
|
||||||
#define USE_SPI
|
#define USE_SPI
|
||||||
|
@@ -14,7 +14,7 @@ static const char *const TAG = "ring_buffer";
|
|||||||
RingBuffer::~RingBuffer() {
|
RingBuffer::~RingBuffer() {
|
||||||
if (this->handle_ != nullptr) {
|
if (this->handle_ != nullptr) {
|
||||||
vRingbufferDelete(this->handle_);
|
vRingbufferDelete(this->handle_);
|
||||||
RAMAllocator<uint8_t> allocator(RAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
allocator.deallocate(this->storage_, this->size_);
|
allocator.deallocate(this->storage_, this->size_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,7 @@ std::unique_ptr<RingBuffer> RingBuffer::create(size_t len) {
|
|||||||
|
|
||||||
rb->size_ = len;
|
rb->size_ = len;
|
||||||
|
|
||||||
RAMAllocator<uint8_t> allocator(RAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
rb->storage_ = allocator.allocate(rb->size_);
|
rb->storage_ = allocator.allocate(rb->size_);
|
||||||
if (rb->storage_ == nullptr) {
|
if (rb->storage_ == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@@ -34,7 +34,6 @@ build_flags =
|
|||||||
[common]
|
[common]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
esphome/noise-c@0.1.4 ; api
|
esphome/noise-c@0.1.4 ; api
|
||||||
makuna/NeoPixelBus@2.7.3 ; neopixelbus
|
|
||||||
improv/Improv@1.2.4 ; improv_serial / esp32_improv
|
improv/Improv@1.2.4 ; improv_serial / esp32_improv
|
||||||
bblanchon/ArduinoJson@6.18.5 ; json
|
bblanchon/ArduinoJson@6.18.5 ; json
|
||||||
wjtje/qr-code-generator-library@1.7.0 ; qr_code
|
wjtje/qr-code-generator-library@1.7.0 ; qr_code
|
||||||
@@ -101,6 +100,7 @@ lib_deps =
|
|||||||
ESP8266WiFi ; wifi (Arduino built-in)
|
ESP8266WiFi ; wifi (Arduino built-in)
|
||||||
Update ; ota (Arduino built-in)
|
Update ; ota (Arduino built-in)
|
||||||
ESP32Async/ESPAsyncTCP@2.0.0 ; async_tcp
|
ESP32Async/ESPAsyncTCP@2.0.0 ; async_tcp
|
||||||
|
makuna/NeoPixelBus@2.7.3 ; neopixelbus
|
||||||
ESP8266HTTPClient ; http_request (Arduino built-in)
|
ESP8266HTTPClient ; http_request (Arduino built-in)
|
||||||
ESP8266mDNS ; mdns (Arduino built-in)
|
ESP8266mDNS ; mdns (Arduino built-in)
|
||||||
DNSServer ; captive_portal (Arduino built-in)
|
DNSServer ; captive_portal (Arduino built-in)
|
||||||
@@ -118,23 +118,26 @@ extra_scripts = post:esphome/components/esp8266/post_build.py.script
|
|||||||
; This are common settings for the ESP32 (all variants) using Arduino.
|
; This are common settings for the ESP32 (all variants) using Arduino.
|
||||||
[common:esp32-arduino]
|
[common:esp32-arduino]
|
||||||
extends = common:arduino
|
extends = common:arduino
|
||||||
platform = platformio/espressif32@5.4.0
|
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.13/platform-espressif32.zip
|
||||||
platform_packages =
|
platform_packages =
|
||||||
platformio/framework-arduinoespressif32@~3.20005.0
|
pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.1.3/esp32-3.1.3.zip
|
||||||
|
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
; order matters with lib-deps; some of the libs in common:arduino.lib_deps
|
; order matters with lib-deps; some of the libs in common:arduino.lib_deps
|
||||||
; don't declare built-in libraries as dependencies, so they have to be declared first
|
; don't declare built-in libraries as dependencies, so they have to be declared first
|
||||||
FS ; web_server_base (Arduino built-in)
|
FS ; web_server_base (Arduino built-in)
|
||||||
|
Networking ; wifi,web_server_base,ethernet (Arduino built-in)
|
||||||
WiFi ; wifi,web_server_base,ethernet (Arduino built-in)
|
WiFi ; wifi,web_server_base,ethernet (Arduino built-in)
|
||||||
Update ; ota,web_server_base (Arduino built-in)
|
Update ; ota,web_server_base (Arduino built-in)
|
||||||
${common:arduino.lib_deps}
|
${common:arduino.lib_deps}
|
||||||
ESP32Async/AsyncTCP@3.4.4 ; async_tcp
|
ESP32Async/AsyncTCP@3.4.4 ; async_tcp
|
||||||
WiFiClientSecure ; http_request,nextion (Arduino built-in)
|
NetworkClientSecure ; http_request,nextion (Arduino built-in)
|
||||||
HTTPClient ; http_request,nextion (Arduino built-in)
|
HTTPClient ; http_request,nextion (Arduino built-in)
|
||||||
ESPmDNS ; mdns (Arduino built-in)
|
ESPmDNS ; mdns (Arduino built-in)
|
||||||
|
ESP32 Async UDP ; captive_portal (Arduino built-in)
|
||||||
DNSServer ; captive_portal (Arduino built-in)
|
DNSServer ; captive_portal (Arduino built-in)
|
||||||
|
makuna/NeoPixelBus@2.8.0 ; neopixelbus
|
||||||
esphome/ESP32-audioI2S@2.3.0 ; i2s_audio
|
esphome/ESP32-audioI2S@2.3.0 ; i2s_audio
|
||||||
droscy/esp_wireguard@0.4.2 ; wireguard
|
droscy/esp_wireguard@0.4.2 ; wireguard
|
||||||
esphome/esp-audio-libs@1.1.4 ; audio
|
esphome/esp-audio-libs@1.1.4 ; audio
|
||||||
|
@@ -13,7 +13,7 @@ platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile
|
|||||||
esptool==4.8.1
|
esptool==4.8.1
|
||||||
click==8.1.7
|
click==8.1.7
|
||||||
esphome-dashboard==20250514.0
|
esphome-dashboard==20250514.0
|
||||||
aioesphomeapi==32.2.3
|
aioesphomeapi==32.2.4
|
||||||
zeroconf==0.147.0
|
zeroconf==0.147.0
|
||||||
puremagic==1.29
|
puremagic==1.29
|
||||||
ruamel.yaml==0.18.14 # dashboard_import
|
ruamel.yaml==0.18.14 # dashboard_import
|
||||||
|
@@ -5,7 +5,7 @@ pyupgrade==3.20.0 # also change in .pre-commit-config.yaml when updating
|
|||||||
pre-commit
|
pre-commit
|
||||||
|
|
||||||
# Unit tests
|
# Unit tests
|
||||||
pytest==8.4.0
|
pytest==8.4.1
|
||||||
pytest-cov==6.2.1
|
pytest-cov==6.2.1
|
||||||
pytest-mock==3.14.1
|
pytest-mock==3.14.1
|
||||||
pytest-asyncio==1.0.0
|
pytest-asyncio==1.0.0
|
||||||
|
@@ -959,8 +959,9 @@ def build_message_type(
|
|||||||
prot = "bool decode_64bit(uint32_t field_id, Proto64Bit value) override;"
|
prot = "bool decode_64bit(uint32_t field_id, Proto64Bit value) override;"
|
||||||
protected_content.insert(0, prot)
|
protected_content.insert(0, prot)
|
||||||
|
|
||||||
o = f"void {desc.name}::encode(ProtoWriteBuffer buffer) const {{"
|
# Only generate encode method if there are fields to encode
|
||||||
if encode:
|
if encode:
|
||||||
|
o = f"void {desc.name}::encode(ProtoWriteBuffer buffer) const {{"
|
||||||
if len(encode) == 1 and len(encode[0]) + len(o) + 3 < 120:
|
if len(encode) == 1 and len(encode[0]) + len(o) + 3 < 120:
|
||||||
o += f" {encode[0]} "
|
o += f" {encode[0]} "
|
||||||
else:
|
else:
|
||||||
@@ -970,25 +971,23 @@ def build_message_type(
|
|||||||
cpp += o
|
cpp += o
|
||||||
prot = "void encode(ProtoWriteBuffer buffer) const override;"
|
prot = "void encode(ProtoWriteBuffer buffer) const override;"
|
||||||
public_content.append(prot)
|
public_content.append(prot)
|
||||||
|
# If no fields to encode, the default implementation in ProtoMessage will be used
|
||||||
|
|
||||||
# Add calculate_size method
|
# Add calculate_size method only if there are fields
|
||||||
o = f"void {desc.name}::calculate_size(uint32_t &total_size) const {{"
|
|
||||||
|
|
||||||
# Add a check for empty/default objects to short-circuit the calculation
|
|
||||||
# Only add this optimization if we have fields to check
|
|
||||||
if size_calc:
|
if size_calc:
|
||||||
|
o = f"void {desc.name}::calculate_size(uint32_t &total_size) const {{"
|
||||||
# For a single field, just inline it for simplicity
|
# For a single field, just inline it for simplicity
|
||||||
if len(size_calc) == 1 and len(size_calc[0]) + len(o) + 3 < 120:
|
if len(size_calc) == 1 and len(size_calc[0]) + len(o) + 3 < 120:
|
||||||
o += f" {size_calc[0]} "
|
o += f" {size_calc[0]} "
|
||||||
else:
|
else:
|
||||||
# For multiple fields, add a short-circuit check
|
# For multiple fields
|
||||||
o += "\n"
|
o += "\n"
|
||||||
# Performance optimization: add all the size calculations
|
|
||||||
o += indent("\n".join(size_calc)) + "\n"
|
o += indent("\n".join(size_calc)) + "\n"
|
||||||
o += "}\n"
|
o += "}\n"
|
||||||
cpp += o
|
cpp += o
|
||||||
prot = "void calculate_size(uint32_t &total_size) const override;"
|
prot = "void calculate_size(uint32_t &total_size) const override;"
|
||||||
public_content.append(prot)
|
public_content.append(prot)
|
||||||
|
# If no fields to calculate size for, the default implementation in ProtoMessage will be used
|
||||||
|
|
||||||
o = f"void {desc.name}::dump_to(std::string &out) const {{"
|
o = f"void {desc.name}::dump_to(std::string &out) const {{"
|
||||||
if dump:
|
if dump:
|
||||||
@@ -1425,18 +1424,32 @@ def main() -> None:
|
|||||||
hpp_protected += f" void {on_func}(const {inp} &msg) override;\n"
|
hpp_protected += f" void {on_func}(const {inp} &msg) override;\n"
|
||||||
hpp += f" virtual {ret} {func}(const {inp} &msg) = 0;\n"
|
hpp += f" virtual {ret} {func}(const {inp} &msg) = 0;\n"
|
||||||
cpp += f"void {class_name}::{on_func}(const {inp} &msg) {{\n"
|
cpp += f"void {class_name}::{on_func}(const {inp} &msg) {{\n"
|
||||||
body = ""
|
|
||||||
if needs_conn:
|
|
||||||
body += "if (!this->is_connection_setup()) {\n"
|
|
||||||
body += " this->on_no_setup_connection();\n"
|
|
||||||
body += " return;\n"
|
|
||||||
body += "}\n"
|
|
||||||
if needs_auth:
|
|
||||||
body += "if (!this->is_authenticated()) {\n"
|
|
||||||
body += " this->on_unauthenticated_access();\n"
|
|
||||||
body += " return;\n"
|
|
||||||
body += "}\n"
|
|
||||||
|
|
||||||
|
# Start with authentication/connection check if needed
|
||||||
|
if needs_auth or needs_conn:
|
||||||
|
# Determine which check to use
|
||||||
|
if needs_auth:
|
||||||
|
check_func = "this->check_authenticated_()"
|
||||||
|
else:
|
||||||
|
check_func = "this->check_connection_setup_()"
|
||||||
|
|
||||||
|
body = f"if ({check_func}) {{\n"
|
||||||
|
|
||||||
|
# Add the actual handler code, indented
|
||||||
|
handler_body = ""
|
||||||
|
if is_void:
|
||||||
|
handler_body = f"this->{func}(msg);\n"
|
||||||
|
else:
|
||||||
|
handler_body = f"{ret} ret = this->{func}(msg);\n"
|
||||||
|
handler_body += "if (!this->send_message(ret)) {\n"
|
||||||
|
handler_body += " this->on_fatal_error();\n"
|
||||||
|
handler_body += "}\n"
|
||||||
|
|
||||||
|
body += indent(handler_body) + "\n"
|
||||||
|
body += "}\n"
|
||||||
|
else:
|
||||||
|
# No auth check needed, just call the handler
|
||||||
|
body = ""
|
||||||
if is_void:
|
if is_void:
|
||||||
body += f"this->{func}(msg);\n"
|
body += f"this->{func}(msg);\n"
|
||||||
else:
|
else:
|
||||||
@@ -1444,6 +1457,7 @@ def main() -> None:
|
|||||||
body += "if (!this->send_message(ret)) {\n"
|
body += "if (!this->send_message(ret)) {\n"
|
||||||
body += " this->on_fatal_error();\n"
|
body += " this->on_fatal_error();\n"
|
||||||
body += "}\n"
|
body += "}\n"
|
||||||
|
|
||||||
cpp += indent(body) + "\n" + "}\n"
|
cpp += indent(body) + "\n" + "}\n"
|
||||||
|
|
||||||
if ifdef is not None:
|
if ifdef is not None:
|
||||||
|
@@ -6,7 +6,6 @@ light:
|
|||||||
rgb_order: GRB
|
rgb_order: GRB
|
||||||
num_leds: 256
|
num_leds: 256
|
||||||
pin: ${pin}
|
pin: ${pin}
|
||||||
rmt_channel: 0
|
|
||||||
|
|
||||||
display:
|
display:
|
||||||
- platform: addressable_light
|
- platform: addressable_light
|
||||||
|
@@ -1,8 +0,0 @@
|
|||||||
<<: !include common.yaml
|
|
||||||
|
|
||||||
esp32_ble_tracker:
|
|
||||||
max_connections: 3
|
|
||||||
|
|
||||||
bluetooth_proxy:
|
|
||||||
active: true
|
|
||||||
connection_slots: 2
|
|
@@ -8,7 +8,6 @@ light:
|
|||||||
rgb_order: GRB
|
rgb_order: GRB
|
||||||
num_leds: 256
|
num_leds: 256
|
||||||
pin: ${pin}
|
pin: ${pin}
|
||||||
rmt_channel: 0
|
|
||||||
effects:
|
effects:
|
||||||
- e131:
|
- e131:
|
||||||
universe: 1
|
universe: 1
|
||||||
|
@@ -32,3 +32,7 @@ esp32_camera_web_server:
|
|||||||
mode: stream
|
mode: stream
|
||||||
- port: 8081
|
- port: 8081
|
||||||
mode: snapshot
|
mode: snapshot
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: MySSID
|
||||||
|
password: password1
|
||||||
|
@@ -1,18 +0,0 @@
|
|||||||
light:
|
|
||||||
- platform: esp32_rmt_led_strip
|
|
||||||
id: led_strip1
|
|
||||||
pin: ${pin1}
|
|
||||||
num_leds: 60
|
|
||||||
rmt_channel: 0
|
|
||||||
rgb_order: GRB
|
|
||||||
chipset: ws2812
|
|
||||||
- platform: esp32_rmt_led_strip
|
|
||||||
id: led_strip2
|
|
||||||
pin: ${pin2}
|
|
||||||
num_leds: 60
|
|
||||||
rmt_channel: 1
|
|
||||||
rgb_order: RGB
|
|
||||||
bit0_high: 100us
|
|
||||||
bit0_low: 100us
|
|
||||||
bit1_high: 100us
|
|
||||||
bit1_low: 100us
|
|
@@ -3,4 +3,4 @@ substitutions:
|
|||||||
pin2: GPIO14
|
pin2: GPIO14
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common-ard.yaml
|
common: !include common.yaml
|
||||||
|
@@ -3,4 +3,4 @@ substitutions:
|
|||||||
pin2: GPIO4
|
pin2: GPIO4
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common-ard.yaml
|
common: !include common.yaml
|
||||||
|
@@ -3,4 +3,4 @@ substitutions:
|
|||||||
pin2: GPIO4
|
pin2: GPIO4
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common-idf.yaml
|
common: !include common.yaml
|
||||||
|
@@ -3,4 +3,4 @@ substitutions:
|
|||||||
pin2: GPIO14
|
pin2: GPIO14
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common-idf.yaml
|
common: !include common.yaml
|
||||||
|
@@ -3,7 +3,7 @@ substitutions:
|
|||||||
pin2: GPIO4
|
pin2: GPIO4
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common-idf.yaml
|
common: !include common.yaml
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- id: !extend led_strip1
|
- id: !extend led_strip1
|
||||||
|
@@ -1,5 +1 @@
|
|||||||
<<: !include common.yaml
|
<<: !include common.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
version: 2.0.9
|
|
||||||
|
@@ -5,7 +5,6 @@ light:
|
|||||||
chipset: ws2812
|
chipset: ws2812
|
||||||
num_leds: 256
|
num_leds: 256
|
||||||
rgb_order: GRB
|
rgb_order: GRB
|
||||||
rmt_channel: 1
|
|
||||||
pin: ${pin}
|
pin: ${pin}
|
||||||
- platform: partition
|
- platform: partition
|
||||||
name: Partition Light
|
name: Partition Light
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
remote_receiver:
|
|
||||||
- id: rcvr
|
|
||||||
pin: ${pin}
|
|
||||||
rmt_channel: ${rmt_channel}
|
|
||||||
dump: all
|
|
||||||
tolerance: 25%
|
|
||||||
<<: !include common-actions.yaml
|
|
||||||
|
|
||||||
binary_sensor:
|
|
||||||
- platform: remote_receiver
|
|
||||||
name: Panasonic Remote Input
|
|
||||||
panasonic:
|
|
||||||
address: 0x4004
|
|
||||||
command: 0x100BCBD
|
|
@@ -1,6 +1,9 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
pin: GPIO2
|
pin: GPIO2
|
||||||
rmt_channel: "2"
|
clock_resolution: "2000000"
|
||||||
|
filter_symbols: "2"
|
||||||
|
receive_symbols: "4"
|
||||||
|
rmt_symbols: "64"
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include esp32-common-ard.yaml
|
common: !include esp32-common.yaml
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
pin: GPIO2
|
pin: GPIO2
|
||||||
rmt_channel: "2"
|
clock_resolution: "2000000"
|
||||||
|
filter_symbols: "2"
|
||||||
|
receive_symbols: "4"
|
||||||
|
rmt_symbols: "64"
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include esp32-common-ard.yaml
|
common: !include esp32-common.yaml
|
||||||
|
@@ -6,4 +6,4 @@ substitutions:
|
|||||||
rmt_symbols: "64"
|
rmt_symbols: "64"
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include esp32-common-idf.yaml
|
common: !include esp32-common.yaml
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user