esphome 2025.5.0b2__py3-none-any.whl → 2025.5.0b3__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.
- esphome/__main__.py +16 -14
- esphome/components/api/api_connection.cpp +4 -3
- esphome/components/api/api_connection.h +8 -1
- esphome/components/api/api_frame_helper.cpp +136 -49
- esphome/components/api/api_frame_helper.h +49 -6
- esphome/components/api/proto.h +48 -8
- esphome/components/ballu/climate.py +1 -1
- esphome/components/bedjet/bedjet_hub.cpp +1 -0
- esphome/components/binary_sensor/binary_sensor.cpp +10 -6
- esphome/components/binary_sensor/binary_sensor.h +1 -1
- esphome/components/binary_sensor/filter.cpp +21 -21
- esphome/components/binary_sensor/filter.h +10 -10
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +2 -1
- esphome/components/ccs811/sensor.py +9 -6
- esphome/components/climate_ir/__init__.py +3 -3
- esphome/components/climate_ir_lg/climate.py +1 -1
- esphome/components/coolix/climate.py +1 -1
- esphome/components/cse7766/cse7766.cpp +2 -1
- esphome/components/current_based/current_based_cover.cpp +2 -1
- esphome/components/daikin/climate.py +1 -1
- esphome/components/daikin_arc/climate.py +1 -1
- esphome/components/daikin_brc/climate.py +1 -1
- esphome/components/daly_bms/daly_bms.cpp +2 -1
- esphome/components/debug/debug_component.cpp +1 -1
- esphome/components/delonghi/climate.py +1 -1
- esphome/components/dps310/sensor.py +6 -6
- esphome/components/ee895/sensor.py +9 -9
- esphome/components/emmeti/climate.py +1 -1
- esphome/components/endstop/endstop_cover.cpp +2 -1
- esphome/components/ens160_base/__init__.py +12 -9
- esphome/components/esp32_ble/ble_advertising.cpp +2 -1
- esphome/components/esp32_camera/esp32_camera.cpp +2 -1
- esphome/components/esp32_camera/esp32_camera.h +1 -1
- esphome/components/esp32_improv/esp32_improv_component.cpp +1 -1
- esphome/components/esp32_touch/esp32_touch.cpp +1 -1
- esphome/components/ethernet/ethernet_component.cpp +1 -1
- esphome/components/feedback/feedback_cover.cpp +2 -1
- esphome/components/fujitsu_general/climate.py +1 -1
- esphome/components/gcja5/gcja5.cpp +2 -1
- esphome/components/gps/__init__.py +37 -16
- esphome/components/gps/gps.cpp +33 -17
- esphome/components/gps/gps.h +16 -15
- esphome/components/gree/climate.py +1 -1
- esphome/components/growatt_solar/growatt_solar.cpp +2 -1
- esphome/components/heatpumpir/climate.py +1 -1
- esphome/components/hitachi_ac344/climate.py +1 -1
- esphome/components/hitachi_ac424/climate.py +1 -1
- esphome/components/hte501/sensor.py +6 -6
- esphome/components/hyt271/sensor.py +6 -6
- esphome/components/kuntze/kuntze.cpp +2 -1
- esphome/components/logger/__init__.py +1 -0
- esphome/components/logger/logger.cpp +53 -32
- esphome/components/logger/logger.h +55 -5
- esphome/components/matrix_keypad/matrix_keypad.cpp +2 -1
- esphome/components/max7219digit/max7219digit.cpp +2 -1
- esphome/components/mhz19/sensor.py +11 -7
- esphome/components/midea_ir/climate.py +1 -1
- esphome/components/mitsubishi/climate.py +1 -1
- esphome/components/modbus/modbus.cpp +2 -1
- esphome/components/mqtt/mqtt_client.cpp +1 -1
- esphome/components/ms5611/sensor.py +6 -6
- esphome/components/ms8607/sensor.py +3 -3
- esphome/components/noblex/climate.py +1 -1
- esphome/components/pmsx003/pmsx003.cpp +2 -1
- esphome/components/pzem004t/pzem004t.cpp +2 -1
- esphome/components/rf_bridge/rf_bridge.cpp +2 -1
- esphome/components/sds011/sds011.cpp +2 -1
- esphome/components/sen5x/sen5x.cpp +55 -36
- esphome/components/senseair/sensor.py +3 -3
- esphome/components/sgp30/sensor.py +14 -16
- esphome/components/shtcx/sensor.py +6 -6
- esphome/components/slow_pwm/slow_pwm_output.cpp +2 -1
- esphome/components/sprinkler/sprinkler.cpp +6 -5
- esphome/components/t6615/sensor.py +3 -3
- esphome/components/t6615/t6615.cpp +2 -1
- esphome/components/tcl112/climate.py +1 -1
- esphome/components/time_based/time_based_cover.cpp +2 -1
- esphome/components/toshiba/climate.py +1 -1
- esphome/components/uart/switch/uart_switch.cpp +2 -1
- esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +2 -1
- esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
- esphome/components/whirlpool/climate.py +1 -1
- esphome/components/whynter/climate.py +1 -1
- esphome/components/zhlt01/climate.py +1 -1
- esphome/config.py +13 -13
- esphome/const.py +1 -1
- esphome/core/application.cpp +22 -10
- esphome/core/application.h +5 -1
- esphome/core/component.cpp +10 -5
- esphome/core/component.h +5 -1
- esphome/core/scheduler.cpp +4 -1
- esphome/log.py +15 -19
- esphome/mqtt.py +2 -2
- esphome/voluptuous_schema.py +3 -1
- esphome/wizard.py +45 -35
- {esphome-2025.5.0b2.dist-info → esphome-2025.5.0b3.dist-info}/METADATA +1 -1
- {esphome-2025.5.0b2.dist-info → esphome-2025.5.0b3.dist-info}/RECORD +101 -101
- {esphome-2025.5.0b2.dist-info → esphome-2025.5.0b3.dist-info}/WHEEL +0 -0
- {esphome-2025.5.0b2.dist-info → esphome-2025.5.0b3.dist-info}/entry_points.txt +0 -0
- {esphome-2025.5.0b2.dist-info → esphome-2025.5.0b3.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.5.0b2.dist-info → esphome-2025.5.0b3.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
|
|
1
1
|
#include "feedback_cover.h"
|
2
2
|
#include "esphome/core/hal.h"
|
3
3
|
#include "esphome/core/log.h"
|
4
|
+
#include "esphome/core/application.h"
|
4
5
|
|
5
6
|
namespace esphome {
|
6
7
|
namespace feedback {
|
@@ -220,7 +221,7 @@ void FeedbackCover::set_open_obstacle_sensor(binary_sensor::BinarySensor *open_o
|
|
220
221
|
void FeedbackCover::loop() {
|
221
222
|
if (this->current_operation == COVER_OPERATION_IDLE)
|
222
223
|
return;
|
223
|
-
const uint32_t now =
|
224
|
+
const uint32_t now = App.get_loop_component_start_time();
|
224
225
|
|
225
226
|
// Recompute position every loop cycle
|
226
227
|
this->recompute_position_();
|
@@ -8,7 +8,7 @@ FujitsuGeneralClimate = fujitsu_general_ns.class_(
|
|
8
8
|
"FujitsuGeneralClimate", climate_ir.ClimateIR
|
9
9
|
)
|
10
10
|
|
11
|
-
CONFIG_SCHEMA = climate_ir.
|
11
|
+
CONFIG_SCHEMA = climate_ir.climate_ir_with_receiver_schema(FujitsuGeneralClimate)
|
12
12
|
|
13
13
|
|
14
14
|
async def to_code(config):
|
@@ -6,6 +6,7 @@
|
|
6
6
|
*/
|
7
7
|
#include "gcja5.h"
|
8
8
|
#include "esphome/core/log.h"
|
9
|
+
#include "esphome/core/application.h"
|
9
10
|
#include <cstring>
|
10
11
|
|
11
12
|
namespace esphome {
|
@@ -16,7 +17,7 @@ static const char *const TAG = "gcja5";
|
|
16
17
|
void GCJA5Component::setup() { ESP_LOGCONFIG(TAG, "Setting up gcja5..."); }
|
17
18
|
|
18
19
|
void GCJA5Component::loop() {
|
19
|
-
const uint32_t now =
|
20
|
+
const uint32_t now = App.get_loop_component_start_time();
|
20
21
|
if (now - this->last_transmission_ >= 500) {
|
21
22
|
// last transmission too long ago. Reset RX index.
|
22
23
|
this->rx_message_.clear();
|
@@ -9,23 +9,32 @@ from esphome.const import (
|
|
9
9
|
CONF_LONGITUDE,
|
10
10
|
CONF_SATELLITES,
|
11
11
|
CONF_SPEED,
|
12
|
+
DEVICE_CLASS_SPEED,
|
12
13
|
STATE_CLASS_MEASUREMENT,
|
13
14
|
UNIT_DEGREES,
|
14
15
|
UNIT_KILOMETER_PER_HOUR,
|
15
16
|
UNIT_METER,
|
16
17
|
)
|
17
18
|
|
19
|
+
CONF_GPS_ID = "gps_id"
|
20
|
+
CONF_HDOP = "hdop"
|
21
|
+
|
22
|
+
ICON_ALTIMETER = "mdi:altimeter"
|
23
|
+
ICON_COMPASS = "mdi:compass"
|
24
|
+
ICON_LATITUDE = "mdi:latitude"
|
25
|
+
ICON_LONGITUDE = "mdi:longitude"
|
26
|
+
ICON_SATELLITE = "mdi:satellite-variant"
|
27
|
+
ICON_SPEEDOMETER = "mdi:speedometer"
|
28
|
+
|
18
29
|
DEPENDENCIES = ["uart"]
|
19
30
|
AUTO_LOAD = ["sensor"]
|
20
31
|
|
21
|
-
CODEOWNERS = ["@coogle"]
|
32
|
+
CODEOWNERS = ["@coogle", "@ximex"]
|
22
33
|
|
23
34
|
gps_ns = cg.esphome_ns.namespace("gps")
|
24
35
|
GPS = gps_ns.class_("GPS", cg.Component, uart.UARTDevice)
|
25
36
|
GPSListener = gps_ns.class_("GPSListener")
|
26
37
|
|
27
|
-
CONF_GPS_ID = "gps_id"
|
28
|
-
CONF_HDOP = "hdop"
|
29
38
|
MULTI_CONF = True
|
30
39
|
CONFIG_SCHEMA = cv.All(
|
31
40
|
cv.Schema(
|
@@ -33,25 +42,37 @@ CONFIG_SCHEMA = cv.All(
|
|
33
42
|
cv.GenerateID(): cv.declare_id(GPS),
|
34
43
|
cv.Optional(CONF_LATITUDE): sensor.sensor_schema(
|
35
44
|
unit_of_measurement=UNIT_DEGREES,
|
45
|
+
icon=ICON_LATITUDE,
|
36
46
|
accuracy_decimals=6,
|
47
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
37
48
|
),
|
38
49
|
cv.Optional(CONF_LONGITUDE): sensor.sensor_schema(
|
39
50
|
unit_of_measurement=UNIT_DEGREES,
|
51
|
+
icon=ICON_LONGITUDE,
|
40
52
|
accuracy_decimals=6,
|
53
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
41
54
|
),
|
42
55
|
cv.Optional(CONF_SPEED): sensor.sensor_schema(
|
43
56
|
unit_of_measurement=UNIT_KILOMETER_PER_HOUR,
|
57
|
+
icon=ICON_SPEEDOMETER,
|
44
58
|
accuracy_decimals=3,
|
59
|
+
device_class=DEVICE_CLASS_SPEED,
|
60
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
45
61
|
),
|
46
62
|
cv.Optional(CONF_COURSE): sensor.sensor_schema(
|
47
63
|
unit_of_measurement=UNIT_DEGREES,
|
64
|
+
icon=ICON_COMPASS,
|
48
65
|
accuracy_decimals=2,
|
66
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
49
67
|
),
|
50
68
|
cv.Optional(CONF_ALTITUDE): sensor.sensor_schema(
|
51
69
|
unit_of_measurement=UNIT_METER,
|
70
|
+
icon=ICON_ALTIMETER,
|
52
71
|
accuracy_decimals=2,
|
72
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
53
73
|
),
|
54
74
|
cv.Optional(CONF_SATELLITES): sensor.sensor_schema(
|
75
|
+
icon=ICON_SATELLITE,
|
55
76
|
accuracy_decimals=0,
|
56
77
|
state_class=STATE_CLASS_MEASUREMENT,
|
57
78
|
),
|
@@ -73,28 +94,28 @@ async def to_code(config):
|
|
73
94
|
await cg.register_component(var, config)
|
74
95
|
await uart.register_uart_device(var, config)
|
75
96
|
|
76
|
-
if
|
77
|
-
sens = await sensor.new_sensor(
|
97
|
+
if latitude_config := config.get(CONF_LATITUDE):
|
98
|
+
sens = await sensor.new_sensor(latitude_config)
|
78
99
|
cg.add(var.set_latitude_sensor(sens))
|
79
100
|
|
80
|
-
if
|
81
|
-
sens = await sensor.new_sensor(
|
101
|
+
if longitude_config := config.get(CONF_LONGITUDE):
|
102
|
+
sens = await sensor.new_sensor(longitude_config)
|
82
103
|
cg.add(var.set_longitude_sensor(sens))
|
83
104
|
|
84
|
-
if
|
85
|
-
sens = await sensor.new_sensor(
|
105
|
+
if speed_config := config.get(CONF_SPEED):
|
106
|
+
sens = await sensor.new_sensor(speed_config)
|
86
107
|
cg.add(var.set_speed_sensor(sens))
|
87
108
|
|
88
|
-
if
|
89
|
-
sens = await sensor.new_sensor(
|
109
|
+
if course_config := config.get(CONF_COURSE):
|
110
|
+
sens = await sensor.new_sensor(course_config)
|
90
111
|
cg.add(var.set_course_sensor(sens))
|
91
112
|
|
92
|
-
if
|
93
|
-
sens = await sensor.new_sensor(
|
113
|
+
if altitude_config := config.get(CONF_ALTITUDE):
|
114
|
+
sens = await sensor.new_sensor(altitude_config)
|
94
115
|
cg.add(var.set_altitude_sensor(sens))
|
95
116
|
|
96
|
-
if
|
97
|
-
sens = await sensor.new_sensor(
|
117
|
+
if satellites_config := config.get(CONF_SATELLITES):
|
118
|
+
sens = await sensor.new_sensor(satellites_config)
|
98
119
|
cg.add(var.set_satellites_sensor(sens))
|
99
120
|
|
100
121
|
if hdop_config := config.get(CONF_HDOP):
|
@@ -102,4 +123,4 @@ async def to_code(config):
|
|
102
123
|
cg.add(var.set_hdop_sensor(sens))
|
103
124
|
|
104
125
|
# https://platformio.org/lib/show/1655/TinyGPSPlus
|
105
|
-
cg.add_library("mikalhart/TinyGPSPlus", "1.0
|
126
|
+
cg.add_library("mikalhart/TinyGPSPlus", "1.1.0")
|
esphome/components/gps/gps.cpp
CHANGED
@@ -10,6 +10,17 @@ static const char *const TAG = "gps";
|
|
10
10
|
|
11
11
|
TinyGPSPlus &GPSListener::get_tiny_gps() { return this->parent_->get_tiny_gps(); }
|
12
12
|
|
13
|
+
void GPS::dump_config() {
|
14
|
+
ESP_LOGCONFIG(TAG, "GPS:");
|
15
|
+
LOG_SENSOR(" ", "Latitude", this->latitude_sensor_);
|
16
|
+
LOG_SENSOR(" ", "Longitude", this->longitude_sensor_);
|
17
|
+
LOG_SENSOR(" ", "Speed", this->speed_sensor_);
|
18
|
+
LOG_SENSOR(" ", "Course", this->course_sensor_);
|
19
|
+
LOG_SENSOR(" ", "Altitude", this->altitude_sensor_);
|
20
|
+
LOG_SENSOR(" ", "Satellites", this->satellites_sensor_);
|
21
|
+
LOG_SENSOR(" ", "HDOP", this->hdop_sensor_);
|
22
|
+
}
|
23
|
+
|
13
24
|
void GPS::update() {
|
14
25
|
if (this->latitude_sensor_ != nullptr)
|
15
26
|
this->latitude_sensor_->publish_state(this->latitude_);
|
@@ -34,40 +45,45 @@ void GPS::update() {
|
|
34
45
|
}
|
35
46
|
|
36
47
|
void GPS::loop() {
|
37
|
-
while (this->available() && !this->has_time_) {
|
48
|
+
while (this->available() > 0 && !this->has_time_) {
|
38
49
|
if (this->tiny_gps_.encode(this->read())) {
|
39
|
-
if (tiny_gps_.location.isUpdated()) {
|
40
|
-
this->latitude_ = tiny_gps_.location.lat();
|
41
|
-
this->longitude_ = tiny_gps_.location.lng();
|
50
|
+
if (this->tiny_gps_.location.isUpdated()) {
|
51
|
+
this->latitude_ = this->tiny_gps_.location.lat();
|
52
|
+
this->longitude_ = this->tiny_gps_.location.lng();
|
42
53
|
|
43
54
|
ESP_LOGD(TAG, "Location:");
|
44
|
-
ESP_LOGD(TAG, " Lat:
|
45
|
-
ESP_LOGD(TAG, " Lon:
|
55
|
+
ESP_LOGD(TAG, " Lat: %.6f °", this->latitude_);
|
56
|
+
ESP_LOGD(TAG, " Lon: %.6f °", this->longitude_);
|
46
57
|
}
|
47
58
|
|
48
|
-
if (tiny_gps_.speed.isUpdated()) {
|
49
|
-
this->speed_ = tiny_gps_.speed.kmph();
|
59
|
+
if (this->tiny_gps_.speed.isUpdated()) {
|
60
|
+
this->speed_ = this->tiny_gps_.speed.kmph();
|
50
61
|
ESP_LOGD(TAG, "Speed: %.3f km/h", this->speed_);
|
51
62
|
}
|
52
|
-
|
53
|
-
|
63
|
+
|
64
|
+
if (this->tiny_gps_.course.isUpdated()) {
|
65
|
+
this->course_ = this->tiny_gps_.course.deg();
|
54
66
|
ESP_LOGD(TAG, "Course: %.2f °", this->course_);
|
55
67
|
}
|
56
|
-
|
57
|
-
|
68
|
+
|
69
|
+
if (this->tiny_gps_.altitude.isUpdated()) {
|
70
|
+
this->altitude_ = this->tiny_gps_.altitude.meters();
|
58
71
|
ESP_LOGD(TAG, "Altitude: %.2f m", this->altitude_);
|
59
72
|
}
|
60
|
-
|
61
|
-
|
73
|
+
|
74
|
+
if (this->tiny_gps_.satellites.isUpdated()) {
|
75
|
+
this->satellites_ = this->tiny_gps_.satellites.value();
|
62
76
|
ESP_LOGD(TAG, "Satellites: %d", this->satellites_);
|
63
77
|
}
|
64
|
-
|
65
|
-
|
78
|
+
|
79
|
+
if (this->tiny_gps_.hdop.isUpdated()) {
|
80
|
+
this->hdop_ = this->tiny_gps_.hdop.hdop();
|
66
81
|
ESP_LOGD(TAG, "HDOP: %.3f", this->hdop_);
|
67
82
|
}
|
68
83
|
|
69
|
-
for (auto *listener : this->listeners_)
|
84
|
+
for (auto *listener : this->listeners_) {
|
70
85
|
listener->on_update(this->tiny_gps_);
|
86
|
+
}
|
71
87
|
}
|
72
88
|
}
|
73
89
|
}
|
esphome/components/gps/gps.h
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
#include "esphome/core/component.h"
|
6
6
|
#include "esphome/components/uart/uart.h"
|
7
7
|
#include "esphome/components/sensor/sensor.h"
|
8
|
-
#include <
|
8
|
+
#include <TinyGPSPlus.h>
|
9
9
|
|
10
10
|
#include <vector>
|
11
11
|
|
@@ -27,13 +27,13 @@ class GPSListener {
|
|
27
27
|
|
28
28
|
class GPS : public PollingComponent, public uart::UARTDevice {
|
29
29
|
public:
|
30
|
-
void set_latitude_sensor(sensor::Sensor *latitude_sensor) { latitude_sensor_ = latitude_sensor; }
|
31
|
-
void set_longitude_sensor(sensor::Sensor *longitude_sensor) { longitude_sensor_ = longitude_sensor; }
|
32
|
-
void set_speed_sensor(sensor::Sensor *speed_sensor) { speed_sensor_ = speed_sensor; }
|
33
|
-
void set_course_sensor(sensor::Sensor *course_sensor) { course_sensor_ = course_sensor; }
|
34
|
-
void set_altitude_sensor(sensor::Sensor *altitude_sensor) { altitude_sensor_ = altitude_sensor; }
|
35
|
-
void set_satellites_sensor(sensor::Sensor *satellites_sensor) { satellites_sensor_ = satellites_sensor; }
|
36
|
-
void set_hdop_sensor(sensor::Sensor *hdop_sensor) { hdop_sensor_ = hdop_sensor; }
|
30
|
+
void set_latitude_sensor(sensor::Sensor *latitude_sensor) { this->latitude_sensor_ = latitude_sensor; }
|
31
|
+
void set_longitude_sensor(sensor::Sensor *longitude_sensor) { this->longitude_sensor_ = longitude_sensor; }
|
32
|
+
void set_speed_sensor(sensor::Sensor *speed_sensor) { this->speed_sensor_ = speed_sensor; }
|
33
|
+
void set_course_sensor(sensor::Sensor *course_sensor) { this->course_sensor_ = course_sensor; }
|
34
|
+
void set_altitude_sensor(sensor::Sensor *altitude_sensor) { this->altitude_sensor_ = altitude_sensor; }
|
35
|
+
void set_satellites_sensor(sensor::Sensor *satellites_sensor) { this->satellites_sensor_ = satellites_sensor; }
|
36
|
+
void set_hdop_sensor(sensor::Sensor *hdop_sensor) { this->hdop_sensor_ = hdop_sensor; }
|
37
37
|
|
38
38
|
void register_listener(GPSListener *listener) {
|
39
39
|
listener->parent_ = this;
|
@@ -41,19 +41,20 @@ class GPS : public PollingComponent, public uart::UARTDevice {
|
|
41
41
|
}
|
42
42
|
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
43
43
|
|
44
|
+
void dump_config() override;
|
44
45
|
void loop() override;
|
45
46
|
void update() override;
|
46
47
|
|
47
48
|
TinyGPSPlus &get_tiny_gps() { return this->tiny_gps_; }
|
48
49
|
|
49
50
|
protected:
|
50
|
-
float latitude_
|
51
|
-
float longitude_
|
52
|
-
float speed_
|
53
|
-
float course_
|
54
|
-
float altitude_
|
55
|
-
|
56
|
-
|
51
|
+
float latitude_{NAN};
|
52
|
+
float longitude_{NAN};
|
53
|
+
float speed_{NAN};
|
54
|
+
float course_{NAN};
|
55
|
+
float altitude_{NAN};
|
56
|
+
uint16_t satellites_{0};
|
57
|
+
float hdop_{NAN};
|
57
58
|
|
58
59
|
sensor::Sensor *latitude_sensor_{nullptr};
|
59
60
|
sensor::Sensor *longitude_sensor_{nullptr};
|
@@ -21,7 +21,7 @@ MODELS = {
|
|
21
21
|
"yag": Model.GREE_YAG,
|
22
22
|
}
|
23
23
|
|
24
|
-
CONFIG_SCHEMA = climate_ir.
|
24
|
+
CONFIG_SCHEMA = climate_ir.climate_ir_with_receiver_schema(GreeClimate).extend(
|
25
25
|
{
|
26
26
|
cv.Required(CONF_MODEL): cv.enum(MODELS),
|
27
27
|
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
#include "growatt_solar.h"
|
2
2
|
#include "esphome/core/log.h"
|
3
|
+
#include "esphome/core/application.h"
|
3
4
|
|
4
5
|
namespace esphome {
|
5
6
|
namespace growatt_solar {
|
@@ -18,7 +19,7 @@ void GrowattSolar::loop() {
|
|
18
19
|
|
19
20
|
void GrowattSolar::update() {
|
20
21
|
// If our last send has had no reply yet, and it wasn't that long ago, do nothing.
|
21
|
-
uint32_t now =
|
22
|
+
const uint32_t now = App.get_loop_component_start_time();
|
22
23
|
if (now - this->last_send_ < this->get_update_interval() / 2) {
|
23
24
|
return;
|
24
25
|
}
|
@@ -97,7 +97,7 @@ VERTICAL_DIRECTIONS = {
|
|
97
97
|
}
|
98
98
|
|
99
99
|
CONFIG_SCHEMA = cv.All(
|
100
|
-
climate_ir.
|
100
|
+
climate_ir.climate_ir_with_receiver_schema(HeatpumpIRClimate).extend(
|
101
101
|
{
|
102
102
|
cv.Required(CONF_PROTOCOL): cv.enum(PROTOCOLS),
|
103
103
|
cv.Required(CONF_HORIZONTAL_DEFAULT): cv.enum(HORIZONTAL_DIRECTIONS),
|
@@ -6,7 +6,7 @@ AUTO_LOAD = ["climate_ir"]
|
|
6
6
|
hitachi_ac344_ns = cg.esphome_ns.namespace("hitachi_ac344")
|
7
7
|
HitachiClimate = hitachi_ac344_ns.class_("HitachiClimate", climate_ir.ClimateIR)
|
8
8
|
|
9
|
-
CONFIG_SCHEMA = climate_ir.
|
9
|
+
CONFIG_SCHEMA = climate_ir.climate_ir_with_receiver_schema(HitachiClimate)
|
10
10
|
|
11
11
|
|
12
12
|
async def to_code(config):
|
@@ -6,7 +6,7 @@ AUTO_LOAD = ["climate_ir"]
|
|
6
6
|
hitachi_ac424_ns = cg.esphome_ns.namespace("hitachi_ac424")
|
7
7
|
HitachiClimate = hitachi_ac424_ns.class_("HitachiClimate", climate_ir.ClimateIR)
|
8
8
|
|
9
|
-
CONFIG_SCHEMA = climate_ir.
|
9
|
+
CONFIG_SCHEMA = climate_ir.climate_ir_with_receiver_schema(HitachiClimate)
|
10
10
|
|
11
11
|
|
12
12
|
async def to_code(config):
|
@@ -25,13 +25,13 @@ CONFIG_SCHEMA = (
|
|
25
25
|
cv.Schema(
|
26
26
|
{
|
27
27
|
cv.GenerateID(): cv.declare_id(HTE501Component),
|
28
|
-
cv.
|
28
|
+
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
29
29
|
unit_of_measurement=UNIT_CELSIUS,
|
30
30
|
accuracy_decimals=1,
|
31
31
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
32
32
|
state_class=STATE_CLASS_MEASUREMENT,
|
33
33
|
),
|
34
|
-
cv.
|
34
|
+
cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
|
35
35
|
unit_of_measurement=UNIT_PERCENT,
|
36
36
|
accuracy_decimals=1,
|
37
37
|
device_class=DEVICE_CLASS_HUMIDITY,
|
@@ -49,10 +49,10 @@ async def to_code(config):
|
|
49
49
|
await cg.register_component(var, config)
|
50
50
|
await i2c.register_i2c_device(var, config)
|
51
51
|
|
52
|
-
if
|
53
|
-
sens = await sensor.new_sensor(
|
52
|
+
if temperature := config.get(CONF_TEMPERATURE):
|
53
|
+
sens = await sensor.new_sensor(temperature)
|
54
54
|
cg.add(var.set_temperature_sensor(sens))
|
55
55
|
|
56
|
-
if
|
57
|
-
sens = await sensor.new_sensor(
|
56
|
+
if humidity := config.get(CONF_HUMIDITY):
|
57
|
+
sens = await sensor.new_sensor(humidity)
|
58
58
|
cg.add(var.set_humidity_sensor(sens))
|
@@ -23,13 +23,13 @@ CONFIG_SCHEMA = (
|
|
23
23
|
cv.Schema(
|
24
24
|
{
|
25
25
|
cv.GenerateID(): cv.declare_id(HYT271Component),
|
26
|
-
cv.
|
26
|
+
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
27
27
|
unit_of_measurement=UNIT_CELSIUS,
|
28
28
|
accuracy_decimals=1,
|
29
29
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
30
30
|
state_class=STATE_CLASS_MEASUREMENT,
|
31
31
|
),
|
32
|
-
cv.
|
32
|
+
cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
|
33
33
|
unit_of_measurement=UNIT_PERCENT,
|
34
34
|
accuracy_decimals=1,
|
35
35
|
device_class=DEVICE_CLASS_HUMIDITY,
|
@@ -47,10 +47,10 @@ async def to_code(config):
|
|
47
47
|
await cg.register_component(var, config)
|
48
48
|
await i2c.register_i2c_device(var, config)
|
49
49
|
|
50
|
-
if
|
51
|
-
sens = await sensor.new_sensor(
|
50
|
+
if temperature := config.get(CONF_TEMPERATURE):
|
51
|
+
sens = await sensor.new_sensor(temperature)
|
52
52
|
cg.add(var.set_temperature(sens))
|
53
53
|
|
54
|
-
if
|
55
|
-
sens = await sensor.new_sensor(
|
54
|
+
if humidity := config.get(CONF_HUMIDITY):
|
55
|
+
sens = await sensor.new_sensor(humidity)
|
56
56
|
cg.add(var.set_humidity(sens))
|
@@ -1,5 +1,6 @@
|
|
1
1
|
#include "kuntze.h"
|
2
2
|
#include "esphome/core/log.h"
|
3
|
+
#include "esphome/core/application.h"
|
3
4
|
|
4
5
|
namespace esphome {
|
5
6
|
namespace kuntze {
|
@@ -60,7 +61,7 @@ void Kuntze::on_modbus_data(const std::vector<uint8_t> &data) {
|
|
60
61
|
}
|
61
62
|
|
62
63
|
void Kuntze::loop() {
|
63
|
-
uint32_t now =
|
64
|
+
uint32_t now = App.get_loop_component_start_time();
|
64
65
|
// timeout after 15 seconds
|
65
66
|
if (this->waiting_ && (now - this->last_send_ > 15000)) {
|
66
67
|
ESP_LOGW(TAG, "timed out waiting for response");
|
@@ -254,6 +254,7 @@ async def to_code(config):
|
|
254
254
|
config[CONF_TX_BUFFER_SIZE],
|
255
255
|
)
|
256
256
|
if CORE.is_esp32:
|
257
|
+
cg.add(log.create_pthread_key())
|
257
258
|
task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE]
|
258
259
|
if task_log_buffer_size > 0:
|
259
260
|
cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER")
|
@@ -14,25 +14,47 @@ namespace logger {
|
|
14
14
|
static const char *const TAG = "logger";
|
15
15
|
|
16
16
|
#ifdef USE_ESP32
|
17
|
-
// Implementation for ESP32 (multi-
|
18
|
-
// Main
|
19
|
-
//
|
17
|
+
// Implementation for ESP32 (multi-task platform with task-specific tracking)
|
18
|
+
// Main task always uses direct buffer access for console output and callbacks
|
19
|
+
//
|
20
|
+
// For non-main tasks:
|
21
|
+
// - WITH task log buffer: Prefer sending to ring buffer for async processing
|
22
|
+
// - Avoids allocating stack memory for console output in normal operation
|
23
|
+
// - Prevents console corruption from concurrent writes by multiple tasks
|
24
|
+
// - Messages are serialized through main loop for proper console output
|
25
|
+
// - Fallback to emergency console logging only if ring buffer is full
|
26
|
+
// - WITHOUT task log buffer: Only emergency console output, no callbacks
|
20
27
|
void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *format, va_list args) { // NOLINT
|
21
|
-
if (level > this->level_for(tag)
|
28
|
+
if (level > this->level_for(tag))
|
22
29
|
return;
|
23
|
-
recursion_guard_.store(true, std::memory_order_relaxed);
|
24
30
|
|
25
31
|
TaskHandle_t current_task = xTaskGetCurrentTaskHandle();
|
32
|
+
bool is_main_task = (current_task == main_task_);
|
26
33
|
|
27
|
-
//
|
28
|
-
if (
|
34
|
+
// Check and set recursion guard - uses pthread TLS for per-task state
|
35
|
+
if (this->check_and_set_task_log_recursion_(is_main_task)) {
|
36
|
+
return; // Recursion detected
|
37
|
+
}
|
38
|
+
|
39
|
+
// Main task uses the shared buffer for efficiency
|
40
|
+
if (is_main_task) {
|
29
41
|
this->log_message_to_buffer_and_send_(level, tag, line, format, args);
|
30
|
-
|
42
|
+
this->reset_task_log_recursion_(is_main_task);
|
31
43
|
return;
|
32
44
|
}
|
33
45
|
|
34
|
-
|
35
|
-
|
46
|
+
bool message_sent = false;
|
47
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
48
|
+
// For non-main tasks, queue the message for callbacks - but only if we have any callbacks registered
|
49
|
+
message_sent = this->log_buffer_->send_message_thread_safe(static_cast<uint8_t>(level), tag,
|
50
|
+
static_cast<uint16_t>(line), current_task, format, args);
|
51
|
+
#endif // USE_ESPHOME_TASK_LOG_BUFFER
|
52
|
+
|
53
|
+
// Emergency console logging for non-main tasks when ring buffer is full or disabled
|
54
|
+
// This is a fallback mechanism to ensure critical log messages are visible
|
55
|
+
// Note: This may cause interleaved/corrupted console output if multiple tasks
|
56
|
+
// log simultaneously, but it's better than losing important messages entirely
|
57
|
+
if (!message_sent && this->baud_rate_ > 0) { // If logging is enabled, write to console
|
36
58
|
// Maximum size for console log messages (includes null terminator)
|
37
59
|
static const size_t MAX_CONSOLE_LOG_MSG_SIZE = 144;
|
38
60
|
char console_buffer[MAX_CONSOLE_LOG_MSG_SIZE]; // MUST be stack allocated for thread safety
|
@@ -42,32 +64,21 @@ void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *
|
|
42
64
|
this->write_msg_(console_buffer);
|
43
65
|
}
|
44
66
|
|
45
|
-
|
46
|
-
|
47
|
-
if (this->log_callback_.size() > 0) {
|
48
|
-
// This will be processed in the main loop
|
49
|
-
this->log_buffer_->send_message_thread_safe(static_cast<uint8_t>(level), tag, static_cast<uint16_t>(line),
|
50
|
-
current_task, format, args);
|
51
|
-
}
|
52
|
-
#endif // USE_ESPHOME_TASK_LOG_BUFFER
|
53
|
-
|
54
|
-
recursion_guard_.store(false, std::memory_order_release);
|
67
|
+
// Reset the recursion guard for this task
|
68
|
+
this->reset_task_log_recursion_(is_main_task);
|
55
69
|
}
|
56
|
-
#
|
57
|
-
|
58
|
-
#ifndef USE_ESP32
|
59
|
-
// Implementation for platforms that do not support atomic operations
|
60
|
-
// or have to consider logging in other tasks
|
70
|
+
#else
|
71
|
+
// Implementation for all other platforms
|
61
72
|
void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *format, va_list args) { // NOLINT
|
62
|
-
if (level > this->level_for(tag) ||
|
73
|
+
if (level > this->level_for(tag) || global_recursion_guard_)
|
63
74
|
return;
|
64
75
|
|
65
|
-
|
76
|
+
global_recursion_guard_ = true;
|
66
77
|
|
67
78
|
// Format and send to both console and callbacks
|
68
79
|
this->log_message_to_buffer_and_send_(level, tag, line, format, args);
|
69
80
|
|
70
|
-
|
81
|
+
global_recursion_guard_ = false;
|
71
82
|
}
|
72
83
|
#endif // !USE_ESP32
|
73
84
|
|
@@ -76,10 +87,10 @@ void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *
|
|
76
87
|
// Note: USE_STORE_LOG_STR_IN_FLASH is only defined for ESP8266.
|
77
88
|
void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStringHelper *format,
|
78
89
|
va_list args) { // NOLINT
|
79
|
-
if (level > this->level_for(tag) ||
|
90
|
+
if (level > this->level_for(tag) || global_recursion_guard_)
|
80
91
|
return;
|
81
92
|
|
82
|
-
|
93
|
+
global_recursion_guard_ = true;
|
83
94
|
this->tx_buffer_at_ = 0;
|
84
95
|
|
85
96
|
// Copy format string from progmem
|
@@ -91,7 +102,7 @@ void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStr
|
|
91
102
|
|
92
103
|
// Buffer full from copying format
|
93
104
|
if (this->tx_buffer_at_ >= this->tx_buffer_size_) {
|
94
|
-
|
105
|
+
global_recursion_guard_ = false; // Make sure to reset the recursion guard before returning
|
95
106
|
return;
|
96
107
|
}
|
97
108
|
|
@@ -107,7 +118,7 @@ void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStr
|
|
107
118
|
}
|
108
119
|
this->call_log_callbacks_(level, tag, this->tx_buffer_ + msg_start);
|
109
120
|
|
110
|
-
|
121
|
+
global_recursion_guard_ = false;
|
111
122
|
}
|
112
123
|
#endif // USE_STORE_LOG_STR_IN_FLASH
|
113
124
|
|
@@ -179,7 +190,17 @@ void Logger::loop() {
|
|
179
190
|
this->write_footer_to_buffer_(this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_);
|
180
191
|
this->tx_buffer_[this->tx_buffer_at_] = '\0';
|
181
192
|
this->call_log_callbacks_(message->level, message->tag, this->tx_buffer_);
|
193
|
+
// At this point all the data we need from message has been transferred to the tx_buffer
|
194
|
+
// so we can release the message to allow other tasks to use it as soon as possible.
|
182
195
|
this->log_buffer_->release_message_main_loop(received_token);
|
196
|
+
|
197
|
+
// Write to console from the main loop to prevent corruption from concurrent writes
|
198
|
+
// This ensures all log messages appear on the console in a clean, serialized manner
|
199
|
+
// Note: Messages may appear slightly out of order due to async processing, but
|
200
|
+
// this is preferred over corrupted/interleaved console output
|
201
|
+
if (this->baud_rate_ > 0) {
|
202
|
+
this->write_msg_(this->tx_buffer_);
|
203
|
+
}
|
183
204
|
}
|
184
205
|
}
|
185
206
|
#endif
|