esphome 2025.7.2__py3-none-any.whl → 2025.7.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of esphome might be problematic. Click here for more details.
- esphome/components/bme680_bsec/__init__.py +10 -2
- esphome/components/esp32_touch/esp32_touch_v1.cpp +16 -10
- esphome/components/fastled_clockless/light.py +17 -2
- esphome/components/fastled_spi/light.py +10 -0
- esphome/components/gpio/binary_sensor/__init__.py +19 -1
- esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +20 -21
- esphome/components/ld2450/ld2450.cpp +6 -4
- esphome/components/logger/__init__.py +1 -0
- esphome/components/neopixelbus/light.py +10 -1
- esphome/components/remote_receiver/__init__.py +17 -1
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +1 -2
- esphome/components/sdl/sdl_esphome.cpp +3 -0
- esphome/components/tuya/fan/__init__.py +6 -5
- esphome/components/web_server/ota/ota_web_server.cpp +2 -2
- esphome/config_validation.py +58 -26
- esphome/const.py +1 -1
- esphome/core/application.cpp +39 -24
- esphome/core/application.h +2 -0
- esphome/core/helpers.h +4 -1
- {esphome-2025.7.2.dist-info → esphome-2025.7.4.dist-info}/METADATA +1 -1
- {esphome-2025.7.2.dist-info → esphome-2025.7.4.dist-info}/RECORD +25 -25
- {esphome-2025.7.2.dist-info → esphome-2025.7.4.dist-info}/WHEEL +0 -0
- {esphome-2025.7.2.dist-info → esphome-2025.7.4.dist-info}/entry_points.txt +0 -0
- {esphome-2025.7.2.dist-info → esphome-2025.7.4.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.7.2.dist-info → esphome-2025.7.4.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import esphome.codegen as cg
|
|
2
2
|
from esphome.components import esp32, i2c
|
|
3
3
|
import esphome.config_validation as cv
|
|
4
|
-
from esphome.const import CONF_ID, CONF_SAMPLE_RATE, CONF_TEMPERATURE_OFFSET
|
|
4
|
+
from esphome.const import CONF_ID, CONF_SAMPLE_RATE, CONF_TEMPERATURE_OFFSET, Framework
|
|
5
5
|
|
|
6
6
|
CODEOWNERS = ["@trvrnrth"]
|
|
7
7
|
DEPENDENCIES = ["i2c"]
|
|
@@ -56,7 +56,15 @@ CONFIG_SCHEMA = cv.All(
|
|
|
56
56
|
): cv.positive_time_period_minutes,
|
|
57
57
|
}
|
|
58
58
|
).extend(i2c.i2c_device_schema(0x76)),
|
|
59
|
-
cv.
|
|
59
|
+
cv.only_with_framework(
|
|
60
|
+
frameworks=Framework.ARDUINO,
|
|
61
|
+
suggestions={
|
|
62
|
+
Framework.ESP_IDF: (
|
|
63
|
+
"bme68x_bsec2_i2c",
|
|
64
|
+
"sensor/bme68x_bsec2",
|
|
65
|
+
)
|
|
66
|
+
},
|
|
67
|
+
),
|
|
60
68
|
cv.Any(
|
|
61
69
|
cv.only_on_esp8266,
|
|
62
70
|
cv.All(
|
|
@@ -16,6 +16,8 @@ namespace esp32_touch {
|
|
|
16
16
|
|
|
17
17
|
static const char *const TAG = "esp32_touch";
|
|
18
18
|
|
|
19
|
+
static const uint32_t SETUP_MODE_THRESHOLD = 0xFFFF;
|
|
20
|
+
|
|
19
21
|
void ESP32TouchComponent::setup() {
|
|
20
22
|
// Create queue for touch events
|
|
21
23
|
// Queue size calculation: children * 4 allows for burst scenarios where ISR
|
|
@@ -44,7 +46,11 @@ void ESP32TouchComponent::setup() {
|
|
|
44
46
|
|
|
45
47
|
// Configure each touch pad
|
|
46
48
|
for (auto *child : this->children_) {
|
|
47
|
-
|
|
49
|
+
if (this->setup_mode_) {
|
|
50
|
+
touch_pad_config(child->get_touch_pad(), SETUP_MODE_THRESHOLD);
|
|
51
|
+
} else {
|
|
52
|
+
touch_pad_config(child->get_touch_pad(), child->get_threshold());
|
|
53
|
+
}
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
// Register ISR handler
|
|
@@ -114,8 +120,8 @@ void ESP32TouchComponent::loop() {
|
|
|
114
120
|
child->publish_state(new_state);
|
|
115
121
|
// Original ESP32: ISR only fires when touched, release is detected by timeout
|
|
116
122
|
// Note: ESP32 v1 uses inverted logic - touched when value < threshold
|
|
117
|
-
ESP_LOGV(TAG, "Touch Pad '%s' state:
|
|
118
|
-
child->get_name().c_str(), event.value, child->get_threshold());
|
|
123
|
+
ESP_LOGV(TAG, "Touch Pad '%s' state: %s (value: %" PRIu32 " < threshold: %" PRIu32 ")",
|
|
124
|
+
child->get_name().c_str(), ONOFF(new_state), event.value, child->get_threshold());
|
|
119
125
|
}
|
|
120
126
|
break; // Exit inner loop after processing matching pad
|
|
121
127
|
}
|
|
@@ -188,11 +194,6 @@ void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) {
|
|
|
188
194
|
// as any pad remains touched. This allows us to detect both new touches and
|
|
189
195
|
// continued touches, but releases must be detected by timeout in the main loop.
|
|
190
196
|
|
|
191
|
-
// IMPORTANT: ESP32 v1 touch detection logic - INVERTED compared to v2!
|
|
192
|
-
// ESP32 v1: Touch is detected when capacitance INCREASES, causing the measured value to DECREASE
|
|
193
|
-
// Therefore: touched = (value < threshold)
|
|
194
|
-
// This is opposite to ESP32-S2/S3 v2 where touched = (value > threshold)
|
|
195
|
-
|
|
196
197
|
// Process all configured pads to check their current state
|
|
197
198
|
// Note: ESP32 v1 doesn't tell us which specific pad triggered the interrupt,
|
|
198
199
|
// so we must scan all configured pads to find which ones were touched
|
|
@@ -211,11 +212,16 @@ void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) {
|
|
|
211
212
|
}
|
|
212
213
|
|
|
213
214
|
// Skip pads that aren’t in the trigger mask
|
|
214
|
-
|
|
215
|
-
if (!is_touched) {
|
|
215
|
+
if (((mask >> pad) & 1) == 0) {
|
|
216
216
|
continue;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
// IMPORTANT: ESP32 v1 touch detection logic - INVERTED compared to v2!
|
|
220
|
+
// ESP32 v1: Touch is detected when capacitance INCREASES, causing the measured value to DECREASE
|
|
221
|
+
// Therefore: touched = (value < threshold)
|
|
222
|
+
// This is opposite to ESP32-S2/S3 v2 where touched = (value > threshold)
|
|
223
|
+
bool is_touched = value < child->get_threshold();
|
|
224
|
+
|
|
219
225
|
// Always send the current state - the main loop will filter for changes
|
|
220
226
|
// We send both touched and untouched states because the ISR doesn't
|
|
221
227
|
// track previous state (to keep ISR fast and simple)
|
|
@@ -2,7 +2,13 @@ from esphome import pins
|
|
|
2
2
|
import esphome.codegen as cg
|
|
3
3
|
from esphome.components import fastled_base
|
|
4
4
|
import esphome.config_validation as cv
|
|
5
|
-
from esphome.const import
|
|
5
|
+
from esphome.const import (
|
|
6
|
+
CONF_CHIPSET,
|
|
7
|
+
CONF_NUM_LEDS,
|
|
8
|
+
CONF_PIN,
|
|
9
|
+
CONF_RGB_ORDER,
|
|
10
|
+
Framework,
|
|
11
|
+
)
|
|
6
12
|
|
|
7
13
|
AUTO_LOAD = ["fastled_base"]
|
|
8
14
|
|
|
@@ -48,13 +54,22 @@ CONFIG_SCHEMA = cv.All(
|
|
|
48
54
|
cv.Required(CONF_PIN): pins.internal_gpio_output_pin_number,
|
|
49
55
|
}
|
|
50
56
|
),
|
|
51
|
-
|
|
57
|
+
cv.only_with_framework(
|
|
58
|
+
frameworks=Framework.ARDUINO,
|
|
59
|
+
suggestions={
|
|
60
|
+
Framework.ESP_IDF: (
|
|
61
|
+
"esp32_rmt_led_strip",
|
|
62
|
+
"light/esp32_rmt_led_strip",
|
|
63
|
+
)
|
|
64
|
+
},
|
|
65
|
+
),
|
|
52
66
|
cv.require_framework_version(
|
|
53
67
|
esp8266_arduino=cv.Version(2, 7, 4),
|
|
54
68
|
esp32_arduino=cv.Version(99, 0, 0),
|
|
55
69
|
max_version=True,
|
|
56
70
|
extra_message="Please see note on documentation for FastLED",
|
|
57
71
|
),
|
|
72
|
+
_validate,
|
|
58
73
|
)
|
|
59
74
|
|
|
60
75
|
|
|
@@ -9,6 +9,7 @@ from esphome.const import (
|
|
|
9
9
|
CONF_DATA_RATE,
|
|
10
10
|
CONF_NUM_LEDS,
|
|
11
11
|
CONF_RGB_ORDER,
|
|
12
|
+
Framework,
|
|
12
13
|
)
|
|
13
14
|
|
|
14
15
|
AUTO_LOAD = ["fastled_base"]
|
|
@@ -33,6 +34,15 @@ CONFIG_SCHEMA = cv.All(
|
|
|
33
34
|
cv.Optional(CONF_DATA_RATE): cv.frequency,
|
|
34
35
|
}
|
|
35
36
|
),
|
|
37
|
+
cv.only_with_framework(
|
|
38
|
+
frameworks=Framework.ARDUINO,
|
|
39
|
+
suggestions={
|
|
40
|
+
Framework.ESP_IDF: (
|
|
41
|
+
"spi_led_strip",
|
|
42
|
+
"light/spi_led_strip",
|
|
43
|
+
)
|
|
44
|
+
},
|
|
45
|
+
),
|
|
36
46
|
cv.require_framework_version(
|
|
37
47
|
esp8266_arduino=cv.Version(2, 7, 4),
|
|
38
48
|
esp32_arduino=cv.Version(99, 0, 0),
|
|
@@ -4,7 +4,13 @@ from esphome import pins
|
|
|
4
4
|
import esphome.codegen as cg
|
|
5
5
|
from esphome.components import binary_sensor
|
|
6
6
|
import esphome.config_validation as cv
|
|
7
|
-
from esphome.const import
|
|
7
|
+
from esphome.const import (
|
|
8
|
+
CONF_ALLOW_OTHER_USES,
|
|
9
|
+
CONF_ID,
|
|
10
|
+
CONF_NAME,
|
|
11
|
+
CONF_NUMBER,
|
|
12
|
+
CONF_PIN,
|
|
13
|
+
)
|
|
8
14
|
from esphome.core import CORE
|
|
9
15
|
|
|
10
16
|
from .. import gpio_ns
|
|
@@ -76,6 +82,18 @@ async def to_code(config):
|
|
|
76
82
|
)
|
|
77
83
|
use_interrupt = False
|
|
78
84
|
|
|
85
|
+
# Check if pin is shared with other components (allow_other_uses)
|
|
86
|
+
# When a pin is shared, interrupts can interfere with other components
|
|
87
|
+
# (e.g., duty_cycle sensor) that need to monitor the pin's state changes
|
|
88
|
+
if use_interrupt and config[CONF_PIN].get(CONF_ALLOW_OTHER_USES, False):
|
|
89
|
+
_LOGGER.info(
|
|
90
|
+
"GPIO binary_sensor '%s': Disabling interrupts because pin %s is shared with other components. "
|
|
91
|
+
"The sensor will use polling mode for compatibility with other pin uses.",
|
|
92
|
+
config.get(CONF_NAME, config[CONF_ID]),
|
|
93
|
+
config[CONF_PIN][CONF_NUMBER],
|
|
94
|
+
)
|
|
95
|
+
use_interrupt = False
|
|
96
|
+
|
|
79
97
|
cg.add(var.set_use_interrupt(use_interrupt))
|
|
80
98
|
if use_interrupt:
|
|
81
99
|
cg.add(var.set_interrupt_type(config[CONF_INTERRUPT_TYPE]))
|
|
@@ -8,6 +8,8 @@ namespace gt911 {
|
|
|
8
8
|
|
|
9
9
|
static const char *const TAG = "gt911.touchscreen";
|
|
10
10
|
|
|
11
|
+
static const uint8_t PRIMARY_ADDRESS = 0x5D; // default I2C address for GT911
|
|
12
|
+
static const uint8_t SECONDARY_ADDRESS = 0x14; // secondary I2C address for GT911
|
|
11
13
|
static const uint8_t GET_TOUCH_STATE[2] = {0x81, 0x4E};
|
|
12
14
|
static const uint8_t CLEAR_TOUCH_STATE[3] = {0x81, 0x4E, 0x00};
|
|
13
15
|
static const uint8_t GET_TOUCHES[2] = {0x81, 0x4F};
|
|
@@ -18,8 +20,7 @@ static const size_t MAX_BUTTONS = 4; // max number of buttons scanned
|
|
|
18
20
|
|
|
19
21
|
#define ERROR_CHECK(err) \
|
|
20
22
|
if ((err) != i2c::ERROR_OK) { \
|
|
21
|
-
|
|
22
|
-
this->status_set_warning(); \
|
|
23
|
+
this->status_set_warning("Communication failure"); \
|
|
23
24
|
return; \
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -30,31 +31,31 @@ void GT911Touchscreen::setup() {
|
|
|
30
31
|
this->reset_pin_->setup();
|
|
31
32
|
this->reset_pin_->digital_write(false);
|
|
32
33
|
if (this->interrupt_pin_ != nullptr) {
|
|
33
|
-
//
|
|
34
|
+
// temporarily set the interrupt pin to output to control address selection
|
|
34
35
|
this->interrupt_pin_->pin_mode(gpio::FLAG_OUTPUT);
|
|
35
|
-
this->interrupt_pin_->setup();
|
|
36
36
|
this->interrupt_pin_->digital_write(false);
|
|
37
37
|
}
|
|
38
38
|
delay(2);
|
|
39
39
|
this->reset_pin_->digital_write(true);
|
|
40
40
|
delay(50); // NOLINT
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
}
|
|
42
|
+
if (this->interrupt_pin_ != nullptr) {
|
|
43
|
+
// set pre-configured input mode
|
|
44
|
+
this->interrupt_pin_->setup();
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
// check the configuration of the int line.
|
|
48
48
|
uint8_t data[4];
|
|
49
|
-
err = this->write(GET_SWITCHES,
|
|
49
|
+
err = this->write(GET_SWITCHES, sizeof(GET_SWITCHES));
|
|
50
|
+
if (err != i2c::ERROR_OK && this->address_ == PRIMARY_ADDRESS) {
|
|
51
|
+
this->address_ = SECONDARY_ADDRESS;
|
|
52
|
+
err = this->write(GET_SWITCHES, sizeof(GET_SWITCHES));
|
|
53
|
+
}
|
|
50
54
|
if (err == i2c::ERROR_OK) {
|
|
51
55
|
err = this->read(data, 1);
|
|
52
56
|
if (err == i2c::ERROR_OK) {
|
|
53
|
-
ESP_LOGD(TAG, "Read from switches: 0x%02X", data[0]);
|
|
57
|
+
ESP_LOGD(TAG, "Read from switches at address 0x%02X: 0x%02X", this->address_, data[0]);
|
|
54
58
|
if (this->interrupt_pin_ != nullptr) {
|
|
55
|
-
// datasheet says NOT to use pullup/down on the int line.
|
|
56
|
-
this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT);
|
|
57
|
-
this->interrupt_pin_->setup();
|
|
58
59
|
this->attach_interrupt_(this->interrupt_pin_,
|
|
59
60
|
(data[0] & 1) ? gpio::INTERRUPT_FALLING_EDGE : gpio::INTERRUPT_RISING_EDGE);
|
|
60
61
|
}
|
|
@@ -63,7 +64,7 @@ void GT911Touchscreen::setup() {
|
|
|
63
64
|
if (this->x_raw_max_ == 0 || this->y_raw_max_ == 0) {
|
|
64
65
|
// no calibration? Attempt to read the max values from the touchscreen.
|
|
65
66
|
if (err == i2c::ERROR_OK) {
|
|
66
|
-
err = this->write(GET_MAX_VALUES,
|
|
67
|
+
err = this->write(GET_MAX_VALUES, sizeof(GET_MAX_VALUES));
|
|
67
68
|
if (err == i2c::ERROR_OK) {
|
|
68
69
|
err = this->read(data, sizeof(data));
|
|
69
70
|
if (err == i2c::ERROR_OK) {
|
|
@@ -75,15 +76,12 @@ void GT911Touchscreen::setup() {
|
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
if (err != i2c::ERROR_OK) {
|
|
78
|
-
|
|
79
|
-
this->mark_failed();
|
|
79
|
+
this->mark_failed("Failed to read calibration");
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
if (err != i2c::ERROR_OK) {
|
|
84
|
-
|
|
85
|
-
this->mark_failed();
|
|
86
|
-
return;
|
|
84
|
+
this->mark_failed("Failed to communicate");
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
ESP_LOGCONFIG(TAG, "GT911 Touchscreen setup complete");
|
|
@@ -94,7 +92,7 @@ void GT911Touchscreen::update_touches() {
|
|
|
94
92
|
uint8_t touch_state = 0;
|
|
95
93
|
uint8_t data[MAX_TOUCHES + 1][8]; // 8 bytes each for each point, plus extra space for the key byte
|
|
96
94
|
|
|
97
|
-
err = this->write(GET_TOUCH_STATE, sizeof(GET_TOUCH_STATE)
|
|
95
|
+
err = this->write(GET_TOUCH_STATE, sizeof(GET_TOUCH_STATE));
|
|
98
96
|
ERROR_CHECK(err);
|
|
99
97
|
err = this->read(&touch_state, 1);
|
|
100
98
|
ERROR_CHECK(err);
|
|
@@ -106,7 +104,7 @@ void GT911Touchscreen::update_touches() {
|
|
|
106
104
|
return;
|
|
107
105
|
}
|
|
108
106
|
|
|
109
|
-
err = this->write(GET_TOUCHES, sizeof(GET_TOUCHES)
|
|
107
|
+
err = this->write(GET_TOUCHES, sizeof(GET_TOUCHES));
|
|
110
108
|
ERROR_CHECK(err);
|
|
111
109
|
// num_of_touches is guaranteed to be 0..5. Also read the key data
|
|
112
110
|
err = this->read(data[0], sizeof(data[0]) * num_of_touches + 1);
|
|
@@ -132,6 +130,7 @@ void GT911Touchscreen::dump_config() {
|
|
|
132
130
|
ESP_LOGCONFIG(TAG, "GT911 Touchscreen:");
|
|
133
131
|
LOG_I2C_DEVICE(this);
|
|
134
132
|
LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
|
|
133
|
+
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
|
135
134
|
}
|
|
136
135
|
|
|
137
136
|
} // namespace gt911
|
|
@@ -477,10 +477,11 @@ void LD2450Component::handle_periodic_data_() {
|
|
|
477
477
|
// X
|
|
478
478
|
start = TARGET_X + index * 8;
|
|
479
479
|
is_moving = false;
|
|
480
|
+
// tx is used for further calculations, so always needs to be populated
|
|
481
|
+
val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]);
|
|
482
|
+
tx = val;
|
|
480
483
|
sensor::Sensor *sx = this->move_x_sensors_[index];
|
|
481
484
|
if (sx != nullptr) {
|
|
482
|
-
val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]);
|
|
483
|
-
tx = val;
|
|
484
485
|
if (this->cached_target_data_[index].x != val) {
|
|
485
486
|
sx->publish_state(val);
|
|
486
487
|
this->cached_target_data_[index].x = val;
|
|
@@ -488,10 +489,11 @@ void LD2450Component::handle_periodic_data_() {
|
|
|
488
489
|
}
|
|
489
490
|
// Y
|
|
490
491
|
start = TARGET_Y + index * 8;
|
|
492
|
+
// ty is used for further calculations, so always needs to be populated
|
|
493
|
+
val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]);
|
|
494
|
+
ty = val;
|
|
491
495
|
sensor::Sensor *sy = this->move_y_sensors_[index];
|
|
492
496
|
if (sy != nullptr) {
|
|
493
|
-
val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]);
|
|
494
|
-
ty = val;
|
|
495
497
|
if (this->cached_target_data_[index].y != val) {
|
|
496
498
|
sy->publish_state(val);
|
|
497
499
|
this->cached_target_data_[index].y = val;
|
|
@@ -400,6 +400,7 @@ CONF_LOGGER_LOG = "logger.log"
|
|
|
400
400
|
LOGGER_LOG_ACTION_SCHEMA = cv.All(
|
|
401
401
|
cv.maybe_simple_value(
|
|
402
402
|
{
|
|
403
|
+
cv.GenerateID(CONF_LOGGER_ID): cv.use_id(Logger),
|
|
403
404
|
cv.Required(CONF_FORMAT): cv.string,
|
|
404
405
|
cv.Optional(CONF_ARGS, default=list): cv.ensure_list(cv.lambda_),
|
|
405
406
|
cv.Optional(CONF_LEVEL, default="DEBUG"): cv.one_of(
|
|
@@ -15,6 +15,7 @@ from esphome.const import (
|
|
|
15
15
|
CONF_PIN,
|
|
16
16
|
CONF_TYPE,
|
|
17
17
|
CONF_VARIANT,
|
|
18
|
+
Framework,
|
|
18
19
|
)
|
|
19
20
|
from esphome.core import CORE
|
|
20
21
|
|
|
@@ -162,7 +163,15 @@ def _validate_method(value):
|
|
|
162
163
|
|
|
163
164
|
|
|
164
165
|
CONFIG_SCHEMA = cv.All(
|
|
165
|
-
cv.
|
|
166
|
+
cv.only_with_framework(
|
|
167
|
+
frameworks=Framework.ARDUINO,
|
|
168
|
+
suggestions={
|
|
169
|
+
Framework.ESP_IDF: (
|
|
170
|
+
"esp32_rmt_led_strip",
|
|
171
|
+
"light/esp32_rmt_led_strip",
|
|
172
|
+
)
|
|
173
|
+
},
|
|
174
|
+
),
|
|
166
175
|
cv.require_framework_version(
|
|
167
176
|
esp8266_arduino=cv.Version(2, 4, 0),
|
|
168
177
|
esp32_arduino=cv.Version(0, 0, 0),
|
|
@@ -60,6 +60,20 @@ RemoteReceiverComponent = remote_receiver_ns.class_(
|
|
|
60
60
|
)
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
def validate_config(config):
|
|
64
|
+
if CORE.is_esp32:
|
|
65
|
+
variant = esp32.get_esp32_variant()
|
|
66
|
+
if variant in (esp32.const.VARIANT_ESP32, esp32.const.VARIANT_ESP32S2):
|
|
67
|
+
max_idle = 65535
|
|
68
|
+
else:
|
|
69
|
+
max_idle = 32767
|
|
70
|
+
if CONF_CLOCK_RESOLUTION in config:
|
|
71
|
+
max_idle = int(max_idle * 1000000 / config[CONF_CLOCK_RESOLUTION])
|
|
72
|
+
if config[CONF_IDLE].total_microseconds > max_idle:
|
|
73
|
+
raise cv.Invalid(f"config 'idle' exceeds the maximum value of {max_idle}us")
|
|
74
|
+
return config
|
|
75
|
+
|
|
76
|
+
|
|
63
77
|
def validate_tolerance(value):
|
|
64
78
|
if isinstance(value, dict):
|
|
65
79
|
return TOLERANCE_SCHEMA(value)
|
|
@@ -136,7 +150,9 @@ CONFIG_SCHEMA = remote_base.validate_triggers(
|
|
|
136
150
|
cv.boolean,
|
|
137
151
|
),
|
|
138
152
|
}
|
|
139
|
-
)
|
|
153
|
+
)
|
|
154
|
+
.extend(cv.COMPONENT_SCHEMA)
|
|
155
|
+
.add_extra(validate_config)
|
|
140
156
|
)
|
|
141
157
|
|
|
142
158
|
|
|
@@ -86,10 +86,9 @@ void RemoteReceiverComponent::setup() {
|
|
|
86
86
|
|
|
87
87
|
uint32_t event_size = sizeof(rmt_rx_done_event_data_t);
|
|
88
88
|
uint32_t max_filter_ns = 255u * 1000 / (RMT_CLK_FREQ / 1000000);
|
|
89
|
-
uint32_t max_idle_ns = 65535u * 1000;
|
|
90
89
|
memset(&this->store_.config, 0, sizeof(this->store_.config));
|
|
91
90
|
this->store_.config.signal_range_min_ns = std::min(this->filter_us_ * 1000, max_filter_ns);
|
|
92
|
-
this->store_.config.signal_range_max_ns =
|
|
91
|
+
this->store_.config.signal_range_max_ns = this->idle_us_ * 1000;
|
|
93
92
|
this->store_.filter_symbols = this->filter_symbols_;
|
|
94
93
|
this->store_.receive_size = this->receive_symbols_ * sizeof(rmt_symbol_word_t);
|
|
95
94
|
this->store_.buffer_size = std::max((event_size + this->store_.receive_size) * 2, this->buffer_size_);
|
|
@@ -48,6 +48,9 @@ void Sdl::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
void Sdl::draw_pixel_at(int x, int y, Color color) {
|
|
51
|
+
if (!this->get_clipping().inside(x, y))
|
|
52
|
+
return;
|
|
53
|
+
|
|
51
54
|
SDL_Rect rect{x, y, 1, 1};
|
|
52
55
|
auto data = (display::ColorUtil::color_to_565(color, display::COLOR_ORDER_RGB));
|
|
53
56
|
SDL_UpdateTexture(this->texture_, &rect, &data, 2);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import esphome.codegen as cg
|
|
2
2
|
from esphome.components import fan
|
|
3
3
|
import esphome.config_validation as cv
|
|
4
|
-
from esphome.const import
|
|
4
|
+
from esphome.const import CONF_ID, CONF_SPEED_COUNT, CONF_SWITCH_DATAPOINT
|
|
5
5
|
|
|
6
6
|
from .. import CONF_TUYA_ID, Tuya, tuya_ns
|
|
7
7
|
|
|
@@ -14,9 +14,9 @@ CONF_DIRECTION_DATAPOINT = "direction_datapoint"
|
|
|
14
14
|
TuyaFan = tuya_ns.class_("TuyaFan", cg.Component, fan.Fan)
|
|
15
15
|
|
|
16
16
|
CONFIG_SCHEMA = cv.All(
|
|
17
|
-
fan.
|
|
17
|
+
fan.fan_schema(TuyaFan)
|
|
18
|
+
.extend(
|
|
18
19
|
{
|
|
19
|
-
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(TuyaFan),
|
|
20
20
|
cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya),
|
|
21
21
|
cv.Optional(CONF_OSCILLATION_DATAPOINT): cv.uint8_t,
|
|
22
22
|
cv.Optional(CONF_SPEED_DATAPOINT): cv.uint8_t,
|
|
@@ -24,7 +24,8 @@ CONFIG_SCHEMA = cv.All(
|
|
|
24
24
|
cv.Optional(CONF_DIRECTION_DATAPOINT): cv.uint8_t,
|
|
25
25
|
cv.Optional(CONF_SPEED_COUNT, default=3): cv.int_range(min=1, max=256),
|
|
26
26
|
}
|
|
27
|
-
)
|
|
27
|
+
)
|
|
28
|
+
.extend(cv.COMPONENT_SCHEMA),
|
|
28
29
|
cv.has_at_least_one_key(CONF_SPEED_DATAPOINT, CONF_SWITCH_DATAPOINT),
|
|
29
30
|
)
|
|
30
31
|
|
|
@@ -32,7 +33,7 @@ CONFIG_SCHEMA = cv.All(
|
|
|
32
33
|
async def to_code(config):
|
|
33
34
|
parent = await cg.get_variable(config[CONF_TUYA_ID])
|
|
34
35
|
|
|
35
|
-
var = cg.new_Pvariable(config[
|
|
36
|
+
var = cg.new_Pvariable(config[CONF_ID], parent, config[CONF_SPEED_COUNT])
|
|
36
37
|
await cg.register_component(var, config)
|
|
37
38
|
await fan.register_fan(var, config)
|
|
38
39
|
|
|
@@ -76,7 +76,7 @@ void OTARequestHandler::report_ota_progress_(AsyncWebServerRequest *request) {
|
|
|
76
76
|
percentage = (this->ota_read_length_ * 100.0f) / request->contentLength();
|
|
77
77
|
ESP_LOGD(TAG, "OTA in progress: %0.1f%%", percentage);
|
|
78
78
|
} else {
|
|
79
|
-
ESP_LOGD(TAG, "OTA in progress: %
|
|
79
|
+
ESP_LOGD(TAG, "OTA in progress: %" PRIu32 " bytes read", this->ota_read_length_);
|
|
80
80
|
}
|
|
81
81
|
#ifdef USE_OTA_STATE_CALLBACK
|
|
82
82
|
// Report progress - use call_deferred since we're in web server task
|
|
@@ -171,7 +171,7 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin
|
|
|
171
171
|
|
|
172
172
|
// Finalize
|
|
173
173
|
if (final) {
|
|
174
|
-
ESP_LOGD(TAG, "OTA final chunk: index=%zu, len=%zu, total_read=%
|
|
174
|
+
ESP_LOGD(TAG, "OTA final chunk: index=%zu, len=%zu, total_read=%" PRIu32 ", contentLength=%zu", index, len,
|
|
175
175
|
this->ota_read_length_, request->contentLength());
|
|
176
176
|
|
|
177
177
|
// For Arduino framework, the Update library tracks expected size from firmware header
|
esphome/config_validation.py
CHANGED
|
@@ -73,6 +73,7 @@ from esphome.const import (
|
|
|
73
73
|
TYPE_GIT,
|
|
74
74
|
TYPE_LOCAL,
|
|
75
75
|
VALID_SUBSTITUTIONS_CHARACTERS,
|
|
76
|
+
Framework,
|
|
76
77
|
__version__ as ESPHOME_VERSION,
|
|
77
78
|
)
|
|
78
79
|
from esphome.core import (
|
|
@@ -282,6 +283,38 @@ class FinalExternalInvalid(Invalid):
|
|
|
282
283
|
"""Represents an invalid value in the final validation phase where the path should not be prepended."""
|
|
283
284
|
|
|
284
285
|
|
|
286
|
+
@dataclass(frozen=True, order=True)
|
|
287
|
+
class Version:
|
|
288
|
+
major: int
|
|
289
|
+
minor: int
|
|
290
|
+
patch: int
|
|
291
|
+
extra: str = ""
|
|
292
|
+
|
|
293
|
+
def __str__(self):
|
|
294
|
+
return f"{self.major}.{self.minor}.{self.patch}"
|
|
295
|
+
|
|
296
|
+
@classmethod
|
|
297
|
+
def parse(cls, value: str) -> Version:
|
|
298
|
+
match = re.match(r"^(\d+).(\d+).(\d+)-?(\w*)$", value)
|
|
299
|
+
if match is None:
|
|
300
|
+
raise ValueError(f"Not a valid version number {value}")
|
|
301
|
+
major = int(match[1])
|
|
302
|
+
minor = int(match[2])
|
|
303
|
+
patch = int(match[3])
|
|
304
|
+
extra = match[4] or ""
|
|
305
|
+
return Version(major=major, minor=minor, patch=patch, extra=extra)
|
|
306
|
+
|
|
307
|
+
@property
|
|
308
|
+
def is_beta(self) -> bool:
|
|
309
|
+
"""Check if this version is a beta version."""
|
|
310
|
+
return self.extra.startswith("b")
|
|
311
|
+
|
|
312
|
+
@property
|
|
313
|
+
def is_dev(self) -> bool:
|
|
314
|
+
"""Check if this version is a development version."""
|
|
315
|
+
return self.extra.startswith("dev")
|
|
316
|
+
|
|
317
|
+
|
|
285
318
|
def check_not_templatable(value):
|
|
286
319
|
if isinstance(value, Lambda):
|
|
287
320
|
raise Invalid("This option is not templatable!")
|
|
@@ -619,16 +652,35 @@ def only_on(platforms):
|
|
|
619
652
|
return validator_
|
|
620
653
|
|
|
621
654
|
|
|
622
|
-
def only_with_framework(
|
|
655
|
+
def only_with_framework(
|
|
656
|
+
frameworks: Framework | str | list[Framework | str], suggestions=None
|
|
657
|
+
):
|
|
623
658
|
"""Validate that this option can only be specified on the given frameworks."""
|
|
624
659
|
if not isinstance(frameworks, list):
|
|
625
660
|
frameworks = [frameworks]
|
|
626
661
|
|
|
662
|
+
frameworks = [Framework(framework) for framework in frameworks]
|
|
663
|
+
|
|
664
|
+
if suggestions is None:
|
|
665
|
+
suggestions = {}
|
|
666
|
+
|
|
667
|
+
version = Version.parse(ESPHOME_VERSION)
|
|
668
|
+
if version.is_beta:
|
|
669
|
+
docs_format = "https://beta.esphome.io/components/{path}"
|
|
670
|
+
elif version.is_dev:
|
|
671
|
+
docs_format = "https://next.esphome.io/components/{path}"
|
|
672
|
+
else:
|
|
673
|
+
docs_format = "https://esphome.io/components/{path}"
|
|
674
|
+
|
|
627
675
|
def validator_(obj):
|
|
628
676
|
if CORE.target_framework not in frameworks:
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
677
|
+
err_str = f"This feature is only available with framework(s) {', '.join([framework.value for framework in frameworks])}"
|
|
678
|
+
if suggestion := suggestions.get(CORE.target_framework, None):
|
|
679
|
+
(component, docs_path) = suggestion
|
|
680
|
+
err_str += f"\nPlease use '{component}'"
|
|
681
|
+
if docs_path:
|
|
682
|
+
err_str += f": {docs_format.format(path=docs_path)}"
|
|
683
|
+
raise Invalid(err_str)
|
|
632
684
|
return obj
|
|
633
685
|
|
|
634
686
|
return validator_
|
|
@@ -637,8 +689,8 @@ def only_with_framework(frameworks):
|
|
|
637
689
|
only_on_esp32 = only_on(PLATFORM_ESP32)
|
|
638
690
|
only_on_esp8266 = only_on(PLATFORM_ESP8266)
|
|
639
691
|
only_on_rp2040 = only_on(PLATFORM_RP2040)
|
|
640
|
-
only_with_arduino = only_with_framework(
|
|
641
|
-
only_with_esp_idf = only_with_framework(
|
|
692
|
+
only_with_arduino = only_with_framework(Framework.ARDUINO)
|
|
693
|
+
only_with_esp_idf = only_with_framework(Framework.ESP_IDF)
|
|
642
694
|
|
|
643
695
|
|
|
644
696
|
# Adapted from:
|
|
@@ -1965,26 +2017,6 @@ def source_refresh(value: str):
|
|
|
1965
2017
|
return positive_time_period_seconds(value)
|
|
1966
2018
|
|
|
1967
2019
|
|
|
1968
|
-
@dataclass(frozen=True, order=True)
|
|
1969
|
-
class Version:
|
|
1970
|
-
major: int
|
|
1971
|
-
minor: int
|
|
1972
|
-
patch: int
|
|
1973
|
-
|
|
1974
|
-
def __str__(self):
|
|
1975
|
-
return f"{self.major}.{self.minor}.{self.patch}"
|
|
1976
|
-
|
|
1977
|
-
@classmethod
|
|
1978
|
-
def parse(cls, value: str) -> Version:
|
|
1979
|
-
match = re.match(r"^(\d+).(\d+).(\d+)-?\w*$", value)
|
|
1980
|
-
if match is None:
|
|
1981
|
-
raise ValueError(f"Not a valid version number {value}")
|
|
1982
|
-
major = int(match[1])
|
|
1983
|
-
minor = int(match[2])
|
|
1984
|
-
patch = int(match[3])
|
|
1985
|
-
return Version(major=major, minor=minor, patch=patch)
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
2020
|
def version_number(value):
|
|
1989
2021
|
value = string_strict(value)
|
|
1990
2022
|
try:
|
esphome/const.py
CHANGED
esphome/core/application.cpp
CHANGED
|
@@ -68,8 +68,11 @@ void Application::setup() {
|
|
|
68
68
|
|
|
69
69
|
do {
|
|
70
70
|
uint8_t new_app_state = STATUS_LED_WARNING;
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
uint32_t now = millis();
|
|
72
|
+
|
|
73
|
+
// Process pending loop enables to handle GPIO interrupts during setup
|
|
74
|
+
this->before_loop_tasks_(now);
|
|
75
|
+
|
|
73
76
|
for (uint32_t j = 0; j <= i; j++) {
|
|
74
77
|
// Update loop_component_start_time_ right before calling each component
|
|
75
78
|
this->loop_component_start_time_ = millis();
|
|
@@ -78,6 +81,8 @@ void Application::setup() {
|
|
|
78
81
|
this->app_state_ |= new_app_state;
|
|
79
82
|
this->feed_wdt();
|
|
80
83
|
}
|
|
84
|
+
|
|
85
|
+
this->after_loop_tasks_();
|
|
81
86
|
this->app_state_ = new_app_state;
|
|
82
87
|
yield();
|
|
83
88
|
} while (!component->can_proceed());
|
|
@@ -94,30 +99,10 @@ void Application::setup() {
|
|
|
94
99
|
void Application::loop() {
|
|
95
100
|
uint8_t new_app_state = 0;
|
|
96
101
|
|
|
97
|
-
this->scheduler.call();
|
|
98
|
-
|
|
99
102
|
// Get the initial loop time at the start
|
|
100
103
|
uint32_t last_op_end_time = millis();
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
this->feed_wdt(last_op_end_time);
|
|
104
|
-
|
|
105
|
-
// Process any pending enable_loop requests from ISRs
|
|
106
|
-
// This must be done before marking in_loop_ = true to avoid race conditions
|
|
107
|
-
if (this->has_pending_enable_loop_requests_) {
|
|
108
|
-
// Clear flag BEFORE processing to avoid race condition
|
|
109
|
-
// If ISR sets it during processing, we'll catch it next loop iteration
|
|
110
|
-
// This is safe because:
|
|
111
|
-
// 1. Each component has its own pending_enable_loop_ flag that we check
|
|
112
|
-
// 2. If we can't process a component (wrong state), enable_pending_loops_()
|
|
113
|
-
// will set this flag back to true
|
|
114
|
-
// 3. Any new ISR requests during processing will set the flag again
|
|
115
|
-
this->has_pending_enable_loop_requests_ = false;
|
|
116
|
-
this->enable_pending_loops_();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Mark that we're in the loop for safe reentrant modifications
|
|
120
|
-
this->in_loop_ = true;
|
|
105
|
+
this->before_loop_tasks_(last_op_end_time);
|
|
121
106
|
|
|
122
107
|
for (this->current_loop_index_ = 0; this->current_loop_index_ < this->looping_components_active_end_;
|
|
123
108
|
this->current_loop_index_++) {
|
|
@@ -138,7 +123,7 @@ void Application::loop() {
|
|
|
138
123
|
this->feed_wdt(last_op_end_time);
|
|
139
124
|
}
|
|
140
125
|
|
|
141
|
-
this->
|
|
126
|
+
this->after_loop_tasks_();
|
|
142
127
|
this->app_state_ = new_app_state;
|
|
143
128
|
|
|
144
129
|
// Use the last component's end time instead of calling millis() again
|
|
@@ -400,6 +385,36 @@ void Application::enable_pending_loops_() {
|
|
|
400
385
|
}
|
|
401
386
|
}
|
|
402
387
|
|
|
388
|
+
void Application::before_loop_tasks_(uint32_t loop_start_time) {
|
|
389
|
+
// Process scheduled tasks
|
|
390
|
+
this->scheduler.call();
|
|
391
|
+
|
|
392
|
+
// Feed the watchdog timer
|
|
393
|
+
this->feed_wdt(loop_start_time);
|
|
394
|
+
|
|
395
|
+
// Process any pending enable_loop requests from ISRs
|
|
396
|
+
// This must be done before marking in_loop_ = true to avoid race conditions
|
|
397
|
+
if (this->has_pending_enable_loop_requests_) {
|
|
398
|
+
// Clear flag BEFORE processing to avoid race condition
|
|
399
|
+
// If ISR sets it during processing, we'll catch it next loop iteration
|
|
400
|
+
// This is safe because:
|
|
401
|
+
// 1. Each component has its own pending_enable_loop_ flag that we check
|
|
402
|
+
// 2. If we can't process a component (wrong state), enable_pending_loops_()
|
|
403
|
+
// will set this flag back to true
|
|
404
|
+
// 3. Any new ISR requests during processing will set the flag again
|
|
405
|
+
this->has_pending_enable_loop_requests_ = false;
|
|
406
|
+
this->enable_pending_loops_();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Mark that we're in the loop for safe reentrant modifications
|
|
410
|
+
this->in_loop_ = true;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
void Application::after_loop_tasks_() {
|
|
414
|
+
// Clear the in_loop_ flag to indicate we're done processing components
|
|
415
|
+
this->in_loop_ = false;
|
|
416
|
+
}
|
|
417
|
+
|
|
403
418
|
#ifdef USE_SOCKET_SELECT_SUPPORT
|
|
404
419
|
bool Application::register_socket_fd(int fd) {
|
|
405
420
|
// WARNING: This function is NOT thread-safe and must only be called from the main loop
|
esphome/core/application.h
CHANGED
|
@@ -504,6 +504,8 @@ class Application {
|
|
|
504
504
|
void enable_component_loop_(Component *component);
|
|
505
505
|
void enable_pending_loops_();
|
|
506
506
|
void activate_looping_component_(uint16_t index);
|
|
507
|
+
void before_loop_tasks_(uint32_t loop_start_time);
|
|
508
|
+
void after_loop_tasks_();
|
|
507
509
|
|
|
508
510
|
void feed_wdt_arch_();
|
|
509
511
|
|
esphome/core/helpers.h
CHANGED
|
@@ -67,7 +67,10 @@ To bit_cast(const From &src) {
|
|
|
67
67
|
return dst;
|
|
68
68
|
}
|
|
69
69
|
#endif
|
|
70
|
-
|
|
70
|
+
|
|
71
|
+
// clang-format off
|
|
72
|
+
inline float lerp(float completion, float start, float end) = delete; // Please use std::lerp. Notice that it has different order on arguments!
|
|
73
|
+
// clang-format on
|
|
71
74
|
|
|
72
75
|
// std::byteswap from C++23
|
|
73
76
|
template<typename T> constexpr T byteswap(T n) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: esphome
|
|
3
|
-
Version: 2025.7.
|
|
3
|
+
Version: 2025.7.4
|
|
4
4
|
Summary: ESPHome is a system to configure your microcontrollers by simple yet powerful configuration files and control them remotely through Home Automation systems.
|
|
5
5
|
Author-email: The ESPHome Authors <esphome@openhomefoundation.org>
|
|
6
6
|
License: MIT
|
|
@@ -4,8 +4,8 @@ esphome/automation.py,sha256=9xmW3AmWDd2oKB7zF-UITYIiSci8ys8qiylK-rcU7Rg,15689
|
|
|
4
4
|
esphome/codegen.py,sha256=H_WB4rj0uEowvlhEb31EjJQwutLQ5CQkJIsNgDK-wx8,1917
|
|
5
5
|
esphome/config.py,sha256=b-Gh-DEx_pax0ZKqHTKb5gmMIvaQA71bJvE-15AI0JI,42211
|
|
6
6
|
esphome/config_helpers.py,sha256=BpyuWRxj5edJGIW7VP4S59i4I8g8baSlWpNyu6nB_uM,5413
|
|
7
|
-
esphome/config_validation.py,sha256=
|
|
8
|
-
esphome/const.py,sha256=
|
|
7
|
+
esphome/config_validation.py,sha256=QUNpomRbIhqTaSrZZXNFcTQdPibGPbYDNSo5sTIzqCI,64924
|
|
8
|
+
esphome/const.py,sha256=TiaRIL8HNMH-_mcJANWLuu8l8f5Mnv0Z59u7fw7TzZg,43367
|
|
9
9
|
esphome/coroutine.py,sha256=HNBqqhaTbpvsOI19bTXltxJCMVtoeqZPe4qTf4CKkAc,9309
|
|
10
10
|
esphome/cpp_generator.py,sha256=khmyuRIOc-ST9zIZjX7uOWLy9sSJhk4C2KexoBv51uk,31946
|
|
11
11
|
esphome/cpp_helpers.py,sha256=P9FVGpid75_UcKxIf-sj7GbhWGQNRcBm_2XVF3r7NtU,3998
|
|
@@ -402,7 +402,7 @@ esphome/components/bme680/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
|
402
402
|
esphome/components/bme680/bme680.cpp,sha256=R_OJihYGYxFUqjK_C8Kcdtf0jNKxEwEWdusQN5ByCkU,16994
|
|
403
403
|
esphome/components/bme680/bme680.h,sha256=zdTFcpzNb3nSPy7q9V3iSJ5uBsmoZgJkzxU3Fcwf_BY,4678
|
|
404
404
|
esphome/components/bme680/sensor.py,sha256=fjZOcC0AymBF4f3vdgd-WfTfkqL0QrCOnaXdnGvGolU,5801
|
|
405
|
-
esphome/components/bme680_bsec/__init__.py,sha256=
|
|
405
|
+
esphome/components/bme680_bsec/__init__.py,sha256=FmtARbE-B7Dkb1FnOWQavaAdOggraJqrDIocHitQrmI,3062
|
|
406
406
|
esphome/components/bme680_bsec/bme680_bsec.cpp,sha256=ja1s94_Gh6HhhXhJiuT5f_rChHy87tgyHurmmMF1Tx8,22705
|
|
407
407
|
esphome/components/bme680_bsec/bme680_bsec.h,sha256=aUGZXwSiu0wOlt13_mxhy0yKxToAInX2rnhZ_UQc7TM,5907
|
|
408
408
|
esphome/components/bme680_bsec/sensor.py,sha256=Y4efGwK7zDHbS8ET7o-bF__A86OJsZt2Ypl4sRtqKLE,4114
|
|
@@ -915,7 +915,7 @@ esphome/components/esp32_touch/__init__.py,sha256=zcxxAkhMPOd--SZyngwDEW-Q9AYcWm
|
|
|
915
915
|
esphome/components/esp32_touch/binary_sensor.py,sha256=JV0p5Ovn4E1EVj6L4JEmRJ--L-D7HWGK2PaQLE9hs3E,1165
|
|
916
916
|
esphome/components/esp32_touch/esp32_touch.h,sha256=Br1-5Lh4U6xmvrM59iuPe5hR6cmO-LO5vSoyc49k9QY,9644
|
|
917
917
|
esphome/components/esp32_touch/esp32_touch_common.cpp,sha256=engSTGARGHfLIwjceV2xrg0y0yX_gpb8MjoK2zd6KZQ,5703
|
|
918
|
-
esphome/components/esp32_touch/esp32_touch_v1.cpp,sha256=
|
|
918
|
+
esphome/components/esp32_touch/esp32_touch_v1.cpp,sha256=v1tGKlHazj2gJFEfQDPIJKR8Q90x_GmlA2DQo3nnteU,8492
|
|
919
919
|
esphome/components/esp32_touch/esp32_touch_v2.cpp,sha256=SZPbpG3fOrJNMkzcJIYFubi4YcTspnVp58iO-_7rJdM,13475
|
|
920
920
|
esphome/components/esp8266/__init__.py,sha256=-2xGbrwE5P4eTmQZRcoKwjBhtCVgnhdh3kEsrqYcGSI,9683
|
|
921
921
|
esphome/components/esp8266/boards.py,sha256=p2btoDa36gfr9QsCOBZuME7Pi20Xf2LcQ_F-oeMFFA8,8647
|
|
@@ -987,9 +987,9 @@ esphome/components/fastled_base/__init__.py,sha256=5Re6yi_0HOCts-U-iiyNKvsQUEBzS
|
|
|
987
987
|
esphome/components/fastled_base/fastled_light.cpp,sha256=MFLr1AV4mTxIQMwxTBg8RtbPuwex7y3nlHbulHdtdps,1369
|
|
988
988
|
esphome/components/fastled_base/fastled_light.h,sha256=Xmv5WA6XuZNGClpiITMo6f73i8P0Z5YoYtlUVhQj2FI,8593
|
|
989
989
|
esphome/components/fastled_clockless/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
990
|
-
esphome/components/fastled_clockless/light.py,sha256=
|
|
990
|
+
esphome/components/fastled_clockless/light.py,sha256=M9x-UAPjmHuaFJR0U1jNgD69Q1FiWTtoRsosju7J8gU,1950
|
|
991
991
|
esphome/components/fastled_spi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
992
|
-
esphome/components/fastled_spi/light.py,sha256=
|
|
992
|
+
esphome/components/fastled_spi/light.py,sha256=KjvKzYWQ82iPdgEXicjZO8VYaQQoHSJ_UQ6gi22fbPE,2107
|
|
993
993
|
esphome/components/feedback/__init__.py,sha256=GjTE91yQyeMDCmGmxAgQwsB9ohUUw83JSCmIi2_sujg,25
|
|
994
994
|
esphome/components/feedback/cover.py,sha256=NuS-WNv7RFctg3jrBjPm6moIlNGgtmXvspdD1_CPgsM,6324
|
|
995
995
|
esphome/components/feedback/feedback_cover.cpp,sha256=bvZ-dgN3zh8Ivc2BvSPO4QKTQuVIFm_AiTUgTUIHnE8,16241
|
|
@@ -1044,7 +1044,7 @@ esphome/components/gp8403/output/__init__.py,sha256=3VX9AD0N0SRXdOfKJcMMgjCwA1-R
|
|
|
1044
1044
|
esphome/components/gp8403/output/gp8403_output.cpp,sha256=FQPUa_ZMgLz7LNHy6N8sNUpnI2hwOIZTRrwWtjXrbGs,714
|
|
1045
1045
|
esphome/components/gp8403/output/gp8403_output.h,sha256=wJd_-CtUSxw5ujhR21E1zCiB9hvpl3Ktt665D3iQLf4,598
|
|
1046
1046
|
esphome/components/gpio/__init__.py,sha256=afIFpPG_fsom-8vYV1yRyvhSCFyASlAdraUCuztWQZ4,103
|
|
1047
|
-
esphome/components/gpio/binary_sensor/__init__.py,sha256=
|
|
1047
|
+
esphome/components/gpio/binary_sensor/__init__.py,sha256=1rCKRDCrbINcJN6m0gRYgyGTouuVpK-s_IV6cGgivUE,3594
|
|
1048
1048
|
esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp,sha256=wVa5pNQMnUOO9RUovnf6G8MYQtKQoRSojA3MItHLnbg,3131
|
|
1049
1049
|
esphome/components/gpio/binary_sensor/gpio_binary_sensor.h,sha256=ukwmyxJhiYXMczcT16zwdliTX5Brf8fdgDzid6l13wE,2000
|
|
1050
1050
|
esphome/components/gpio/one_wire/__init__.py,sha256=oH6-6zy18pG_7iqzLegjh4AbjnbZHqBRZKHdHBI-828,714
|
|
@@ -1090,7 +1090,7 @@ esphome/components/gt911/binary_sensor/__init__.py,sha256=iLJRYUsSFiY0BeJMH0RQ1A
|
|
|
1090
1090
|
esphome/components/gt911/binary_sensor/gt911_button.cpp,sha256=KACuxHcVbk3TZdSPy-8kO4j0LZZZmdAy4VWMicnaoLY,586
|
|
1091
1091
|
esphome/components/gt911/binary_sensor/gt911_button.h,sha256=3QCm3g8Ca9VtsKKjWgc_Bre4Dc3RhXgaLt1Mq3iEKd8,714
|
|
1092
1092
|
esphome/components/gt911/touchscreen/__init__.py,sha256=Hx69_ljCE1F-dP5BzEoQ7vIcOTy9_AsnDBb9FH3pCpU,1155
|
|
1093
|
-
esphome/components/gt911/touchscreen/gt911_touchscreen.cpp,sha256=
|
|
1093
|
+
esphome/components/gt911/touchscreen/gt911_touchscreen.cpp,sha256=AIfOlB5kudlaw-NIEsQOb_MDBzTOadf0q3kSNajtByI,4770
|
|
1094
1094
|
esphome/components/gt911/touchscreen/gt911_touchscreen.h,sha256=q-ZvP6OEGk8TU9eNfWI5-Bj5lVz-DXkxEGEiSzYr2L0,1026
|
|
1095
1095
|
esphome/components/haier/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1096
1096
|
esphome/components/haier/automation.h,sha256=xHnMbqHWFwtibKxgqLraPeNlKLWv2_AT7VX0aMVYtr8,3688
|
|
@@ -1455,7 +1455,7 @@ esphome/components/ld2420/text_sensor/text_sensor.cpp,sha256=6rvT1dp3u9Fpmpm-3kH
|
|
|
1455
1455
|
esphome/components/ld2420/text_sensor/text_sensor.h,sha256=aK91ri0NvHth3ya0zN1OeX81v1nqveoiJcOfqCpaAJI,672
|
|
1456
1456
|
esphome/components/ld2450/__init__.py,sha256=n6KvEkMsoaR3DUix1a1MGq-ZyjAAIAKDZ0lYN7iKSpQ,1267
|
|
1457
1457
|
esphome/components/ld2450/binary_sensor.py,sha256=SyIw9c-4JqNm8JKuzSKA9rVWaVCGsYAslV0VbhqJnoM,1755
|
|
1458
|
-
esphome/components/ld2450/ld2450.cpp,sha256=
|
|
1458
|
+
esphome/components/ld2450/ld2450.cpp,sha256=YpWKOjueeC0dXrh4gJemnbnXBpIUv-UjLMx2uvGp70w,35639
|
|
1459
1459
|
esphome/components/ld2450/ld2450.h,sha256=azHWHt9CdUL2R80km7_ahTjEc7OUgsIzDWq9apVrtCg,8292
|
|
1460
1460
|
esphome/components/ld2450/sensor.py,sha256=91vupem8yF0nfMaLLkjaRsaarWxxNxKXLvT6WiaimDo,6568
|
|
1461
1461
|
esphome/components/ld2450/text_sensor.py,sha256=msgqwIFvkSrewI7MP_KPKMWdMOEpPFOj0hhsfudUfho,2009
|
|
@@ -1550,7 +1550,7 @@ esphome/components/lock/__init__.py,sha256=z2ykcnNNmzRbri8sqwqQmbX0WtEkBV_Tazr1R
|
|
|
1550
1550
|
esphome/components/lock/automation.h,sha256=7MU5AuJizydt7mKTr_uFsNleFI2jeBf7B_dNp3e8Fks,1771
|
|
1551
1551
|
esphome/components/lock/lock.cpp,sha256=IyEt5xShAxMpmcn_GAPFv2lRCS-kr4MjjfExxfXuK-Q,3212
|
|
1552
1552
|
esphome/components/lock/lock.h,sha256=p_t5cG-75MNGVM8zEyfKJlziSjeUiIbpYan3tlZG6W8,6042
|
|
1553
|
-
esphome/components/logger/__init__.py,sha256=
|
|
1553
|
+
esphome/components/logger/__init__.py,sha256=3T2mSo2rmK87MINepmYAW6nF6kloLvLueb_dIPyXCJM,16265
|
|
1554
1554
|
esphome/components/logger/logger.cpp,sha256=aIra5ZZ5OEAPuqDgxZd3zkyAf46Jchht6mx-mcv380U,11704
|
|
1555
1555
|
esphome/components/logger/logger.h,sha256=Tkdz9qoSTiyx6Ebp9jBUnGMXyxG1iH6LTJoJfguTOaA,14460
|
|
1556
1556
|
esphome/components/logger/logger_esp32.cpp,sha256=NJddudDpsMP1fdV0mel8zXd7VNgMxqRIfarLp3uJPe0,6220
|
|
@@ -2028,7 +2028,7 @@ esphome/components/nau7802/sensor.py,sha256=1_p7nQLcClL3l5FX3qZ627wf9cP8h8Yt4yl7
|
|
|
2028
2028
|
esphome/components/neopixelbus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2029
2029
|
esphome/components/neopixelbus/_methods.py,sha256=zWtt2M2kG4V3iYlvEWZn-BGuTlmCnTvT2VYjiRn3NiY,14544
|
|
2030
2030
|
esphome/components/neopixelbus/const.py,sha256=8dPnqN1skzSEnjjsr3H2Q3BJOEn-TyFB1PApCSSsYUw,824
|
|
2031
|
-
esphome/components/neopixelbus/light.py,sha256=
|
|
2031
|
+
esphome/components/neopixelbus/light.py,sha256=mGs_W1AuFwzw9_nft_vZdpeX3Z4fe0QNrm49lj15YRc,7572
|
|
2032
2032
|
esphome/components/neopixelbus/neopixelbus_light.h,sha256=flA7U9l1Bfj7Vdii4wwi2ukVG_RO0mvL6kNaa_k3xBI,4680
|
|
2033
2033
|
esphome/components/network/__init__.py,sha256=4SVVU4J6pPdGUY_Tz1zEZm4E1LzITStl1RMMMWR71A4,2218
|
|
2034
2034
|
esphome/components/network/ip_address.h,sha256=tTltJn7qkuxr1_BhSTUYOBItZG-d3eBus04C5GEOS08,4552
|
|
@@ -2464,10 +2464,10 @@ esphome/components/remote_base/toshiba_ac_protocol.cpp,sha256=CQNONh4-M91jPDecR_
|
|
|
2464
2464
|
esphome/components/remote_base/toshiba_ac_protocol.h,sha256=xkpVmBNtQ_uEbMHzwaJOle2KXBxa34Q-ABZfuCsMouA,1092
|
|
2465
2465
|
esphome/components/remote_base/toto_protocol.cpp,sha256=GxWkvuGXo3ThBQ3Q7ogNRrMYWHxjxcmeWRZj0JxZ1eM,2601
|
|
2466
2466
|
esphome/components/remote_base/toto_protocol.h,sha256=ZN4X6heapkxFeA0k5acAgRpGjzaB8SiKs2ABEvaDfns,1275
|
|
2467
|
-
esphome/components/remote_receiver/__init__.py,sha256=
|
|
2467
|
+
esphome/components/remote_receiver/__init__.py,sha256=0d8i1tuM-VQkJ8S6XMDHBuPqcgmdrUzxOOo37bk7SVA,6696
|
|
2468
2468
|
esphome/components/remote_receiver/binary_sensor.py,sha256=AybkaXQkJpcxpJhDkbgupO9zIiVhBFYpxvjUHBQbs_w,291
|
|
2469
2469
|
esphome/components/remote_receiver/remote_receiver.h,sha256=Rl2MH_ZclRL889h5Tiig15Yf_EX6KbsKcezuLSiKQlQ,2885
|
|
2470
|
-
esphome/components/remote_receiver/remote_receiver_esp32.cpp,sha256=
|
|
2470
|
+
esphome/components/remote_receiver/remote_receiver_esp32.cpp,sha256=tZlNUOJ24yoywp-ZDF4WptKp-RK6B6-b-0N2CLPvUS0,9024
|
|
2471
2471
|
esphome/components/remote_receiver/remote_receiver_esp8266.cpp,sha256=CDLSICGZ360ewhn1rgVDaKzwR-TOFqqRGjYusElNT0g,4535
|
|
2472
2472
|
esphome/components/remote_receiver/remote_receiver_libretiny.cpp,sha256=742G1k3RNETru9kbFHn5Ax3NE_OVt6EqeWWVDUNKj9Y,4490
|
|
2473
2473
|
esphome/components/remote_transmitter/__init__.py,sha256=wE9ogHpnVTbBPLn9pZH5qhyYi_mYzRHd5pKJ96uvuUc,3867
|
|
@@ -2574,7 +2574,7 @@ esphome/components/script/script.h,sha256=0z4aoCBM2x2RLtpk0LNs3biHIS--rDzhfQjN-S
|
|
|
2574
2574
|
esphome/components/sdl/__init__.py,sha256=4Nn7UhpMJ9oSbuLdyVEW7G9PlIey2v33SWRNVizt9Oc,30
|
|
2575
2575
|
esphome/components/sdl/binary_sensor.py,sha256=0fXpK11HIO9fpRqnyhN-nshlmKCgqXGK1OBlInQjOL4,6528
|
|
2576
2576
|
esphome/components/sdl/display.py,sha256=mVm2J93NP-a0_Z70b6Rz_305-jIO8Rt2Kcxnc3rp5tw,3385
|
|
2577
|
-
esphome/components/sdl/sdl_esphome.cpp,sha256=
|
|
2577
|
+
esphome/components/sdl/sdl_esphome.cpp,sha256=sc5r_zZuy_bg2iX50tZYRL_KyRZaeQfdWSGZVzolqK4,4087
|
|
2578
2578
|
esphome/components/sdl/sdl_esphome.h,sha256=S_HSX0cQYI3oUWHVPPwv9dFVhbhTUYitnO5o5GNeX28,2373
|
|
2579
2579
|
esphome/components/sdl/touchscreen/__init__.py,sha256=VhcFG1Vc_i4eIYHoV4_Nb3VlanUCr0r9RPAM5BMKr9Y,633
|
|
2580
2580
|
esphome/components/sdl/touchscreen/sdl_touchscreen.h,sha256=dgw2wGuEvjX6zbPjqMOPLkOl-aVYVWxY7n7Gc_kAKm0,595
|
|
@@ -3229,7 +3229,7 @@ esphome/components/tuya/climate/tuya_climate.h,sha256=16nLDVoVwyd6fOtqq9SqRSQu17
|
|
|
3229
3229
|
esphome/components/tuya/cover/__init__.py,sha256=zNsaJUYfibX_38oe9mQ-19UhXIWXNBOVbNWwr4bq3yo,2947
|
|
3230
3230
|
esphome/components/tuya/cover/tuya_cover.cpp,sha256=0VKNLg0zDy7EPk7sRQC6aL1QjV7832tmubbPenbQW3Y,4369
|
|
3231
3231
|
esphome/components/tuya/cover/tuya_cover.h,sha256=9S9_X7xuiusjDRfsXw_aV6_7i8P9WpMOvOg-dlyOrz8,1787
|
|
3232
|
-
esphome/components/tuya/fan/__init__.py,sha256=
|
|
3232
|
+
esphome/components/tuya/fan/__init__.py,sha256=nHTmFEtNcASuOrBHeixTUpzvQYtYHsb0F_bRLSYutgk,1734
|
|
3233
3233
|
esphome/components/tuya/fan/tuya_fan.cpp,sha256=KZTNjsQtSAIr4JXf2VKocxBANqORi7jaC5BsUt-gNWs,4330
|
|
3234
3234
|
esphome/components/tuya/fan/tuya_fan.h,sha256=nYKtPdShhbQl05W83rAFS4CxKbsY2jhp5N11k1c2alk,1114
|
|
3235
3235
|
esphome/components/tuya/light/__init__.py,sha256=mZj2c72EhHo8CHwkNFvn58jmj7mycIzHPRY5F5Th3VI,4858
|
|
@@ -3396,7 +3396,7 @@ esphome/components/web_server/web_server.cpp,sha256=bwc2jb7b4-7mtrztGpW9SMWseuh3
|
|
|
3396
3396
|
esphome/components/web_server/web_server.h,sha256=AGCOdOaZe7Xe5nCL4rHhqWNg-uo5cc6nu84vQr4GdrQ,21558
|
|
3397
3397
|
esphome/components/web_server/web_server_v1.cpp,sha256=ZnFV1J2YAzAT2mtR-eeVgG1TSVpy953EF1yVKYdTcTg,7409
|
|
3398
3398
|
esphome/components/web_server/ota/__init__.py,sha256=w4Ufe8mN-5r0913AODCjl9LlCKMpWRTFMSCEmLgRzxE,1018
|
|
3399
|
-
esphome/components/web_server/ota/ota_web_server.cpp,sha256=
|
|
3399
|
+
esphome/components/web_server/ota/ota_web_server.cpp,sha256=q-GKNDmwjonXaBOndktCulkJfrCSpmCGqcreuJxtRJI,8158
|
|
3400
3400
|
esphome/components/web_server/ota/ota_web_server.h,sha256=ZZQHTxb21gqukibGei-om00MxpBD4Qyy031PXBMmjT8,604
|
|
3401
3401
|
esphome/components/web_server_base/__init__.py,sha256=uM9rrhE1Pu_yvwfrLLHheh1ip_9mL2JSZC5NrrBdrj0,1281
|
|
3402
3402
|
esphome/components/web_server_base/web_server_base.cpp,sha256=plEcGgYKFku3cSlv7rNAPC6GMWkjIflie3yVERoHDNA,876
|
|
@@ -3593,8 +3593,8 @@ esphome/components/zyaura/sensor.py,sha256=cSmO4ozYdi4ZD7NK4lmYjswWVmJoDvEruU1Hh
|
|
|
3593
3593
|
esphome/components/zyaura/zyaura.cpp,sha256=F7WM8XAZ5MYuCD3eERm2_IA-O7sP1i-A-yF5TV4PqX8,3679
|
|
3594
3594
|
esphome/components/zyaura/zyaura.h,sha256=7O3EGFIopUEfBp3A5sBC0l4zx2mesRxDWa_MBdGtPKQ,2307
|
|
3595
3595
|
esphome/core/__init__.py,sha256=uWhgtqaPGiMeMp6KMvRs60gvFG_4jabueLzKTMuVAHc,28445
|
|
3596
|
-
esphome/core/application.cpp,sha256=
|
|
3597
|
-
esphome/core/application.h,sha256=
|
|
3596
|
+
esphome/core/application.cpp,sha256=wrjr4SVAWMarEo-cKJ_eUfarCrSrWzqoK2-oA74wPYU,19182
|
|
3597
|
+
esphome/core/application.h,sha256=psgw-_TDgZQLK00Kg5A9Y-B17Mkdn4WeMzmOkyX2e98,21929
|
|
3598
3598
|
esphome/core/area.h,sha256=mtFxmuv8fC2hArcey3cZ0F6hMXSO2QpFZ9Xv49z4rvk,393
|
|
3599
3599
|
esphome/core/automation.h,sha256=UgoI-ebaL5YJ_cyRB-3ijHQxzt4cTbTaWw4eRGoOwBI,8627
|
|
3600
3600
|
esphome/core/base_automation.h,sha256=C-6op63m-ghuaUy-q515XAx7iKjoxBFbQeRLmRtQGSM,11230
|
|
@@ -3618,7 +3618,7 @@ esphome/core/event_pool.h,sha256=X8_-72rODgpG9P_dSjezkJjFaaFvXy0cV42o6X-Vv1Q,240
|
|
|
3618
3618
|
esphome/core/gpio.h,sha256=kLkCnPxu4_1CsLR4BI_Baj1lDGoRIh8uubbwsIkJPIA,2575
|
|
3619
3619
|
esphome/core/hal.h,sha256=Le0-vtdDylYCaE9i4yvrv5-Y5PB5xoL3PM2FfMJsIeA,970
|
|
3620
3620
|
esphome/core/helpers.cpp,sha256=eyOYJWmMEcdX8dJ3RoIcl6MeOmc0C3cTPafZDTzQ4OM,20961
|
|
3621
|
-
esphome/core/helpers.h,sha256=
|
|
3621
|
+
esphome/core/helpers.h,sha256=TX-xJuk8__wi4mGJPjNr8B9JngJMRju8MmAVhfg6xn0,34129
|
|
3622
3622
|
esphome/core/lock_free_queue.h,sha256=j3wSEyxqkjBDnCwEQd4ARHDubjSrLPxMAzZvqdNN2co,4953
|
|
3623
3623
|
esphome/core/log.cpp,sha256=cc6JIMRlIEk7lCQa6JFrL6bTBZ89xWNLwf26AFNzKC0,1625
|
|
3624
3624
|
esphome/core/log.h,sha256=Fb0_ORK0q-WV0i49gzb8i9_C38RUe8VILIdbu1Bel5M,6627
|
|
@@ -3655,9 +3655,9 @@ esphome/dashboard/util/itertools.py,sha256=8eLrWEWmICLtXNxkKdYPQV0c_N4GEz8m9Npnb
|
|
|
3655
3655
|
esphome/dashboard/util/password.py,sha256=cQz3b9B-ijTe7zS6BeCW0hc3pWv6JjC78jmnycYYAh8,321
|
|
3656
3656
|
esphome/dashboard/util/subprocess.py,sha256=T8EW6dbU4LPd2DG1dRrdh8li71tt6J1isn411poMhkk,1022
|
|
3657
3657
|
esphome/dashboard/util/text.py,sha256=wwFtORlvHjsYkqb68IT-772LHAhWxT4OtnkIcPICQB0,317
|
|
3658
|
-
esphome-2025.7.
|
|
3659
|
-
esphome-2025.7.
|
|
3660
|
-
esphome-2025.7.
|
|
3661
|
-
esphome-2025.7.
|
|
3662
|
-
esphome-2025.7.
|
|
3663
|
-
esphome-2025.7.
|
|
3658
|
+
esphome-2025.7.4.dist-info/licenses/LICENSE,sha256=HzEjkBInJe44L4WvAOPfhPJJDNj6YbnqFyvGWRzArGM,36664
|
|
3659
|
+
esphome-2025.7.4.dist-info/METADATA,sha256=Dlcq3C2cnO1s5Q9H8HB11OWErxRCjoN-MSri4PJV9TI,3705
|
|
3660
|
+
esphome-2025.7.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
3661
|
+
esphome-2025.7.4.dist-info/entry_points.txt,sha256=mIxVNuWtbYzeEcaWCl-AQ-97aBOWbnYBAK8nbF6P4M0,50
|
|
3662
|
+
esphome-2025.7.4.dist-info/top_level.txt,sha256=0GSXEW3cnITpgG3qnsSMz0qoqJHAFyfw7Y8MVtEf1Yk,8
|
|
3663
|
+
esphome-2025.7.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|