1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-13 07:13:47 +01:00

Merge remote-tracking branch 'upstream/dev' into bound_tx_buf

This commit is contained in:
J. Nick Koston
2025-10-03 18:38:20 -05:00
28 changed files with 236 additions and 99 deletions

View File

@@ -466,7 +466,7 @@ jobs:
with:
python-version: ${{ env.DEFAULT_PYTHON }}
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:
SKIP: pylint,clang-tidy-hash
- uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0

View File

@@ -58,7 +58,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5
uses: github/codeql-action/init@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -86,6 +86,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5
uses: github/codeql-action/analyze@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6
with:
category: "/language:${{matrix.language}}"

View File

@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Stale
uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0
uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
with:
debug-only: ${{ github.ref != 'refs/heads/dev' }} # Dry-run when not run on dev branch
remove-stale-when-updated: true

View File

@@ -11,7 +11,7 @@ ci:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.13.2
rev: v0.13.3
hooks:
# Run the linter.
- id: ruff

View File

@@ -14,9 +14,11 @@ from typing import Protocol
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
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.const import (
ALLOWED_NAME_CHARS,
@@ -240,6 +242,8 @@ def has_ota() -> bool:
def has_mqtt_ip_lookup() -> bool:
"""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:
return False
# Default Enabled

View File

@@ -14,6 +14,7 @@ from esphome.const import (
CONF_EVENT,
CONF_ID,
CONF_KEY,
CONF_MAX_CONNECTIONS,
CONF_ON_CLIENT_CONNECTED,
CONF_ON_CLIENT_DISCONNECTED,
CONF_PASSWORD,
@@ -60,7 +61,6 @@ CONF_CUSTOM_SERVICES = "custom_services"
CONF_HOMEASSISTANT_SERVICES = "homeassistant_services"
CONF_HOMEASSISTANT_STATES = "homeassistant_states"
CONF_LISTEN_BACKLOG = "listen_backlog"
CONF_MAX_CONNECTIONS = "max_connections"
CONF_MAX_SEND_QUEUE = "max_send_queue"

View File

@@ -205,7 +205,8 @@ void APIConnection::loop() {
// Disconnect if not responded within 2.5*keepalive
if (now - this->last_traffic_ > KEEPALIVE_DISCONNECT_TIMEOUT) {
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) {
// Only send ping if we're not disconnecting
@@ -255,7 +256,7 @@ bool APIConnection::send_disconnect_response(const DisconnectRequest &msg) {
// remote initiated disconnect_client
// don't close yet, we still need to send the disconnect response
// 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;
DisconnectResponse resp;
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);
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
this->parent_->get_client_connected_trigger()->trigger(this->client_info_.name, this->client_info_.peername);
#endif
@@ -1609,12 +1610,12 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) {
#ifdef USE_API_PASSWORD
void APIConnection::on_unauthenticated_access() {
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
void APIConnection::on_no_setup_connection() {
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() {
this->helper_->close();
@@ -1866,8 +1867,8 @@ void APIConnection::process_state_subscriptions_() {
#endif // USE_API_HOMEASSISTANT_STATES
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),
LOG_STR_ARG(api_error_to_logstr(err)), errno);
ESP_LOGW(TAG, "%s (%s): %s %s errno=%d", this->client_info_.name.c_str(), this->client_info_.peername.c_str(),
LOG_STR_ARG(message), LOG_STR_ARG(api_error_to_logstr(err)), errno);
}
void APIConnection::log_socket_operation_failed_(APIError err) {

View File

@@ -19,14 +19,6 @@ namespace esphome::api {
struct ClientInfo {
std::string name; // Client name from Hello message
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
@@ -278,7 +270,8 @@ class APIConnection final : public APIServerConnection {
bool try_to_clear_buffer(bool log_out_of_space);
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:
// Helper function to handle authentication completion

View File

@@ -13,7 +13,8 @@ namespace esphome::api {
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
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())

View File

@@ -24,7 +24,8 @@ static const char *const PROLOGUE_INIT = "NoiseAPIInit";
#endif
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
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())

View File

@@ -18,7 +18,8 @@ namespace esphome::api {
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
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())

View File

@@ -177,7 +177,8 @@ void APIServer::loop() {
// Network is down - disconnect all clients
for (auto &client : this->clients_) {
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
}

View File

@@ -55,7 +55,7 @@ template<typename... Ts> class UserServiceBase : public UserServiceDescriptor {
protected:
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]))...);
}

View File

@@ -24,6 +24,7 @@ from esphome.const import (
CONF_INTERVAL,
CONF_MAC_ADDRESS,
CONF_MANUFACTURER_ID,
CONF_MAX_CONNECTIONS,
CONF_ON_BLE_ADVERTISE,
CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE,
CONF_ON_BLE_SERVICE_DATA_ADVERTISE,
@@ -41,7 +42,6 @@ CODEOWNERS = ["@bdraco"]
KEY_ESP32_BLE_TRACKER = "esp32_ble_tracker"
KEY_USED_CONNECTION_SLOTS = "used_connection_slots"
CONF_MAX_CONNECTIONS = "max_connections"
CONF_ESP32_BLE_ID = "esp32_ble_id"
CONF_SCAN_PARAMETERS = "scan_parameters"
CONF_WINDOW = "window"

View File

@@ -67,8 +67,16 @@ static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config
}
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_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()) {
g_config.tx_queue_len = this->tx_queue_len_.value();
}
@@ -86,14 +94,14 @@ bool ESP32Can::setup_internal() {
}
// 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
this->mark_failed();
return false;
}
// Start TWAI driver
if (twai_start() != ESP_OK) {
if (twai_start_v2(this->twai_handle_) != ESP_OK) {
// Failed to start driver
this->mark_failed();
return false;
@@ -102,6 +110,11 @@ bool ESP32Can::setup_internal() {
}
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) {
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);
}
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;
} else {
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) {
if (this->twai_handle_ == nullptr) {
// not setup yet or setup failed
return canbus::ERROR_FAIL;
}
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;
}

View File

@@ -5,6 +5,8 @@
#include "esphome/components/canbus/canbus.h"
#include "esphome/core/component.h"
#include <driver/twai.h>
namespace esphome {
namespace esp32_can {
@@ -29,6 +31,7 @@ class ESP32Can : public canbus::Canbus {
TickType_t tx_enqueue_timeout_ticks_{};
optional<uint32_t> tx_queue_len_{};
optional<uint32_t> rx_queue_len_{};
twai_handle_t twai_handle_{nullptr};
};
} // namespace esp32_can

View File

@@ -355,9 +355,18 @@ class Logger : public Component {
buffer[pos++] = '[';
copy_string(buffer, pos, tag);
buffer[pos++] = ':';
buffer[pos++] = '0' + (line / 100) % 10;
buffer[pos++] = '0' + (line / 10) % 10;
buffer[pos++] = '0' + line % 10;
// Format line number without modulo operations (passed by value, safe to mutate)
if (line > 999) [[unlikely]] {
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++] = ']';
#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)

View File

@@ -3,11 +3,10 @@
namespace esphome::logger {
void LoggerLevelSelect::publish_state(int level) {
auto value = this->at(level);
if (!value) {
const auto &option = this->at(level_to_index(level));
if (!option)
return;
}
Select::publish_state(value.value());
Select::publish_state(option.value());
}
void LoggerLevelSelect::setup() {
@@ -16,10 +15,10 @@ void LoggerLevelSelect::setup() {
}
void LoggerLevelSelect::control(const std::string &value) {
auto level = this->index_of(value);
if (!level)
const auto index = this->index_of(value);
if (!index)
return;
this->parent_->set_log_level(level.value());
this->parent_->set_log_level(index_to_level(index.value()));
}
} // namespace esphome::logger

View File

@@ -3,11 +3,18 @@
#include "esphome/components/select/select.h"
#include "esphome/core/component.h"
#include "esphome/components/logger/logger.h"
namespace esphome::logger {
class LoggerLevelSelect : public Component, public select::Select, public Parented<Logger> {
public:
void publish_state(int level);
void setup() 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

View File

@@ -13,45 +13,46 @@ static const char *const TAG = "mpr121";
void MPR121Component::setup() {
// soft reset device
this->write_byte(MPR121_SOFTRESET, 0x63);
delay(100); // NOLINT
if (!this->write_byte(MPR121_ECR, 0x0)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
return;
}
this->set_timeout(100, [this]() {
if (!this->write_byte(MPR121_ECR, 0x0)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
return;
}
// set touch sensitivity for all 12 channels
for (auto *channel : this->channels_) {
channel->setup();
}
this->write_byte(MPR121_MHDR, 0x01);
this->write_byte(MPR121_NHDR, 0x01);
this->write_byte(MPR121_NCLR, 0x0E);
this->write_byte(MPR121_FDLR, 0x00);
// set touch sensitivity for all 12 channels
for (auto *channel : this->channels_) {
channel->setup();
}
this->write_byte(MPR121_MHDR, 0x01);
this->write_byte(MPR121_NHDR, 0x01);
this->write_byte(MPR121_NCLR, 0x0E);
this->write_byte(MPR121_FDLR, 0x00);
this->write_byte(MPR121_MHDF, 0x01);
this->write_byte(MPR121_NHDF, 0x05);
this->write_byte(MPR121_NCLF, 0x01);
this->write_byte(MPR121_FDLF, 0x00);
this->write_byte(MPR121_MHDF, 0x01);
this->write_byte(MPR121_NHDF, 0x05);
this->write_byte(MPR121_NCLF, 0x01);
this->write_byte(MPR121_FDLF, 0x00);
this->write_byte(MPR121_NHDT, 0x00);
this->write_byte(MPR121_NCLT, 0x00);
this->write_byte(MPR121_FDLT, 0x00);
this->write_byte(MPR121_NHDT, 0x00);
this->write_byte(MPR121_NCLT, 0x00);
this->write_byte(MPR121_FDLT, 0x00);
this->write_byte(MPR121_DEBOUNCE, 0);
// default, 16uA charge current
this->write_byte(MPR121_CONFIG1, 0x10);
// 0.5uS encoding, 1ms period
this->write_byte(MPR121_CONFIG2, 0x20);
this->write_byte(MPR121_DEBOUNCE, 0);
// default, 16uA charge current
this->write_byte(MPR121_CONFIG1, 0x10);
// 0.5uS encoding, 1ms period
this->write_byte(MPR121_CONFIG2, 0x20);
// Write the Electrode Configuration Register
// * Highest 2 bits is "Calibration Lock", which we set to a value corresponding to 5 bits.
// * The 2 bits below is "Proximity Enable" and are left at 0.
// * The 4 least significant bits control how many electrodes are enabled. Electrodes are enabled
// as a range, starting at 0 up to the highest channel index used.
this->write_byte(MPR121_ECR, 0x80 | (this->max_touch_channel_ + 1));
// Write the Electrode Configuration Register
// * Highest 2 bits is "Calibration Lock", which we set to a value corresponding to 5 bits.
// * The 2 bits below is "Proximity Enable" and are left at 0.
// * The 4 least significant bits control how many electrodes are enabled. Electrodes are enabled
// as a range, starting at 0 up to the highest channel index used.
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) {
@@ -73,15 +74,15 @@ void MPR121Component::dump_config() {
case COMMUNICATION_FAILED:
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case WRONG_CHIP_STATE:
ESP_LOGE(TAG, "MPR121 has wrong default value for CONFIG2?");
break;
case NONE:
default:
break;
}
}
void MPR121Component::loop() {
if (!this->setup_complete_)
return;
uint16_t val = 0;
this->read_byte_16(MPR121_TOUCHSTATUS_L, &val);

View File

@@ -80,6 +80,7 @@ class MPR121Component : public Component, public i2c::I2CDevice {
void pin_mode(uint8_t ionum, gpio::Flags flags);
protected:
bool setup_complete_{false};
std::vector<MPR121Channel *> channels_{};
uint8_t debounce_{0};
uint8_t touch_threshold_{};
@@ -88,7 +89,6 @@ class MPR121Component : public Component, public i2c::I2CDevice {
enum ErrorCode {
NONE = 0,
COMMUNICATION_FAILED,
WRONG_CHIP_STATE,
} error_code_{NONE};
bool flush_gpio_();

View File

@@ -374,7 +374,7 @@ void Rtttl::loop() {
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) {
switch (state) {
case STATE_STOPPED:

View File

@@ -45,24 +45,26 @@ void SPS30Component::setup() {
}
ESP_LOGV(TAG, " Serial number: %s", this->serial_number_);
bool result;
if (this->fan_interval_.has_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 {
result = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS);
}
if (result) {
delay(20);
uint16_t secs[2];
if (this->read_data(secs, 2)) {
this->fan_interval_ = secs[0] << 16 | secs[1];
}
this->result_ = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS);
}
this->status_clear_warning();
this->skipped_data_read_cycles_ = 0;
this->start_continuous_measurement_();
this->set_timeout(20, [this]() {
if (this->result_) {
uint16_t secs[2];
if (this->read_data(secs, 2)) {
this->fan_interval_ = secs[0] << 16 | secs[1];
}
}
this->status_clear_warning();
this->skipped_data_read_cycles_ = 0;
this->start_continuous_measurement_();
this->setup_complete_ = true;
});
});
}
@@ -111,6 +113,8 @@ void SPS30Component::dump_config() {
}
void SPS30Component::update() {
if (!this->setup_complete_)
return;
/// Check if warning flag active (sensor reconnected?)
if (this->status_has_warning()) {
ESP_LOGD(TAG, "Reconnecting");

View File

@@ -30,9 +30,12 @@ class SPS30Component : public PollingComponent, public sensirion_common::Sensiri
bool start_fan_cleaning();
protected:
bool result_{false};
bool setup_complete_{false};
uint16_t raw_firmware_version_;
char serial_number_[17] = {0}; /// Terminating NULL character
uint8_t skipped_data_read_cycles_ = 0;
bool start_continuous_measurement_();
enum ErrorCode : uint8_t {

View File

@@ -429,8 +429,9 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr
if (this->api_client_ != nullptr) {
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, "New client: %s", client->get_client_combined_info().c_str());
ESP_LOGE(TAG, "Current client: %s (%s)", this->api_client_->get_name().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;
}

View File

@@ -542,6 +542,7 @@ CONF_MANUAL_IP = "manual_ip"
CONF_MANUFACTURER_ID = "manufacturer_id"
CONF_MASK_DISTURBER = "mask_disturber"
CONF_MAX_BRIGHTNESS = "max_brightness"
CONF_MAX_CONNECTIONS = "max_connections"
CONF_MAX_COOLING_RUN_TIME = "max_cooling_run_time"
CONF_MAX_CURRENT = "max_current"
CONF_MAX_DURATION = "max_duration"
@@ -1169,7 +1170,7 @@ UNIT_KILOMETER = "km"
UNIT_KILOMETER_PER_HOUR = "km/h"
UNIT_KILOVOLT_AMPS = "kVA"
UNIT_KILOVOLT_AMPS_HOURS = "kVAh"
UNIT_KILOVOLT_AMPS_REACTIVE = "kVAR"
UNIT_KILOVOLT_AMPS_REACTIVE = "kvar"
UNIT_KILOVOLT_AMPS_REACTIVE_HOURS = "kvarh"
UNIT_KILOWATT = "kW"
UNIT_KILOWATT_HOURS = "kWh"

View File

@@ -1,6 +1,6 @@
pylint==3.3.8
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
pre-commit

View 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...
}