mirror of
https://github.com/esphome/esphome.git
synced 2025-10-13 15:23:49 +01:00
Merge remote-tracking branch 'upstream/dev' into bound_tx_buf
This commit is contained in:
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -466,7 +466,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
cache-key: ${{ needs.common.outputs.cache-key }}
|
cache-key: ${{ needs.common.outputs.cache-key }}
|
||||||
- uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
|
- uses: esphome/action@43cd1109c09c544d97196f7730ee5b2e0cc6d81e # v3.0.1 fork with pinned actions/cache
|
||||||
env:
|
env:
|
||||||
SKIP: pylint,clang-tidy-hash
|
SKIP: pylint,clang-tidy-hash
|
||||||
- uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0
|
- uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0
|
||||||
|
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
@@ -58,7 +58,7 @@ jobs:
|
|||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5
|
uses: github/codeql-action/init@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
build-mode: ${{ matrix.build-mode }}
|
build-mode: ${{ matrix.build-mode }}
|
||||||
@@ -86,6 +86,6 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5
|
uses: github/codeql-action/analyze@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6
|
||||||
with:
|
with:
|
||||||
category: "/language:${{matrix.language}}"
|
category: "/language:${{matrix.language}}"
|
||||||
|
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Stale
|
- name: Stale
|
||||||
uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0
|
uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
|
||||||
with:
|
with:
|
||||||
debug-only: ${{ github.ref != 'refs/heads/dev' }} # Dry-run when not run on dev branch
|
debug-only: ${{ github.ref != 'refs/heads/dev' }} # Dry-run when not run on dev branch
|
||||||
remove-stale-when-updated: true
|
remove-stale-when-updated: true
|
||||||
|
@@ -11,7 +11,7 @@ ci:
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
# Ruff version.
|
# Ruff version.
|
||||||
rev: v0.13.2
|
rev: v0.13.3
|
||||||
hooks:
|
hooks:
|
||||||
# Run the linter.
|
# Run the linter.
|
||||||
- id: ruff
|
- id: ruff
|
||||||
|
@@ -14,9 +14,11 @@ from typing import Protocol
|
|||||||
|
|
||||||
import argcomplete
|
import argcomplete
|
||||||
|
|
||||||
|
# Note: Do not import modules from esphome.components here, as this would
|
||||||
|
# cause them to be loaded before external components are processed, resulting
|
||||||
|
# in the built-in version being used instead of the external component one.
|
||||||
from esphome import const, writer, yaml_util
|
from esphome import const, writer, yaml_util
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
from esphome.components.mqtt import CONF_DISCOVER_IP
|
|
||||||
from esphome.config import iter_component_configs, read_config, strip_default_ids
|
from esphome.config import iter_component_configs, read_config, strip_default_ids
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
ALLOWED_NAME_CHARS,
|
ALLOWED_NAME_CHARS,
|
||||||
@@ -240,6 +242,8 @@ def has_ota() -> bool:
|
|||||||
|
|
||||||
def has_mqtt_ip_lookup() -> bool:
|
def has_mqtt_ip_lookup() -> bool:
|
||||||
"""Check if MQTT is available and IP lookup is supported."""
|
"""Check if MQTT is available and IP lookup is supported."""
|
||||||
|
from esphome.components.mqtt import CONF_DISCOVER_IP
|
||||||
|
|
||||||
if CONF_MQTT not in CORE.config:
|
if CONF_MQTT not in CORE.config:
|
||||||
return False
|
return False
|
||||||
# Default Enabled
|
# Default Enabled
|
||||||
|
@@ -14,6 +14,7 @@ from esphome.const import (
|
|||||||
CONF_EVENT,
|
CONF_EVENT,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_KEY,
|
CONF_KEY,
|
||||||
|
CONF_MAX_CONNECTIONS,
|
||||||
CONF_ON_CLIENT_CONNECTED,
|
CONF_ON_CLIENT_CONNECTED,
|
||||||
CONF_ON_CLIENT_DISCONNECTED,
|
CONF_ON_CLIENT_DISCONNECTED,
|
||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
@@ -60,7 +61,6 @@ CONF_CUSTOM_SERVICES = "custom_services"
|
|||||||
CONF_HOMEASSISTANT_SERVICES = "homeassistant_services"
|
CONF_HOMEASSISTANT_SERVICES = "homeassistant_services"
|
||||||
CONF_HOMEASSISTANT_STATES = "homeassistant_states"
|
CONF_HOMEASSISTANT_STATES = "homeassistant_states"
|
||||||
CONF_LISTEN_BACKLOG = "listen_backlog"
|
CONF_LISTEN_BACKLOG = "listen_backlog"
|
||||||
CONF_MAX_CONNECTIONS = "max_connections"
|
|
||||||
CONF_MAX_SEND_QUEUE = "max_send_queue"
|
CONF_MAX_SEND_QUEUE = "max_send_queue"
|
||||||
|
|
||||||
|
|
||||||
|
@@ -205,7 +205,8 @@ 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_DISCONNECT_TIMEOUT) {
|
if (now - this->last_traffic_ > KEEPALIVE_DISCONNECT_TIMEOUT) {
|
||||||
on_fatal_error();
|
on_fatal_error();
|
||||||
ESP_LOGW(TAG, "%s is unresponsive; disconnecting", this->get_client_combined_info().c_str());
|
ESP_LOGW(TAG, "%s (%s) is unresponsive; disconnecting", this->client_info_.name.c_str(),
|
||||||
|
this->client_info_.peername.c_str());
|
||||||
}
|
}
|
||||||
} else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS && !this->flags_.remove) {
|
} else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS && !this->flags_.remove) {
|
||||||
// Only send ping if we're not disconnecting
|
// Only send ping if we're not disconnecting
|
||||||
@@ -255,7 +256,7 @@ bool APIConnection::send_disconnect_response(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->get_client_combined_info().c_str());
|
ESP_LOGD(TAG, "%s (%s) disconnected", this->client_info_.name.c_str(), this->client_info_.peername.c_str());
|
||||||
this->flags_.next_close = true;
|
this->flags_.next_close = true;
|
||||||
DisconnectResponse resp;
|
DisconnectResponse resp;
|
||||||
return this->send_message(resp, DisconnectResponse::MESSAGE_TYPE);
|
return this->send_message(resp, DisconnectResponse::MESSAGE_TYPE);
|
||||||
@@ -1385,7 +1386,7 @@ void APIConnection::complete_authentication_() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::AUTHENTICATED);
|
this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::AUTHENTICATED);
|
||||||
ESP_LOGD(TAG, "%s connected", this->get_client_combined_info().c_str());
|
ESP_LOGD(TAG, "%s (%s) connected", this->client_info_.name.c_str(), this->client_info_.peername.c_str());
|
||||||
#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
|
#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
|
||||||
this->parent_->get_client_connected_trigger()->trigger(this->client_info_.name, this->client_info_.peername);
|
this->parent_->get_client_connected_trigger()->trigger(this->client_info_.name, this->client_info_.peername);
|
||||||
#endif
|
#endif
|
||||||
@@ -1609,12 +1610,12 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) {
|
|||||||
#ifdef USE_API_PASSWORD
|
#ifdef USE_API_PASSWORD
|
||||||
void APIConnection::on_unauthenticated_access() {
|
void APIConnection::on_unauthenticated_access() {
|
||||||
this->on_fatal_error();
|
this->on_fatal_error();
|
||||||
ESP_LOGD(TAG, "%s access without authentication", this->get_client_combined_info().c_str());
|
ESP_LOGD(TAG, "%s (%s) no authentication", this->client_info_.name.c_str(), this->client_info_.peername.c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void APIConnection::on_no_setup_connection() {
|
void APIConnection::on_no_setup_connection() {
|
||||||
this->on_fatal_error();
|
this->on_fatal_error();
|
||||||
ESP_LOGD(TAG, "%s access without full connection", this->get_client_combined_info().c_str());
|
ESP_LOGD(TAG, "%s (%s) no connection setup", this->client_info_.name.c_str(), this->client_info_.peername.c_str());
|
||||||
}
|
}
|
||||||
void APIConnection::on_fatal_error() {
|
void APIConnection::on_fatal_error() {
|
||||||
this->helper_->close();
|
this->helper_->close();
|
||||||
@@ -1866,8 +1867,8 @@ void APIConnection::process_state_subscriptions_() {
|
|||||||
#endif // USE_API_HOMEASSISTANT_STATES
|
#endif // USE_API_HOMEASSISTANT_STATES
|
||||||
|
|
||||||
void APIConnection::log_warning_(const LogString *message, APIError err) {
|
void APIConnection::log_warning_(const LogString *message, APIError err) {
|
||||||
ESP_LOGW(TAG, "%s: %s %s errno=%d", this->get_client_combined_info().c_str(), LOG_STR_ARG(message),
|
ESP_LOGW(TAG, "%s (%s): %s %s errno=%d", this->client_info_.name.c_str(), this->client_info_.peername.c_str(),
|
||||||
LOG_STR_ARG(api_error_to_logstr(err)), errno);
|
LOG_STR_ARG(message), LOG_STR_ARG(api_error_to_logstr(err)), errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIConnection::log_socket_operation_failed_(APIError err) {
|
void APIConnection::log_socket_operation_failed_(APIError err) {
|
||||||
|
@@ -19,14 +19,6 @@ namespace esphome::api {
|
|||||||
struct ClientInfo {
|
struct ClientInfo {
|
||||||
std::string name; // Client name from Hello message
|
std::string name; // Client name from Hello message
|
||||||
std::string peername; // IP:port from socket
|
std::string peername; // IP:port from socket
|
||||||
|
|
||||||
std::string get_combined_info() const {
|
|
||||||
if (name == peername) {
|
|
||||||
// Before Hello message, both are the same
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
return name + " (" + peername + ")";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Keepalive timeout in milliseconds
|
// Keepalive timeout in milliseconds
|
||||||
@@ -278,7 +270,8 @@ class APIConnection final : 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, uint8_t message_type) override;
|
bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) override;
|
||||||
|
|
||||||
std::string get_client_combined_info() const { return this->client_info_.get_combined_info(); }
|
const std::string &get_name() const { return this->client_info_.name; }
|
||||||
|
const std::string &get_peername() const { return this->client_info_.peername; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Helper function to handle authentication completion
|
// Helper function to handle authentication completion
|
||||||
|
@@ -13,7 +13,8 @@ namespace esphome::api {
|
|||||||
|
|
||||||
static const char *const TAG = "api.frame_helper";
|
static const char *const TAG = "api.frame_helper";
|
||||||
|
|
||||||
#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s: " msg, this->client_info_->get_combined_info().c_str(), ##__VA_ARGS__)
|
#define HELPER_LOG(msg, ...) \
|
||||||
|
ESP_LOGVV(TAG, "%s (%s): " msg, this->client_info_->name.c_str(), this->client_info_->peername.c_str(), ##__VA_ARGS__)
|
||||||
|
|
||||||
#ifdef HELPER_LOG_PACKETS
|
#ifdef HELPER_LOG_PACKETS
|
||||||
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())
|
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())
|
||||||
|
@@ -24,7 +24,8 @@ static const char *const PROLOGUE_INIT = "NoiseAPIInit";
|
|||||||
#endif
|
#endif
|
||||||
static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit")
|
static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit")
|
||||||
|
|
||||||
#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s: " msg, this->client_info_->get_combined_info().c_str(), ##__VA_ARGS__)
|
#define HELPER_LOG(msg, ...) \
|
||||||
|
ESP_LOGVV(TAG, "%s (%s): " msg, this->client_info_->name.c_str(), this->client_info_->peername.c_str(), ##__VA_ARGS__)
|
||||||
|
|
||||||
#ifdef HELPER_LOG_PACKETS
|
#ifdef HELPER_LOG_PACKETS
|
||||||
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())
|
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())
|
||||||
|
@@ -18,7 +18,8 @@ namespace esphome::api {
|
|||||||
|
|
||||||
static const char *const TAG = "api.plaintext";
|
static const char *const TAG = "api.plaintext";
|
||||||
|
|
||||||
#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s: " msg, this->client_info_->get_combined_info().c_str(), ##__VA_ARGS__)
|
#define HELPER_LOG(msg, ...) \
|
||||||
|
ESP_LOGVV(TAG, "%s (%s): " msg, this->client_info_->name.c_str(), this->client_info_->peername.c_str(), ##__VA_ARGS__)
|
||||||
|
|
||||||
#ifdef HELPER_LOG_PACKETS
|
#ifdef HELPER_LOG_PACKETS
|
||||||
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())
|
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())
|
||||||
|
@@ -177,7 +177,8 @@ void APIServer::loop() {
|
|||||||
// Network is down - disconnect all clients
|
// Network is down - disconnect all clients
|
||||||
for (auto &client : this->clients_) {
|
for (auto &client : this->clients_) {
|
||||||
client->on_fatal_error();
|
client->on_fatal_error();
|
||||||
ESP_LOGW(TAG, "%s: Network down; disconnect", client->get_client_combined_info().c_str());
|
ESP_LOGW(TAG, "%s (%s): Network down; disconnect", client->client_info_.name.c_str(),
|
||||||
|
client->client_info_.peername.c_str());
|
||||||
}
|
}
|
||||||
// Continue to process and clean up the clients below
|
// Continue to process and clean up the clients below
|
||||||
}
|
}
|
||||||
|
@@ -55,7 +55,7 @@ template<typename... Ts> class UserServiceBase : public UserServiceDescriptor {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void execute(Ts... x) = 0;
|
virtual void execute(Ts... x) = 0;
|
||||||
template<int... S> void execute_(std::vector<ExecuteServiceArgument> args, seq<S...> type) {
|
template<int... S> void execute_(const std::vector<ExecuteServiceArgument> &args, seq<S...> type) {
|
||||||
this->execute((get_execute_arg_value<Ts>(args[S]))...);
|
this->execute((get_execute_arg_value<Ts>(args[S]))...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@ from esphome.const import (
|
|||||||
CONF_INTERVAL,
|
CONF_INTERVAL,
|
||||||
CONF_MAC_ADDRESS,
|
CONF_MAC_ADDRESS,
|
||||||
CONF_MANUFACTURER_ID,
|
CONF_MANUFACTURER_ID,
|
||||||
|
CONF_MAX_CONNECTIONS,
|
||||||
CONF_ON_BLE_ADVERTISE,
|
CONF_ON_BLE_ADVERTISE,
|
||||||
CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE,
|
CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE,
|
||||||
CONF_ON_BLE_SERVICE_DATA_ADVERTISE,
|
CONF_ON_BLE_SERVICE_DATA_ADVERTISE,
|
||||||
@@ -41,7 +42,6 @@ CODEOWNERS = ["@bdraco"]
|
|||||||
KEY_ESP32_BLE_TRACKER = "esp32_ble_tracker"
|
KEY_ESP32_BLE_TRACKER = "esp32_ble_tracker"
|
||||||
KEY_USED_CONNECTION_SLOTS = "used_connection_slots"
|
KEY_USED_CONNECTION_SLOTS = "used_connection_slots"
|
||||||
|
|
||||||
CONF_MAX_CONNECTIONS = "max_connections"
|
|
||||||
CONF_ESP32_BLE_ID = "esp32_ble_id"
|
CONF_ESP32_BLE_ID = "esp32_ble_id"
|
||||||
CONF_SCAN_PARAMETERS = "scan_parameters"
|
CONF_SCAN_PARAMETERS = "scan_parameters"
|
||||||
CONF_WINDOW = "window"
|
CONF_WINDOW = "window"
|
||||||
|
@@ -67,8 +67,16 @@ static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ESP32Can::setup_internal() {
|
bool ESP32Can::setup_internal() {
|
||||||
|
static int next_twai_ctrl_num = 0;
|
||||||
|
if (next_twai_ctrl_num >= SOC_TWAI_CONTROLLER_NUM) {
|
||||||
|
ESP_LOGW(TAG, "Maximum number of esp32_can components created already");
|
||||||
|
this->mark_failed();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
twai_general_config_t g_config =
|
twai_general_config_t g_config =
|
||||||
TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t) this->tx_, (gpio_num_t) this->rx_, TWAI_MODE_NORMAL);
|
TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t) this->tx_, (gpio_num_t) this->rx_, TWAI_MODE_NORMAL);
|
||||||
|
g_config.controller_id = next_twai_ctrl_num++;
|
||||||
if (this->tx_queue_len_.has_value()) {
|
if (this->tx_queue_len_.has_value()) {
|
||||||
g_config.tx_queue_len = this->tx_queue_len_.value();
|
g_config.tx_queue_len = this->tx_queue_len_.value();
|
||||||
}
|
}
|
||||||
@@ -86,14 +94,14 @@ bool ESP32Can::setup_internal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Install TWAI driver
|
// Install TWAI driver
|
||||||
if (twai_driver_install(&g_config, &t_config, &f_config) != ESP_OK) {
|
if (twai_driver_install_v2(&g_config, &t_config, &f_config, &(this->twai_handle_)) != ESP_OK) {
|
||||||
// Failed to install driver
|
// Failed to install driver
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start TWAI driver
|
// Start TWAI driver
|
||||||
if (twai_start() != ESP_OK) {
|
if (twai_start_v2(this->twai_handle_) != ESP_OK) {
|
||||||
// Failed to start driver
|
// Failed to start driver
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return false;
|
return false;
|
||||||
@@ -102,6 +110,11 @@ bool ESP32Can::setup_internal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canbus::Error ESP32Can::send_message(struct canbus::CanFrame *frame) {
|
canbus::Error ESP32Can::send_message(struct canbus::CanFrame *frame) {
|
||||||
|
if (this->twai_handle_ == nullptr) {
|
||||||
|
// not setup yet or setup failed
|
||||||
|
return canbus::ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (frame->can_data_length_code > canbus::CAN_MAX_DATA_LENGTH) {
|
if (frame->can_data_length_code > canbus::CAN_MAX_DATA_LENGTH) {
|
||||||
return canbus::ERROR_FAILTX;
|
return canbus::ERROR_FAILTX;
|
||||||
}
|
}
|
||||||
@@ -124,7 +137,7 @@ canbus::Error ESP32Can::send_message(struct canbus::CanFrame *frame) {
|
|||||||
memcpy(message.data, frame->data, frame->can_data_length_code);
|
memcpy(message.data, frame->data, frame->can_data_length_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (twai_transmit(&message, this->tx_enqueue_timeout_ticks_) == ESP_OK) {
|
if (twai_transmit_v2(this->twai_handle_, &message, this->tx_enqueue_timeout_ticks_) == ESP_OK) {
|
||||||
return canbus::ERROR_OK;
|
return canbus::ERROR_OK;
|
||||||
} else {
|
} else {
|
||||||
return canbus::ERROR_ALLTXBUSY;
|
return canbus::ERROR_ALLTXBUSY;
|
||||||
@@ -132,9 +145,14 @@ canbus::Error ESP32Can::send_message(struct canbus::CanFrame *frame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canbus::Error ESP32Can::read_message(struct canbus::CanFrame *frame) {
|
canbus::Error ESP32Can::read_message(struct canbus::CanFrame *frame) {
|
||||||
|
if (this->twai_handle_ == nullptr) {
|
||||||
|
// not setup yet or setup failed
|
||||||
|
return canbus::ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
twai_message_t message;
|
twai_message_t message;
|
||||||
|
|
||||||
if (twai_receive(&message, 0) != ESP_OK) {
|
if (twai_receive_v2(this->twai_handle_, &message, 0) != ESP_OK) {
|
||||||
return canbus::ERROR_NOMSG;
|
return canbus::ERROR_NOMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,6 +5,8 @@
|
|||||||
#include "esphome/components/canbus/canbus.h"
|
#include "esphome/components/canbus/canbus.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
|
|
||||||
|
#include <driver/twai.h>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32_can {
|
namespace esp32_can {
|
||||||
|
|
||||||
@@ -29,6 +31,7 @@ class ESP32Can : public canbus::Canbus {
|
|||||||
TickType_t tx_enqueue_timeout_ticks_{};
|
TickType_t tx_enqueue_timeout_ticks_{};
|
||||||
optional<uint32_t> tx_queue_len_{};
|
optional<uint32_t> tx_queue_len_{};
|
||||||
optional<uint32_t> rx_queue_len_{};
|
optional<uint32_t> rx_queue_len_{};
|
||||||
|
twai_handle_t twai_handle_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace esp32_can
|
} // namespace esp32_can
|
||||||
|
@@ -355,9 +355,18 @@ class Logger : public Component {
|
|||||||
buffer[pos++] = '[';
|
buffer[pos++] = '[';
|
||||||
copy_string(buffer, pos, tag);
|
copy_string(buffer, pos, tag);
|
||||||
buffer[pos++] = ':';
|
buffer[pos++] = ':';
|
||||||
buffer[pos++] = '0' + (line / 100) % 10;
|
// Format line number without modulo operations (passed by value, safe to mutate)
|
||||||
buffer[pos++] = '0' + (line / 10) % 10;
|
if (line > 999) [[unlikely]] {
|
||||||
buffer[pos++] = '0' + line % 10;
|
int thousands = line / 1000;
|
||||||
|
buffer[pos++] = '0' + thousands;
|
||||||
|
line -= thousands * 1000;
|
||||||
|
}
|
||||||
|
int hundreds = line / 100;
|
||||||
|
int remainder = line - hundreds * 100;
|
||||||
|
int tens = remainder / 10;
|
||||||
|
buffer[pos++] = '0' + hundreds;
|
||||||
|
buffer[pos++] = '0' + tens;
|
||||||
|
buffer[pos++] = '0' + (remainder - tens * 10);
|
||||||
buffer[pos++] = ']';
|
buffer[pos++] = ']';
|
||||||
|
|
||||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
|
#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
|
||||||
|
@@ -3,11 +3,10 @@
|
|||||||
namespace esphome::logger {
|
namespace esphome::logger {
|
||||||
|
|
||||||
void LoggerLevelSelect::publish_state(int level) {
|
void LoggerLevelSelect::publish_state(int level) {
|
||||||
auto value = this->at(level);
|
const auto &option = this->at(level_to_index(level));
|
||||||
if (!value) {
|
if (!option)
|
||||||
return;
|
return;
|
||||||
}
|
Select::publish_state(option.value());
|
||||||
Select::publish_state(value.value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoggerLevelSelect::setup() {
|
void LoggerLevelSelect::setup() {
|
||||||
@@ -16,10 +15,10 @@ void LoggerLevelSelect::setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LoggerLevelSelect::control(const std::string &value) {
|
void LoggerLevelSelect::control(const std::string &value) {
|
||||||
auto level = this->index_of(value);
|
const auto index = this->index_of(value);
|
||||||
if (!level)
|
if (!index)
|
||||||
return;
|
return;
|
||||||
this->parent_->set_log_level(level.value());
|
this->parent_->set_log_level(index_to_level(index.value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace esphome::logger
|
} // namespace esphome::logger
|
||||||
|
@@ -3,11 +3,18 @@
|
|||||||
#include "esphome/components/select/select.h"
|
#include "esphome/components/select/select.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/components/logger/logger.h"
|
#include "esphome/components/logger/logger.h"
|
||||||
|
|
||||||
namespace esphome::logger {
|
namespace esphome::logger {
|
||||||
class LoggerLevelSelect : public Component, public select::Select, public Parented<Logger> {
|
class LoggerLevelSelect : public Component, public select::Select, public Parented<Logger> {
|
||||||
public:
|
public:
|
||||||
void publish_state(int level);
|
void publish_state(int level);
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void control(const std::string &value) override;
|
void control(const std::string &value) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Convert log level to option index (skip CONFIG at level 4)
|
||||||
|
static uint8_t level_to_index(uint8_t level) { return (level > ESPHOME_LOG_LEVEL_CONFIG) ? level - 1 : level; }
|
||||||
|
// Convert option index to log level (skip CONFIG at level 4)
|
||||||
|
static uint8_t index_to_level(uint8_t index) { return (index >= ESPHOME_LOG_LEVEL_CONFIG) ? index + 1 : index; }
|
||||||
};
|
};
|
||||||
} // namespace esphome::logger
|
} // namespace esphome::logger
|
||||||
|
@@ -13,13 +13,12 @@ static const char *const TAG = "mpr121";
|
|||||||
void MPR121Component::setup() {
|
void MPR121Component::setup() {
|
||||||
// soft reset device
|
// soft reset device
|
||||||
this->write_byte(MPR121_SOFTRESET, 0x63);
|
this->write_byte(MPR121_SOFTRESET, 0x63);
|
||||||
delay(100); // NOLINT
|
this->set_timeout(100, [this]() {
|
||||||
if (!this->write_byte(MPR121_ECR, 0x0)) {
|
if (!this->write_byte(MPR121_ECR, 0x0)) {
|
||||||
this->error_code_ = COMMUNICATION_FAILED;
|
this->error_code_ = COMMUNICATION_FAILED;
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set touch sensitivity for all 12 channels
|
// set touch sensitivity for all 12 channels
|
||||||
for (auto *channel : this->channels_) {
|
for (auto *channel : this->channels_) {
|
||||||
channel->setup();
|
channel->setup();
|
||||||
@@ -52,6 +51,8 @@ void MPR121Component::setup() {
|
|||||||
this->write_byte(MPR121_ECR, 0x80 | (this->max_touch_channel_ + 1));
|
this->write_byte(MPR121_ECR, 0x80 | (this->max_touch_channel_ + 1));
|
||||||
|
|
||||||
this->flush_gpio_();
|
this->flush_gpio_();
|
||||||
|
this->setup_complete_ = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPR121Component::set_touch_debounce(uint8_t debounce) {
|
void MPR121Component::set_touch_debounce(uint8_t debounce) {
|
||||||
@@ -73,15 +74,15 @@ void MPR121Component::dump_config() {
|
|||||||
case COMMUNICATION_FAILED:
|
case COMMUNICATION_FAILED:
|
||||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||||
break;
|
break;
|
||||||
case WRONG_CHIP_STATE:
|
|
||||||
ESP_LOGE(TAG, "MPR121 has wrong default value for CONFIG2?");
|
|
||||||
break;
|
|
||||||
case NONE:
|
case NONE:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void MPR121Component::loop() {
|
void MPR121Component::loop() {
|
||||||
|
if (!this->setup_complete_)
|
||||||
|
return;
|
||||||
|
|
||||||
uint16_t val = 0;
|
uint16_t val = 0;
|
||||||
this->read_byte_16(MPR121_TOUCHSTATUS_L, &val);
|
this->read_byte_16(MPR121_TOUCHSTATUS_L, &val);
|
||||||
|
|
||||||
|
@@ -80,6 +80,7 @@ class MPR121Component : public Component, public i2c::I2CDevice {
|
|||||||
void pin_mode(uint8_t ionum, gpio::Flags flags);
|
void pin_mode(uint8_t ionum, gpio::Flags flags);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool setup_complete_{false};
|
||||||
std::vector<MPR121Channel *> channels_{};
|
std::vector<MPR121Channel *> channels_{};
|
||||||
uint8_t debounce_{0};
|
uint8_t debounce_{0};
|
||||||
uint8_t touch_threshold_{};
|
uint8_t touch_threshold_{};
|
||||||
@@ -88,7 +89,6 @@ class MPR121Component : public Component, public i2c::I2CDevice {
|
|||||||
enum ErrorCode {
|
enum ErrorCode {
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
COMMUNICATION_FAILED,
|
COMMUNICATION_FAILED,
|
||||||
WRONG_CHIP_STATE,
|
|
||||||
} error_code_{NONE};
|
} error_code_{NONE};
|
||||||
|
|
||||||
bool flush_gpio_();
|
bool flush_gpio_();
|
||||||
|
@@ -374,7 +374,7 @@ void Rtttl::loop() {
|
|||||||
this->last_note_ = millis();
|
this->last_note_ = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
|
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||||
static const LogString *state_to_string(State state) {
|
static const LogString *state_to_string(State state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_STOPPED:
|
case STATE_STOPPED:
|
||||||
|
@@ -45,24 +45,26 @@ void SPS30Component::setup() {
|
|||||||
}
|
}
|
||||||
ESP_LOGV(TAG, " Serial number: %s", this->serial_number_);
|
ESP_LOGV(TAG, " Serial number: %s", this->serial_number_);
|
||||||
|
|
||||||
bool result;
|
|
||||||
if (this->fan_interval_.has_value()) {
|
if (this->fan_interval_.has_value()) {
|
||||||
// override default value
|
// override default value
|
||||||
result = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS, this->fan_interval_.value());
|
this->result_ =
|
||||||
|
this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS, this->fan_interval_.value());
|
||||||
} else {
|
} else {
|
||||||
result = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS);
|
this->result_ = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS);
|
||||||
}
|
}
|
||||||
if (result) {
|
|
||||||
delay(20);
|
this->set_timeout(20, [this]() {
|
||||||
|
if (this->result_) {
|
||||||
uint16_t secs[2];
|
uint16_t secs[2];
|
||||||
if (this->read_data(secs, 2)) {
|
if (this->read_data(secs, 2)) {
|
||||||
this->fan_interval_ = secs[0] << 16 | secs[1];
|
this->fan_interval_ = secs[0] << 16 | secs[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->status_clear_warning();
|
this->status_clear_warning();
|
||||||
this->skipped_data_read_cycles_ = 0;
|
this->skipped_data_read_cycles_ = 0;
|
||||||
this->start_continuous_measurement_();
|
this->start_continuous_measurement_();
|
||||||
|
this->setup_complete_ = true;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +113,8 @@ void SPS30Component::dump_config() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SPS30Component::update() {
|
void SPS30Component::update() {
|
||||||
|
if (!this->setup_complete_)
|
||||||
|
return;
|
||||||
/// Check if warning flag active (sensor reconnected?)
|
/// Check if warning flag active (sensor reconnected?)
|
||||||
if (this->status_has_warning()) {
|
if (this->status_has_warning()) {
|
||||||
ESP_LOGD(TAG, "Reconnecting");
|
ESP_LOGD(TAG, "Reconnecting");
|
||||||
|
@@ -30,9 +30,12 @@ class SPS30Component : public PollingComponent, public sensirion_common::Sensiri
|
|||||||
bool start_fan_cleaning();
|
bool start_fan_cleaning();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool result_{false};
|
||||||
|
bool setup_complete_{false};
|
||||||
uint16_t raw_firmware_version_;
|
uint16_t raw_firmware_version_;
|
||||||
char serial_number_[17] = {0}; /// Terminating NULL character
|
char serial_number_[17] = {0}; /// Terminating NULL character
|
||||||
uint8_t skipped_data_read_cycles_ = 0;
|
uint8_t skipped_data_read_cycles_ = 0;
|
||||||
|
|
||||||
bool start_continuous_measurement_();
|
bool start_continuous_measurement_();
|
||||||
|
|
||||||
enum ErrorCode : uint8_t {
|
enum ErrorCode : uint8_t {
|
||||||
|
@@ -429,8 +429,9 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr
|
|||||||
|
|
||||||
if (this->api_client_ != nullptr) {
|
if (this->api_client_ != nullptr) {
|
||||||
ESP_LOGE(TAG, "Multiple API Clients attempting to connect to Voice Assistant");
|
ESP_LOGE(TAG, "Multiple API Clients attempting to connect to Voice Assistant");
|
||||||
ESP_LOGE(TAG, "Current client: %s", this->api_client_->get_client_combined_info().c_str());
|
ESP_LOGE(TAG, "Current client: %s (%s)", this->api_client_->get_name().c_str(),
|
||||||
ESP_LOGE(TAG, "New client: %s", client->get_client_combined_info().c_str());
|
this->api_client_->get_peername().c_str());
|
||||||
|
ESP_LOGE(TAG, "New client: %s (%s)", client->get_name().c_str(), client->get_peername().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -542,6 +542,7 @@ CONF_MANUAL_IP = "manual_ip"
|
|||||||
CONF_MANUFACTURER_ID = "manufacturer_id"
|
CONF_MANUFACTURER_ID = "manufacturer_id"
|
||||||
CONF_MASK_DISTURBER = "mask_disturber"
|
CONF_MASK_DISTURBER = "mask_disturber"
|
||||||
CONF_MAX_BRIGHTNESS = "max_brightness"
|
CONF_MAX_BRIGHTNESS = "max_brightness"
|
||||||
|
CONF_MAX_CONNECTIONS = "max_connections"
|
||||||
CONF_MAX_COOLING_RUN_TIME = "max_cooling_run_time"
|
CONF_MAX_COOLING_RUN_TIME = "max_cooling_run_time"
|
||||||
CONF_MAX_CURRENT = "max_current"
|
CONF_MAX_CURRENT = "max_current"
|
||||||
CONF_MAX_DURATION = "max_duration"
|
CONF_MAX_DURATION = "max_duration"
|
||||||
@@ -1169,7 +1170,7 @@ UNIT_KILOMETER = "km"
|
|||||||
UNIT_KILOMETER_PER_HOUR = "km/h"
|
UNIT_KILOMETER_PER_HOUR = "km/h"
|
||||||
UNIT_KILOVOLT_AMPS = "kVA"
|
UNIT_KILOVOLT_AMPS = "kVA"
|
||||||
UNIT_KILOVOLT_AMPS_HOURS = "kVAh"
|
UNIT_KILOVOLT_AMPS_HOURS = "kVAh"
|
||||||
UNIT_KILOVOLT_AMPS_REACTIVE = "kVAR"
|
UNIT_KILOVOLT_AMPS_REACTIVE = "kvar"
|
||||||
UNIT_KILOVOLT_AMPS_REACTIVE_HOURS = "kvarh"
|
UNIT_KILOVOLT_AMPS_REACTIVE_HOURS = "kvarh"
|
||||||
UNIT_KILOWATT = "kW"
|
UNIT_KILOWATT = "kW"
|
||||||
UNIT_KILOWATT_HOURS = "kWh"
|
UNIT_KILOWATT_HOURS = "kWh"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
pylint==3.3.8
|
pylint==3.3.8
|
||||||
flake8==7.3.0 # also change in .pre-commit-config.yaml when updating
|
flake8==7.3.0 # also change in .pre-commit-config.yaml when updating
|
||||||
ruff==0.13.2 # also change in .pre-commit-config.yaml when updating
|
ruff==0.13.3 # also change in .pre-commit-config.yaml when updating
|
||||||
pyupgrade==3.20.0 # also change in .pre-commit-config.yaml when updating
|
pyupgrade==3.20.0 # also change in .pre-commit-config.yaml when updating
|
||||||
pre-commit
|
pre-commit
|
||||||
|
|
||||||
|
89
tests/components/esp32_can/test.esp32-c6-idf.yaml
Normal file
89
tests/components/esp32_can/test.esp32-c6-idf.yaml
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
esphome:
|
||||||
|
on_boot:
|
||||||
|
then:
|
||||||
|
- canbus.send:
|
||||||
|
# Extended ID explicit
|
||||||
|
canbus_id: esp32_internal_can
|
||||||
|
use_extended_id: true
|
||||||
|
can_id: 0x100
|
||||||
|
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
|
||||||
|
- canbus.send:
|
||||||
|
# Standard ID by default
|
||||||
|
canbus_id: esp32_internal_can
|
||||||
|
can_id: 0x100
|
||||||
|
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
|
||||||
|
- canbus.send:
|
||||||
|
# Extended ID explicit
|
||||||
|
canbus_id: esp32_internal_can_2
|
||||||
|
use_extended_id: true
|
||||||
|
can_id: 0x100
|
||||||
|
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
|
||||||
|
- canbus.send:
|
||||||
|
# Standard ID by default
|
||||||
|
canbus_id: esp32_internal_can_2
|
||||||
|
can_id: 0x100
|
||||||
|
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
|
||||||
|
|
||||||
|
canbus:
|
||||||
|
- platform: esp32_can
|
||||||
|
id: esp32_internal_can
|
||||||
|
rx_pin: GPIO8
|
||||||
|
tx_pin: GPIO7
|
||||||
|
can_id: 4
|
||||||
|
bit_rate: 50kbps
|
||||||
|
on_frame:
|
||||||
|
- can_id: 500
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
std::string b(x.begin(), x.end());
|
||||||
|
ESP_LOGD("canbus1", "canid 500 %s", b.c_str() );
|
||||||
|
- can_id: 0b00000000000000000000001000000
|
||||||
|
can_id_mask: 0b11111000000000011111111000000
|
||||||
|
use_extended_id: true
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
auto pdo_id = can_id >> 14;
|
||||||
|
switch (pdo_id)
|
||||||
|
{
|
||||||
|
case 117:
|
||||||
|
ESP_LOGD("canbus1", "exhaust_fan_duty");
|
||||||
|
break;
|
||||||
|
case 118:
|
||||||
|
ESP_LOGD("canbus1", "supply_fan_duty");
|
||||||
|
break;
|
||||||
|
case 119:
|
||||||
|
ESP_LOGD("canbus1", "supply_fan_flow");
|
||||||
|
break;
|
||||||
|
// to be continued...
|
||||||
|
}
|
||||||
|
- platform: esp32_can
|
||||||
|
id: esp32_internal_can_2
|
||||||
|
rx_pin: GPIO10
|
||||||
|
tx_pin: GPIO9
|
||||||
|
can_id: 4
|
||||||
|
bit_rate: 50kbps
|
||||||
|
on_frame:
|
||||||
|
- can_id: 500
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
std::string b(x.begin(), x.end());
|
||||||
|
ESP_LOGD("canbus2", "canid 500 %s", b.c_str() );
|
||||||
|
- can_id: 0b00000000000000000000001000000
|
||||||
|
can_id_mask: 0b11111000000000011111111000000
|
||||||
|
use_extended_id: true
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
auto pdo_id = can_id >> 14;
|
||||||
|
switch (pdo_id)
|
||||||
|
{
|
||||||
|
case 117:
|
||||||
|
ESP_LOGD("canbus2", "exhaust_fan_duty");
|
||||||
|
break;
|
||||||
|
case 118:
|
||||||
|
ESP_LOGD("canbus2", "supply_fan_duty");
|
||||||
|
break;
|
||||||
|
case 119:
|
||||||
|
ESP_LOGD("canbus2", "supply_fan_flow");
|
||||||
|
break;
|
||||||
|
// to be continued...
|
||||||
|
}
|
Reference in New Issue
Block a user