Compare commits
8 Commits
memory
...
00eb56d8db
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00eb56d8db | ||
|
|
60eac6ea07 | ||
|
|
9b3ece4caf | ||
|
|
289aedcfe2 | ||
|
|
4cdc804c17 | ||
|
|
56a963dfe6 | ||
|
|
f6f0e52d5e | ||
|
|
eba2c82fec |
@@ -3494,7 +3494,7 @@ bool SubscribeLogsResponse::decode_length(uint32_t field_id, ProtoLengthDelimite
|
||||
}
|
||||
void SubscribeLogsResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_enum<enums::LogLevel>(1, this->level);
|
||||
buffer.encode_string(3, this->message);
|
||||
buffer.encode_bytes(3, reinterpret_cast<const uint8_t *>(this->message.data()), this->message.size());
|
||||
buffer.encode_bool(4, this->send_failed);
|
||||
}
|
||||
void SubscribeLogsResponse::calculate_size(uint32_t &total_size) const {
|
||||
@@ -3530,7 +3530,9 @@ bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthD
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void NoiseEncryptionSetKeyRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->key); }
|
||||
void NoiseEncryptionSetKeyRequest::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bytes(1, reinterpret_cast<const uint8_t *>(this->key.data()), this->key.size());
|
||||
}
|
||||
void NoiseEncryptionSetKeyRequest::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->key, false);
|
||||
}
|
||||
@@ -4267,7 +4269,7 @@ bool CameraImageResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
|
||||
}
|
||||
void CameraImageResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_fixed32(1, this->key);
|
||||
buffer.encode_string(2, this->data);
|
||||
buffer.encode_bytes(2, reinterpret_cast<const uint8_t *>(this->data.data()), this->data.size());
|
||||
buffer.encode_bool(3, this->done);
|
||||
}
|
||||
void CameraImageResponse::calculate_size(uint32_t &total_size) const {
|
||||
@@ -6785,7 +6787,7 @@ void BluetoothServiceData::encode(ProtoWriteBuffer buffer) const {
|
||||
for (auto &it : this->legacy_data) {
|
||||
buffer.encode_uint32(2, it, true);
|
||||
}
|
||||
buffer.encode_string(3, this->data);
|
||||
buffer.encode_bytes(3, reinterpret_cast<const uint8_t *>(this->data.data()), this->data.size());
|
||||
}
|
||||
void BluetoothServiceData::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->uuid, false);
|
||||
@@ -6859,7 +6861,7 @@ bool BluetoothLEAdvertisementResponse::decode_length(uint32_t field_id, ProtoLen
|
||||
}
|
||||
void BluetoothLEAdvertisementResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint64(1, this->address);
|
||||
buffer.encode_string(2, this->name);
|
||||
buffer.encode_bytes(2, reinterpret_cast<const uint8_t *>(this->name.data()), this->name.size());
|
||||
buffer.encode_sint32(3, this->rssi);
|
||||
for (auto &it : this->service_uuids) {
|
||||
buffer.encode_string(4, it, true);
|
||||
@@ -6960,7 +6962,7 @@ void BluetoothLERawAdvertisement::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint64(1, this->address);
|
||||
buffer.encode_sint32(2, this->rssi);
|
||||
buffer.encode_uint32(3, this->address_type);
|
||||
buffer.encode_string(4, this->data);
|
||||
buffer.encode_bytes(4, reinterpret_cast<const uint8_t *>(this->data.data()), this->data.size());
|
||||
}
|
||||
void BluetoothLERawAdvertisement::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_uint64_field(total_size, 1, this->address, false);
|
||||
@@ -7493,7 +7495,7 @@ bool BluetoothGATTReadResponse::decode_length(uint32_t field_id, ProtoLengthDeli
|
||||
void BluetoothGATTReadResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint64(1, this->address);
|
||||
buffer.encode_uint32(2, this->handle);
|
||||
buffer.encode_string(3, this->data);
|
||||
buffer.encode_bytes(3, reinterpret_cast<const uint8_t *>(this->data.data()), this->data.size());
|
||||
}
|
||||
void BluetoothGATTReadResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_uint64_field(total_size, 1, this->address, false);
|
||||
@@ -7552,7 +7554,7 @@ void BluetoothGATTWriteRequest::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint64(1, this->address);
|
||||
buffer.encode_uint32(2, this->handle);
|
||||
buffer.encode_bool(3, this->response);
|
||||
buffer.encode_string(4, this->data);
|
||||
buffer.encode_bytes(4, reinterpret_cast<const uint8_t *>(this->data.data()), this->data.size());
|
||||
}
|
||||
void BluetoothGATTWriteRequest::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_uint64_field(total_size, 1, this->address, false);
|
||||
@@ -7649,7 +7651,7 @@ bool BluetoothGATTWriteDescriptorRequest::decode_length(uint32_t field_id, Proto
|
||||
void BluetoothGATTWriteDescriptorRequest::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint64(1, this->address);
|
||||
buffer.encode_uint32(2, this->handle);
|
||||
buffer.encode_string(3, this->data);
|
||||
buffer.encode_bytes(3, reinterpret_cast<const uint8_t *>(this->data.data()), this->data.size());
|
||||
}
|
||||
void BluetoothGATTWriteDescriptorRequest::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_uint64_field(total_size, 1, this->address, false);
|
||||
@@ -7751,7 +7753,7 @@ bool BluetoothGATTNotifyDataResponse::decode_length(uint32_t field_id, ProtoLeng
|
||||
void BluetoothGATTNotifyDataResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint64(1, this->address);
|
||||
buffer.encode_uint32(2, this->handle);
|
||||
buffer.encode_string(3, this->data);
|
||||
buffer.encode_bytes(3, reinterpret_cast<const uint8_t *>(this->data.data()), this->data.size());
|
||||
}
|
||||
void BluetoothGATTNotifyDataResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_uint64_field(total_size, 1, this->address, false);
|
||||
@@ -8481,7 +8483,7 @@ bool VoiceAssistantAudio::decode_length(uint32_t field_id, ProtoLengthDelimited
|
||||
}
|
||||
}
|
||||
void VoiceAssistantAudio::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(1, this->data);
|
||||
buffer.encode_bytes(1, reinterpret_cast<const uint8_t *>(this->data.data()), this->data.size());
|
||||
buffer.encode_bool(2, this->end);
|
||||
}
|
||||
void VoiceAssistantAudio::calculate_size(uint32_t &total_size) const {
|
||||
|
||||
@@ -93,7 +93,6 @@ class ESP32TouchComponent : public Component {
|
||||
uint32_t last_release_check_{0};
|
||||
uint32_t release_timeout_ms_{1500};
|
||||
uint32_t release_check_interval_ms_{50};
|
||||
bool initial_state_published_[TOUCH_PAD_MAX] = {false};
|
||||
|
||||
// Common configuration parameters
|
||||
uint16_t sleep_cycle_{4095};
|
||||
@@ -123,13 +122,6 @@ class ESP32TouchComponent : public Component {
|
||||
};
|
||||
|
||||
protected:
|
||||
// Design note: last_touch_time_ does not require synchronization primitives because:
|
||||
// 1. ESP32 guarantees atomic 32-bit aligned reads/writes
|
||||
// 2. ISR only writes timestamps, main loop only reads
|
||||
// 3. Timing tolerance allows for occasional stale reads (50ms check interval)
|
||||
// 4. Queue operations provide implicit memory barriers
|
||||
// Using atomic/critical sections would add overhead without meaningful benefit
|
||||
uint32_t last_touch_time_[TOUCH_PAD_MAX] = {0};
|
||||
uint32_t iir_filter_{0};
|
||||
|
||||
bool iir_filter_enabled_() const { return this->iir_filter_ > 0; }
|
||||
@@ -147,9 +139,6 @@ class ESP32TouchComponent : public Component {
|
||||
uint32_t intr_mask;
|
||||
};
|
||||
|
||||
// Track last touch time for timeout-based release detection
|
||||
uint32_t last_touch_time_[TOUCH_PAD_MAX] = {0};
|
||||
|
||||
protected:
|
||||
// Filter configuration
|
||||
touch_filter_mode_t filter_mode_{TOUCH_PAD_FILTER_MAX};
|
||||
@@ -255,11 +244,22 @@ class ESP32TouchBinarySensor : public binary_sensor::BinarySensor {
|
||||
|
||||
touch_pad_t touch_pad_{TOUCH_PAD_MAX};
|
||||
uint32_t threshold_{0};
|
||||
uint32_t benchmark_{};
|
||||
#ifdef USE_ESP32_VARIANT_ESP32
|
||||
uint32_t value_{0};
|
||||
#endif
|
||||
bool last_state_{false};
|
||||
const uint32_t wakeup_threshold_{0};
|
||||
|
||||
// Track last touch time for timeout-based release detection
|
||||
// Design note: last_touch_time_ does not require synchronization primitives because:
|
||||
// 1. ESP32 guarantees atomic 32-bit aligned reads/writes
|
||||
// 2. ISR only writes timestamps, main loop only reads
|
||||
// 3. Timing tolerance allows for occasional stale reads (50ms check interval)
|
||||
// 4. Queue operations provide implicit memory barriers
|
||||
// Using atomic/critical sections would add overhead without meaningful benefit
|
||||
uint32_t last_touch_time_{};
|
||||
bool initial_state_published_{};
|
||||
};
|
||||
|
||||
} // namespace esp32_touch
|
||||
|
||||
@@ -22,16 +22,20 @@ void ESP32TouchComponent::dump_config_base_() {
|
||||
" Sleep cycle: %.2fms\n"
|
||||
" Low Voltage Reference: %s\n"
|
||||
" High Voltage Reference: %s\n"
|
||||
" Voltage Attenuation: %s",
|
||||
" Voltage Attenuation: %s\n"
|
||||
" Release Timeout: %" PRIu32 "ms\n",
|
||||
this->meas_cycle_ / (8000000.0f / 1000.0f), this->sleep_cycle_ / (150000.0f / 1000.0f), lv_s, hv_s,
|
||||
atten_s);
|
||||
atten_s, this->release_timeout_ms_);
|
||||
}
|
||||
|
||||
void ESP32TouchComponent::dump_config_sensors_() {
|
||||
for (auto *child : this->children_) {
|
||||
LOG_BINARY_SENSOR(" ", "Touch Pad", child);
|
||||
ESP_LOGCONFIG(TAG, " Pad: T%" PRIu32, (uint32_t) child->get_touch_pad());
|
||||
ESP_LOGCONFIG(TAG, " Threshold: %" PRIu32, child->get_threshold());
|
||||
ESP_LOGCONFIG(TAG,
|
||||
" Pad: T%u\n"
|
||||
" Threshold: %" PRIu32 "\n"
|
||||
" Benchmark: %" PRIu32,
|
||||
(unsigned) child->touch_pad_, child->threshold_, child->benchmark_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,12 +116,11 @@ bool ESP32TouchComponent::should_check_for_releases_(uint32_t now) {
|
||||
}
|
||||
|
||||
void ESP32TouchComponent::publish_initial_state_if_needed_(ESP32TouchBinarySensor *child, uint32_t now) {
|
||||
touch_pad_t pad = child->get_touch_pad();
|
||||
if (!this->initial_state_published_[pad]) {
|
||||
if (!child->initial_state_published_) {
|
||||
// Check if enough time has passed since startup
|
||||
if (now > this->release_timeout_ms_) {
|
||||
child->publish_initial_state(false);
|
||||
this->initial_state_published_[pad] = true;
|
||||
child->initial_state_published_ = true;
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF (initial)", child->get_name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ void ESP32TouchComponent::loop() {
|
||||
|
||||
// Track when we last saw this pad as touched
|
||||
if (new_state) {
|
||||
this->last_touch_time_[event.pad] = now;
|
||||
child->last_touch_time_ = now;
|
||||
}
|
||||
|
||||
// Only publish if state changed - this filters out repeated events
|
||||
@@ -127,15 +127,13 @@ void ESP32TouchComponent::loop() {
|
||||
|
||||
size_t pads_off = 0;
|
||||
for (auto *child : this->children_) {
|
||||
touch_pad_t pad = child->get_touch_pad();
|
||||
|
||||
// Handle initial state publication after startup
|
||||
this->publish_initial_state_if_needed_(child, now);
|
||||
|
||||
if (child->last_state_) {
|
||||
// Pad is currently in touched state - check for release timeout
|
||||
// Using subtraction handles 32-bit rollover correctly
|
||||
uint32_t time_diff = now - this->last_touch_time_[pad];
|
||||
uint32_t time_diff = now - child->last_touch_time_;
|
||||
|
||||
// Check if we haven't seen this pad recently
|
||||
if (time_diff > this->release_timeout_ms_) {
|
||||
|
||||
@@ -14,19 +14,16 @@ static const char *const TAG = "esp32_touch";
|
||||
void ESP32TouchComponent::update_touch_state_(ESP32TouchBinarySensor *child, bool is_touched) {
|
||||
// Always update timer when touched
|
||||
if (is_touched) {
|
||||
this->last_touch_time_[child->get_touch_pad()] = App.get_loop_component_start_time();
|
||||
child->last_touch_time_ = App.get_loop_component_start_time();
|
||||
}
|
||||
|
||||
if (child->last_state_ != is_touched) {
|
||||
// Read value for logging
|
||||
uint32_t value = this->read_touch_value(child->get_touch_pad());
|
||||
|
||||
child->last_state_ = is_touched;
|
||||
child->publish_state(is_touched);
|
||||
if (is_touched) {
|
||||
// ESP32-S2/S3 v2: touched when value > threshold
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: ON (value: %" PRIu32 " > threshold: %" PRIu32 ")", child->get_name().c_str(),
|
||||
value, child->get_threshold());
|
||||
this->read_touch_value(child->touch_pad_), child->threshold_ + child->benchmark_);
|
||||
} else {
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF", child->get_name().c_str());
|
||||
}
|
||||
@@ -36,10 +33,13 @@ void ESP32TouchComponent::update_touch_state_(ESP32TouchBinarySensor *child, boo
|
||||
// Helper to read touch value and update state for a given child (used for timeout events)
|
||||
bool ESP32TouchComponent::check_and_update_touch_state_(ESP32TouchBinarySensor *child) {
|
||||
// Read current touch value
|
||||
uint32_t value = this->read_touch_value(child->get_touch_pad());
|
||||
uint32_t value = this->read_touch_value(child->touch_pad_);
|
||||
|
||||
// ESP32-S2/S3 v2: Touch is detected when value > threshold
|
||||
bool is_touched = value > child->get_threshold();
|
||||
// ESP32-S2/S3 v2: Touch is detected when value > threshold + benchmark
|
||||
ESP_LOGV(TAG,
|
||||
"Checking touch state for '%s' (T%d): value = %" PRIu32 ", threshold = %" PRIu32 ", benchmark = %" PRIu32,
|
||||
child->get_name().c_str(), child->touch_pad_, value, child->threshold_, child->benchmark_);
|
||||
bool is_touched = value > child->benchmark_ + child->threshold_;
|
||||
|
||||
this->update_touch_state_(child, is_touched);
|
||||
return is_touched;
|
||||
@@ -61,9 +61,9 @@ void ESP32TouchComponent::setup() {
|
||||
|
||||
// Configure each touch pad first
|
||||
for (auto *child : this->children_) {
|
||||
esp_err_t config_err = touch_pad_config(child->get_touch_pad());
|
||||
esp_err_t config_err = touch_pad_config(child->touch_pad_);
|
||||
if (config_err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to configure touch pad %d: %s", child->get_touch_pad(), esp_err_to_name(config_err));
|
||||
ESP_LOGE(TAG, "Failed to configure touch pad %d: %s", child->touch_pad_, esp_err_to_name(config_err));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,8 +100,8 @@ void ESP32TouchComponent::setup() {
|
||||
|
||||
// Configure measurement parameters
|
||||
touch_pad_set_voltage(this->high_voltage_reference_, this->low_voltage_reference_, this->voltage_attenuation_);
|
||||
// ESP32-S2/S3 always use the older API
|
||||
touch_pad_set_meas_time(this->sleep_cycle_, this->meas_cycle_);
|
||||
touch_pad_set_charge_discharge_times(this->meas_cycle_);
|
||||
touch_pad_set_measurement_interval(this->sleep_cycle_);
|
||||
|
||||
// Configure timeout if needed
|
||||
touch_pad_timeout_set(true, TOUCH_PAD_THRESHOLD_MAX);
|
||||
@@ -118,8 +118,8 @@ void ESP32TouchComponent::setup() {
|
||||
|
||||
// Set thresholds for each pad BEFORE starting FSM
|
||||
for (auto *child : this->children_) {
|
||||
if (child->get_threshold() != 0) {
|
||||
touch_pad_set_thresh(child->get_touch_pad(), child->get_threshold());
|
||||
if (child->threshold_ != 0) {
|
||||
touch_pad_set_thresh(child->touch_pad_, child->threshold_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,6 +277,7 @@ void ESP32TouchComponent::loop() {
|
||||
// Process any queued touch events from interrupts
|
||||
TouchPadEventV2 event;
|
||||
while (xQueueReceive(this->touch_queue_, &event, 0) == pdTRUE) {
|
||||
ESP_LOGD(TAG, "Event received, mask = 0x%" PRIx32 ", pad = %d", event.intr_mask, event.pad);
|
||||
// Handle timeout events
|
||||
if (event.intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) {
|
||||
// Resume measurement after timeout
|
||||
@@ -289,18 +290,16 @@ void ESP32TouchComponent::loop() {
|
||||
|
||||
// Find the child for the pad that triggered the interrupt
|
||||
for (auto *child : this->children_) {
|
||||
if (child->get_touch_pad() != event.pad) {
|
||||
continue;
|
||||
if (child->touch_pad_ == event.pad) {
|
||||
if (event.intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) {
|
||||
// For timeout events, we need to read the value to determine state
|
||||
this->check_and_update_touch_state_(child);
|
||||
} else if (event.intr_mask & TOUCH_PAD_INTR_MASK_ACTIVE) {
|
||||
// We only get ACTIVE interrupts now, releases are detected by timeout
|
||||
this->update_touch_state_(child, true); // Always touched for ACTIVE interrupts
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (event.intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) {
|
||||
// For timeout events, we need to read the value to determine state
|
||||
this->check_and_update_touch_state_(child);
|
||||
} else if (event.intr_mask & TOUCH_PAD_INTR_MASK_ACTIVE) {
|
||||
// We only get ACTIVE interrupts now, releases are detected by timeout
|
||||
this->update_touch_state_(child, true); // Always touched for ACTIVE interrupts
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,15 +310,15 @@ void ESP32TouchComponent::loop() {
|
||||
|
||||
size_t pads_off = 0;
|
||||
for (auto *child : this->children_) {
|
||||
touch_pad_t pad = child->get_touch_pad();
|
||||
|
||||
if (child->benchmark_ == 0)
|
||||
touch_pad_read_benchmark(child->touch_pad_, &child->benchmark_);
|
||||
// Handle initial state publication after startup
|
||||
this->publish_initial_state_if_needed_(child, now);
|
||||
|
||||
if (child->last_state_) {
|
||||
// Pad is currently in touched state - check for release timeout
|
||||
// Using subtraction handles 32-bit rollover correctly
|
||||
uint32_t time_diff = now - this->last_touch_time_[pad];
|
||||
uint32_t time_diff = now - child->last_touch_time_;
|
||||
|
||||
// Check if we haven't seen this pad recently
|
||||
if (time_diff > this->release_timeout_ms_) {
|
||||
|
||||
@@ -70,6 +70,7 @@ PROTOCOLS = {
|
||||
"airway": Protocol.PROTOCOL_AIRWAY,
|
||||
"bgh_aud": Protocol.PROTOCOL_BGH_AUD,
|
||||
"panasonic_altdke": Protocol.PROTOCOL_PANASONIC_ALTDKE,
|
||||
"philco_phs32": Protocol.PROTOCOL_PHILCO_PHS32,
|
||||
"vaillantvai8": Protocol.PROTOCOL_VAILLANTVAI8,
|
||||
"r51m": Protocol.PROTOCOL_R51M,
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ const std::map<Protocol, std::function<HeatpumpIR *()>> PROTOCOL_CONSTRUCTOR_MAP
|
||||
{PROTOCOL_AIRWAY, []() { return new AIRWAYHeatpumpIR(); }}, // NOLINT
|
||||
{PROTOCOL_BGH_AUD, []() { return new BGHHeatpumpIR(); }}, // NOLINT
|
||||
{PROTOCOL_PANASONIC_ALTDKE, []() { return new PanasonicAltDKEHeatpumpIR(); }}, // NOLINT
|
||||
{PROTOCOL_PHILCO_PHS32, []() { return new PhilcoPHS32HeatpumpIR(); }}, // NOLINT
|
||||
{PROTOCOL_VAILLANTVAI8, []() { return new VaillantHeatpumpIR(); }}, // NOLINT
|
||||
{PROTOCOL_R51M, []() { return new R51MHeatpumpIR(); }}, // NOLINT
|
||||
};
|
||||
|
||||
@@ -65,6 +65,7 @@ enum Protocol {
|
||||
PROTOCOL_AIRWAY,
|
||||
PROTOCOL_BGH_AUD,
|
||||
PROTOCOL_PANASONIC_ALTDKE,
|
||||
PROTOCOL_PHILCO_PHS32,
|
||||
PROTOCOL_VAILLANTVAI8,
|
||||
PROTOCOL_R51M,
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ from esphome.const import CONF_CHANNEL, CONF_ENABLE_IPV6, CONF_ID
|
||||
import esphome.final_validate as fv
|
||||
|
||||
from .const import (
|
||||
CONF_DEVICE_TYPE,
|
||||
CONF_EXT_PAN_ID,
|
||||
CONF_FORCE_DATASET,
|
||||
CONF_MDNS_ID,
|
||||
@@ -32,6 +33,11 @@ AUTO_LOAD = ["network"]
|
||||
CONFLICTS_WITH = ["wifi"]
|
||||
DEPENDENCIES = ["esp32"]
|
||||
|
||||
CONF_DEVICE_TYPES = [
|
||||
"FTD",
|
||||
"MTD",
|
||||
]
|
||||
|
||||
|
||||
def set_sdkconfig_options(config):
|
||||
# and expose options for using SPI/UART RCPs
|
||||
@@ -82,7 +88,7 @@ def set_sdkconfig_options(config):
|
||||
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_SRP_CLIENT_MAX_SERVICES", 5)
|
||||
|
||||
# TODO: Add suport for sleepy end devices
|
||||
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_FTD", True) # Full Thread Device
|
||||
add_idf_sdkconfig_option(f"CONFIG_OPENTHREAD_{config.get(CONF_DEVICE_TYPE)}", True)
|
||||
|
||||
|
||||
openthread_ns = cg.esphome_ns.namespace("openthread")
|
||||
@@ -107,6 +113,9 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.GenerateID(): cv.declare_id(OpenThreadComponent),
|
||||
cv.GenerateID(CONF_SRP_ID): cv.declare_id(OpenThreadSrpComponent),
|
||||
cv.GenerateID(CONF_MDNS_ID): cv.use_id(MDNSComponent),
|
||||
cv.Optional(CONF_DEVICE_TYPE, default="FTD"): cv.one_of(
|
||||
*CONF_DEVICE_TYPES, upper=True
|
||||
),
|
||||
cv.Optional(CONF_FORCE_DATASET): cv.boolean,
|
||||
cv.Optional(CONF_TLV): cv.string_strict,
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
CONF_DEVICE_TYPE = "device_type"
|
||||
CONF_EXT_PAN_ID = "ext_pan_id"
|
||||
CONF_FORCE_DATASET = "force_dataset"
|
||||
CONF_MDNS_ID = "mdns_id"
|
||||
|
||||
@@ -371,6 +371,7 @@ void Rtttl::finish_() {
|
||||
ESP_LOGD(TAG, "Playback finished");
|
||||
}
|
||||
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
|
||||
static const LogString *state_to_string(State state) {
|
||||
switch (state) {
|
||||
case STATE_STOPPED:
|
||||
@@ -387,6 +388,7 @@ static const LogString *state_to_string(State state) {
|
||||
return LOG_STR("UNKNOWN");
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
void Rtttl::set_state_(State state) {
|
||||
State old_state = this->state_;
|
||||
|
||||
@@ -268,7 +268,19 @@ def validate_tz(value: str) -> str:
|
||||
|
||||
TIME_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_TIMEZONE, default=detect_tz): validate_tz,
|
||||
cv.SplitDefault(
|
||||
CONF_TIMEZONE,
|
||||
esp8266=detect_tz,
|
||||
esp32=detect_tz,
|
||||
rp2040=detect_tz,
|
||||
bk72xx=detect_tz,
|
||||
rtl87xx=detect_tz,
|
||||
ln882x=detect_tz,
|
||||
host=detect_tz,
|
||||
): cv.All(
|
||||
cv.only_with_framework(["arduino", "esp-idf", "host"]),
|
||||
validate_tz,
|
||||
),
|
||||
cv.Optional(CONF_ON_TIME): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CronTrigger),
|
||||
@@ -293,7 +305,9 @@ TIME_SCHEMA = cv.Schema(
|
||||
|
||||
|
||||
async def setup_time_core_(time_var, config):
|
||||
cg.add(time_var.set_timezone(config[CONF_TIMEZONE]))
|
||||
if timezone := config.get(CONF_TIMEZONE):
|
||||
cg.add(time_var.set_timezone(timezone))
|
||||
cg.add_define("USE_TIME_TIMEZONE")
|
||||
|
||||
for conf in config.get(CONF_ON_TIME, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], time_var)
|
||||
|
||||
@@ -35,8 +35,10 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) {
|
||||
ret = settimeofday(&timev, nullptr);
|
||||
}
|
||||
|
||||
#ifdef USE_TIME_TIMEZONE
|
||||
// Move timezone back to local timezone.
|
||||
this->apply_timezone_();
|
||||
#endif
|
||||
|
||||
if (ret != 0) {
|
||||
ESP_LOGW(TAG, "setimeofday() failed with code %d", ret);
|
||||
@@ -49,10 +51,12 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) {
|
||||
this->time_sync_callback_.call();
|
||||
}
|
||||
|
||||
#ifdef USE_TIME_TIMEZONE
|
||||
void RealTimeClock::apply_timezone_() {
|
||||
setenv("TZ", this->timezone_.c_str(), 1);
|
||||
tzset();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace time
|
||||
} // namespace esphome
|
||||
|
||||
@@ -20,6 +20,7 @@ class RealTimeClock : public PollingComponent {
|
||||
public:
|
||||
explicit RealTimeClock();
|
||||
|
||||
#ifdef USE_TIME_TIMEZONE
|
||||
/// Set the time zone.
|
||||
void set_timezone(const std::string &tz) {
|
||||
this->timezone_ = tz;
|
||||
@@ -28,6 +29,7 @@ class RealTimeClock : public PollingComponent {
|
||||
|
||||
/// Get the time zone currently in use.
|
||||
std::string get_timezone() { return this->timezone_; }
|
||||
#endif
|
||||
|
||||
/// Get the time in the currently defined timezone.
|
||||
ESPTime now() { return ESPTime::from_epoch_local(this->timestamp_now()); }
|
||||
@@ -38,7 +40,7 @@ class RealTimeClock : public PollingComponent {
|
||||
/// Get the current time as the UTC epoch since January 1st 1970.
|
||||
time_t timestamp_now() { return ::time(nullptr); }
|
||||
|
||||
void add_on_time_sync_callback(std::function<void()> callback) {
|
||||
void add_on_time_sync_callback(std::function<void()> &&callback) {
|
||||
this->time_sync_callback_.add(std::move(callback));
|
||||
};
|
||||
|
||||
@@ -46,8 +48,10 @@ class RealTimeClock : public PollingComponent {
|
||||
/// Report a unix epoch as current time.
|
||||
void synchronize_epoch_(uint32_t epoch);
|
||||
|
||||
#ifdef USE_TIME_TIMEZONE
|
||||
std::string timezone_{};
|
||||
void apply_timezone_();
|
||||
#endif
|
||||
|
||||
CallbackManager<void()> time_sync_callback_;
|
||||
};
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
#define USE_OTA_PASSWORD
|
||||
#define USE_OTA_STATE_CALLBACK
|
||||
#define USE_OTA_VERSION 2
|
||||
#define USE_TIME_TIMEZONE
|
||||
#define USE_WIFI
|
||||
#define USE_WIFI_AP
|
||||
#define USE_WIREGUARD
|
||||
|
||||
@@ -107,6 +107,11 @@ def storage_should_clean(old: StorageJSON, new: StorageJSON) -> bool:
|
||||
return True
|
||||
if old.build_path != new.build_path:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def storage_should_update_cmake_cache(old: StorageJSON, new: StorageJSON) -> bool:
|
||||
if (
|
||||
old.loaded_integrations != new.loaded_integrations
|
||||
or old.loaded_platforms != new.loaded_platforms
|
||||
@@ -126,10 +131,11 @@ def update_storage_json():
|
||||
return
|
||||
|
||||
if storage_should_clean(old, new):
|
||||
_LOGGER.info(
|
||||
"Core config, version or integrations changed, cleaning build files..."
|
||||
)
|
||||
_LOGGER.info("Core config, version changed, cleaning build files...")
|
||||
clean_build()
|
||||
elif storage_should_update_cmake_cache(old, new):
|
||||
_LOGGER.info("Integrations changed, cleaning cmake cache...")
|
||||
clean_cmake_cache()
|
||||
|
||||
new.save(path)
|
||||
|
||||
@@ -353,6 +359,15 @@ def write_cpp(code_s):
|
||||
write_file_if_changed(path, full_file)
|
||||
|
||||
|
||||
def clean_cmake_cache():
|
||||
pioenvs = CORE.relative_pioenvs_path()
|
||||
if os.path.isdir(pioenvs):
|
||||
pioenvs_cmake_path = CORE.relative_pioenvs_path(CORE.name, "CMakeCache.txt")
|
||||
if os.path.isfile(pioenvs_cmake_path):
|
||||
_LOGGER.info("Deleting %s", pioenvs_cmake_path)
|
||||
os.remove(pioenvs_cmake_path)
|
||||
|
||||
|
||||
def clean_build():
|
||||
import shutil
|
||||
|
||||
|
||||
@@ -526,9 +526,13 @@ class BytesType(TypeInfo):
|
||||
reference_type = "std::string &"
|
||||
const_reference_type = "const std::string &"
|
||||
decode_length = "value.as_string()"
|
||||
encode_func = "encode_string"
|
||||
encode_func = "encode_bytes"
|
||||
wire_type = WireType.LENGTH_DELIMITED # Uses wire type 2
|
||||
|
||||
@property
|
||||
def encode_content(self) -> str:
|
||||
return f"buffer.encode_bytes({self.number}, reinterpret_cast<const uint8_t*>(this->{self.field_name}.data()), this->{self.field_name}.size());"
|
||||
|
||||
def dump(self, name: str) -> str:
|
||||
o = f"out.append(format_hex_pretty({name}));"
|
||||
return o
|
||||
|
||||
@@ -2,6 +2,7 @@ network:
|
||||
enable_ipv6: true
|
||||
|
||||
openthread:
|
||||
device_type: FTD
|
||||
channel: 13
|
||||
network_name: OpenThread-8f28
|
||||
network_key: 0xdfd34f0f05cad978ec4e32b0413038ff
|
||||
|
||||
Reference in New Issue
Block a user