esphome 2025.7.0b3__py3-none-any.whl → 2025.7.0b5__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/as3935_spi/as3935_spi.h +0 -2
- esphome/components/async_tcp/__init__.py +1 -1
- esphome/components/fan/fan.cpp +4 -0
- esphome/components/http_request/update/http_request_update.cpp +7 -7
- esphome/components/json/__init__.py +1 -1
- esphome/components/json/json_util.cpp +56 -63
- esphome/components/light/light_json_schema.cpp +17 -16
- esphome/components/mqtt/mqtt_alarm_control_panel.cpp +2 -1
- esphome/components/mqtt/mqtt_binary_sensor.cpp +1 -0
- esphome/components/mqtt/mqtt_button.cpp +4 -1
- esphome/components/mqtt/mqtt_client.cpp +2 -0
- esphome/components/mqtt/mqtt_climate.cpp +6 -4
- esphome/components/mqtt/mqtt_component.cpp +3 -1
- esphome/components/mqtt/mqtt_cover.cpp +1 -0
- esphome/components/mqtt/mqtt_date.cpp +4 -3
- esphome/components/mqtt/mqtt_datetime.cpp +7 -6
- esphome/components/mqtt/mqtt_event.cpp +6 -3
- esphome/components/mqtt/mqtt_fan.cpp +1 -0
- esphome/components/mqtt/mqtt_light.cpp +8 -4
- esphome/components/mqtt/mqtt_lock.cpp +3 -1
- esphome/components/mqtt/mqtt_number.cpp +1 -0
- esphome/components/mqtt/mqtt_select.cpp +2 -1
- esphome/components/mqtt/mqtt_sensor.cpp +3 -1
- esphome/components/mqtt/mqtt_switch.cpp +3 -1
- esphome/components/mqtt/mqtt_text.cpp +1 -0
- esphome/components/mqtt/mqtt_text_sensor.cpp +3 -1
- esphome/components/mqtt/mqtt_time.cpp +4 -3
- esphome/components/mqtt/mqtt_update.cpp +1 -0
- esphome/components/mqtt/mqtt_valve.cpp +3 -1
- esphome/components/ms8607/ms8607.cpp +1 -1
- esphome/components/online_image/__init__.py +4 -1
- esphome/components/online_image/online_image.cpp +11 -5
- esphome/components/online_image/online_image.h +6 -1
- esphome/components/opentherm/output/output.cpp +1 -1
- esphome/components/servo/servo.cpp +2 -2
- esphome/components/web_server/web_server.cpp +13 -9
- esphome/components/web_server_base/__init__.py +1 -1
- esphome/components/web_server_idf/web_server_idf.cpp +2 -0
- esphome/const.py +1 -1
- esphome/core/application.cpp +6 -0
- esphome/core/component.cpp +1 -0
- esphome/platformio_api.py +2 -0
- esphome/writer.py +23 -0
- {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/METADATA +1 -1
- {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/RECORD +49 -49
- {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/WHEEL +0 -0
- {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/entry_points.txt +0 -0
- {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/top_level.txt +0 -0
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
#include "esphome/core/component.h"
|
|
4
4
|
#include "esphome/components/as3935/as3935.h"
|
|
5
5
|
#include "esphome/components/spi/spi.h"
|
|
6
|
-
#include "esphome/components/sensor/sensor.h"
|
|
7
|
-
#include "esphome/components/binary_sensor/binary_sensor.h"
|
|
8
6
|
|
|
9
7
|
namespace esphome {
|
|
10
8
|
namespace as3935_spi {
|
|
@@ -31,7 +31,7 @@ CONFIG_SCHEMA = cv.All(
|
|
|
31
31
|
async def to_code(config):
|
|
32
32
|
if CORE.is_esp32 or CORE.is_libretiny:
|
|
33
33
|
# https://github.com/ESP32Async/AsyncTCP
|
|
34
|
-
cg.add_library("ESP32Async/AsyncTCP", "3.4.
|
|
34
|
+
cg.add_library("ESP32Async/AsyncTCP", "3.4.5")
|
|
35
35
|
elif CORE.is_esp8266:
|
|
36
36
|
# https://github.com/ESP32Async/ESPAsyncTCP
|
|
37
37
|
cg.add_library("ESP32Async/ESPAsyncTCP", "2.0.0")
|
esphome/components/fan/fan.cpp
CHANGED
|
@@ -177,6 +177,10 @@ optional<FanRestoreState> Fan::restore_state_() {
|
|
|
177
177
|
return {};
|
|
178
178
|
}
|
|
179
179
|
void Fan::save_state_() {
|
|
180
|
+
if (this->restore_mode_ == FanRestoreMode::NO_RESTORE) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
180
184
|
FanRestoreState state{};
|
|
181
185
|
state.state = this->state;
|
|
182
186
|
state.oscillating = this->oscillating;
|
|
@@ -83,7 +83,7 @@ void HttpRequestUpdate::update_task(void *params) {
|
|
|
83
83
|
container.reset(); // Release ownership of the container's shared_ptr
|
|
84
84
|
|
|
85
85
|
valid = json::parse_json(response, [this_update](JsonObject root) -> bool {
|
|
86
|
-
if (!root
|
|
86
|
+
if (!root["name"].is<const char *>() || !root["version"].is<const char *>() || !root["builds"].is<JsonArray>()) {
|
|
87
87
|
ESP_LOGE(TAG, "Manifest does not contain required fields");
|
|
88
88
|
return false;
|
|
89
89
|
}
|
|
@@ -91,26 +91,26 @@ void HttpRequestUpdate::update_task(void *params) {
|
|
|
91
91
|
this_update->update_info_.latest_version = root["version"].as<std::string>();
|
|
92
92
|
|
|
93
93
|
for (auto build : root["builds"].as<JsonArray>()) {
|
|
94
|
-
if (!build
|
|
94
|
+
if (!build["chipFamily"].is<const char *>()) {
|
|
95
95
|
ESP_LOGE(TAG, "Manifest does not contain required fields");
|
|
96
96
|
return false;
|
|
97
97
|
}
|
|
98
98
|
if (build["chipFamily"] == ESPHOME_VARIANT) {
|
|
99
|
-
if (!build
|
|
99
|
+
if (!build["ota"].is<JsonObject>()) {
|
|
100
100
|
ESP_LOGE(TAG, "Manifest does not contain required fields");
|
|
101
101
|
return false;
|
|
102
102
|
}
|
|
103
|
-
|
|
104
|
-
if (!ota
|
|
103
|
+
JsonObject ota = build["ota"].as<JsonObject>();
|
|
104
|
+
if (!ota["path"].is<const char *>() || !ota["md5"].is<const char *>()) {
|
|
105
105
|
ESP_LOGE(TAG, "Manifest does not contain required fields");
|
|
106
106
|
return false;
|
|
107
107
|
}
|
|
108
108
|
this_update->update_info_.firmware_url = ota["path"].as<std::string>();
|
|
109
109
|
this_update->update_info_.md5 = ota["md5"].as<std::string>();
|
|
110
110
|
|
|
111
|
-
if (ota
|
|
111
|
+
if (ota["summary"].is<const char *>())
|
|
112
112
|
this_update->update_info_.summary = ota["summary"].as<std::string>();
|
|
113
|
-
if (ota
|
|
113
|
+
if (ota["release_url"].is<const char *>())
|
|
114
114
|
this_update->update_info_.release_url = ota["release_url"].as<std::string>();
|
|
115
115
|
|
|
116
116
|
return true;
|
|
@@ -1,83 +1,76 @@
|
|
|
1
1
|
#include "json_util.h"
|
|
2
2
|
#include "esphome/core/log.h"
|
|
3
3
|
|
|
4
|
+
// ArduinoJson::Allocator is included via ArduinoJson.h in json_util.h
|
|
5
|
+
|
|
4
6
|
namespace esphome {
|
|
5
7
|
namespace json {
|
|
6
8
|
|
|
7
9
|
static const char *const TAG = "json";
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
// Build an allocator for the JSON Library using the RAMAllocator class
|
|
12
|
+
struct SpiRamAllocator : ArduinoJson::Allocator {
|
|
13
|
+
void *allocate(size_t size) override { return this->allocator_.allocate(size); }
|
|
14
|
+
|
|
15
|
+
void deallocate(void *pointer) override {
|
|
16
|
+
// ArduinoJson's Allocator interface doesn't provide the size parameter in deallocate.
|
|
17
|
+
// RAMAllocator::deallocate() requires the size, which we don't have access to here.
|
|
18
|
+
// RAMAllocator::deallocate implementation just calls free() regardless of whether
|
|
19
|
+
// the memory was allocated with heap_caps_malloc or malloc.
|
|
20
|
+
// This is safe because ESP-IDF's heap implementation internally tracks the memory region
|
|
21
|
+
// and routes free() to the appropriate heap.
|
|
22
|
+
free(pointer); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
void *reallocate(void *ptr, size_t new_size) override {
|
|
26
|
+
return this->allocator_.reallocate(static_cast<uint8_t *>(ptr), new_size);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
protected:
|
|
30
|
+
RAMAllocator<uint8_t> allocator_{RAMAllocator<uint8_t>(RAMAllocator<uint8_t>::NONE)};
|
|
31
|
+
};
|
|
11
32
|
|
|
12
33
|
std::string build_json(const json_build_t &f) {
|
|
13
|
-
//
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return "{}";
|
|
26
|
-
}
|
|
27
|
-
JsonObject root = json_document.to<JsonObject>();
|
|
28
|
-
f(root);
|
|
29
|
-
if (json_document.overflowed()) {
|
|
30
|
-
if (request_size == free_heap) {
|
|
31
|
-
ESP_LOGE(TAG, "Could not allocate memory for document! Overflowed largest free heap block: %zu bytes",
|
|
32
|
-
free_heap);
|
|
33
|
-
return "{}";
|
|
34
|
-
}
|
|
35
|
-
request_size = std::min(request_size * 2, free_heap);
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
json_document.shrinkToFit();
|
|
39
|
-
ESP_LOGV(TAG, "Size after shrink %zu bytes", json_document.capacity());
|
|
40
|
-
std::string output;
|
|
41
|
-
serializeJson(json_document, output);
|
|
42
|
-
return output;
|
|
34
|
+
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
35
|
+
auto doc_allocator = SpiRamAllocator();
|
|
36
|
+
JsonDocument json_document(&doc_allocator);
|
|
37
|
+
if (json_document.overflowed()) {
|
|
38
|
+
ESP_LOGE(TAG, "Could not allocate memory for JSON document!");
|
|
39
|
+
return "{}";
|
|
40
|
+
}
|
|
41
|
+
JsonObject root = json_document.to<JsonObject>();
|
|
42
|
+
f(root);
|
|
43
|
+
if (json_document.overflowed()) {
|
|
44
|
+
ESP_LOGE(TAG, "Could not allocate memory for JSON document!");
|
|
45
|
+
return "{}";
|
|
43
46
|
}
|
|
47
|
+
std::string output;
|
|
48
|
+
serializeJson(json_document, output);
|
|
49
|
+
return output;
|
|
50
|
+
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
bool parse_json(const std::string &data, const json_parse_t &f) {
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (json_document.capacity() == 0) {
|
|
56
|
-
ESP_LOGE(TAG, "Could not allocate memory for document! Requested %zu bytes, free heap: %zu", request_size,
|
|
57
|
-
free_heap);
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
DeserializationError err = deserializeJson(json_document, data);
|
|
61
|
-
json_document.shrinkToFit();
|
|
54
|
+
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
55
|
+
auto doc_allocator = SpiRamAllocator();
|
|
56
|
+
JsonDocument json_document(&doc_allocator);
|
|
57
|
+
if (json_document.overflowed()) {
|
|
58
|
+
ESP_LOGE(TAG, "Could not allocate memory for JSON document!");
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
DeserializationError err = deserializeJson(json_document, data);
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
JsonObject root = json_document.as<JsonObject>();
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
ESP_LOGV(TAG, "Increasing memory allocation.");
|
|
73
|
-
request_size *= 2;
|
|
74
|
-
continue;
|
|
75
|
-
} else {
|
|
76
|
-
ESP_LOGE(TAG, "Parse error: %s", err.c_str());
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
65
|
+
if (err == DeserializationError::Ok) {
|
|
66
|
+
return f(root);
|
|
67
|
+
} else if (err == DeserializationError::NoMemory) {
|
|
68
|
+
ESP_LOGE(TAG, "Can not allocate more memory for deserialization. Consider making source string smaller");
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
ESP_LOGE(TAG, "Parse error: %s", err.c_str());
|
|
80
72
|
return false;
|
|
73
|
+
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
|
81
74
|
}
|
|
82
75
|
|
|
83
76
|
} // namespace json
|
|
@@ -9,6 +9,7 @@ namespace light {
|
|
|
9
9
|
// See https://www.home-assistant.io/integrations/light.mqtt/#json-schema for documentation on the schema
|
|
10
10
|
|
|
11
11
|
void LightJSONSchema::dump_json(LightState &state, JsonObject root) {
|
|
12
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
12
13
|
if (state.supports_effects())
|
|
13
14
|
root["effect"] = state.get_effect_name();
|
|
14
15
|
|
|
@@ -52,7 +53,7 @@ void LightJSONSchema::dump_json(LightState &state, JsonObject root) {
|
|
|
52
53
|
if (values.get_color_mode() & ColorCapability::BRIGHTNESS)
|
|
53
54
|
root["brightness"] = uint8_t(values.get_brightness() * 255);
|
|
54
55
|
|
|
55
|
-
JsonObject color = root
|
|
56
|
+
JsonObject color = root["color"].to<JsonObject>();
|
|
56
57
|
if (values.get_color_mode() & ColorCapability::RGB) {
|
|
57
58
|
color["r"] = uint8_t(values.get_color_brightness() * values.get_red() * 255);
|
|
58
59
|
color["g"] = uint8_t(values.get_color_brightness() * values.get_green() * 255);
|
|
@@ -73,7 +74,7 @@ void LightJSONSchema::dump_json(LightState &state, JsonObject root) {
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonObject root) {
|
|
76
|
-
if (root
|
|
77
|
+
if (root["state"].is<const char *>()) {
|
|
77
78
|
auto val = parse_on_off(root["state"]);
|
|
78
79
|
switch (val) {
|
|
79
80
|
case PARSE_ON:
|
|
@@ -90,40 +91,40 @@ void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonO
|
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
if (root
|
|
94
|
+
if (root["brightness"].is<uint8_t>()) {
|
|
94
95
|
call.set_brightness(float(root["brightness"]) / 255.0f);
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
if (root
|
|
98
|
+
if (root["color"].is<JsonObject>()) {
|
|
98
99
|
JsonObject color = root["color"];
|
|
99
100
|
// HA also encodes brightness information in the r, g, b values, so extract that and set it as color brightness.
|
|
100
101
|
float max_rgb = 0.0f;
|
|
101
|
-
if (color
|
|
102
|
+
if (color["r"].is<uint8_t>()) {
|
|
102
103
|
float r = float(color["r"]) / 255.0f;
|
|
103
104
|
max_rgb = fmaxf(max_rgb, r);
|
|
104
105
|
call.set_red(r);
|
|
105
106
|
}
|
|
106
|
-
if (color
|
|
107
|
+
if (color["g"].is<uint8_t>()) {
|
|
107
108
|
float g = float(color["g"]) / 255.0f;
|
|
108
109
|
max_rgb = fmaxf(max_rgb, g);
|
|
109
110
|
call.set_green(g);
|
|
110
111
|
}
|
|
111
|
-
if (color
|
|
112
|
+
if (color["b"].is<uint8_t>()) {
|
|
112
113
|
float b = float(color["b"]) / 255.0f;
|
|
113
114
|
max_rgb = fmaxf(max_rgb, b);
|
|
114
115
|
call.set_blue(b);
|
|
115
116
|
}
|
|
116
|
-
if (color
|
|
117
|
+
if (color["r"].is<uint8_t>() || color["g"].is<uint8_t>() || color["b"].is<uint8_t>()) {
|
|
117
118
|
call.set_color_brightness(max_rgb);
|
|
118
119
|
}
|
|
119
120
|
|
|
120
|
-
if (color
|
|
121
|
+
if (color["c"].is<uint8_t>()) {
|
|
121
122
|
call.set_cold_white(float(color["c"]) / 255.0f);
|
|
122
123
|
}
|
|
123
|
-
if (color
|
|
124
|
+
if (color["w"].is<uint8_t>()) {
|
|
124
125
|
// the HA scheme is ambiguous here, the same key is used for white channel in RGBW and warm
|
|
125
126
|
// white channel in RGBWW.
|
|
126
|
-
if (color
|
|
127
|
+
if (color["c"].is<uint8_t>()) {
|
|
127
128
|
call.set_warm_white(float(color["w"]) / 255.0f);
|
|
128
129
|
} else {
|
|
129
130
|
call.set_white(float(color["w"]) / 255.0f);
|
|
@@ -131,11 +132,11 @@ void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonO
|
|
|
131
132
|
}
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
if (root
|
|
135
|
+
if (root["white_value"].is<uint8_t>()) { // legacy API
|
|
135
136
|
call.set_white(float(root["white_value"]) / 255.0f);
|
|
136
137
|
}
|
|
137
138
|
|
|
138
|
-
if (root
|
|
139
|
+
if (root["color_temp"].is<uint16_t>()) {
|
|
139
140
|
call.set_color_temperature(float(root["color_temp"]));
|
|
140
141
|
}
|
|
141
142
|
}
|
|
@@ -143,17 +144,17 @@ void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonO
|
|
|
143
144
|
void LightJSONSchema::parse_json(LightState &state, LightCall &call, JsonObject root) {
|
|
144
145
|
LightJSONSchema::parse_color_json(state, call, root);
|
|
145
146
|
|
|
146
|
-
if (root
|
|
147
|
+
if (root["flash"].is<uint32_t>()) {
|
|
147
148
|
auto length = uint32_t(float(root["flash"]) * 1000);
|
|
148
149
|
call.set_flash_length(length);
|
|
149
150
|
}
|
|
150
151
|
|
|
151
|
-
if (root
|
|
152
|
+
if (root["transition"].is<uint16_t>()) {
|
|
152
153
|
auto length = uint32_t(float(root["transition"]) * 1000);
|
|
153
154
|
call.set_transition_length(length);
|
|
154
155
|
}
|
|
155
156
|
|
|
156
|
-
if (root
|
|
157
|
+
if (root["effect"].is<const char *>()) {
|
|
157
158
|
const char *effect = root["effect"];
|
|
158
159
|
call.set_effect(effect);
|
|
159
160
|
}
|
|
@@ -55,7 +55,8 @@ void MQTTAlarmControlPanelComponent::dump_config() {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
void MQTTAlarmControlPanelComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
58
|
-
|
|
58
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
59
|
+
JsonArray supported_features = root[MQTT_SUPPORTED_FEATURES].to<JsonArray>();
|
|
59
60
|
const uint32_t acp_supported_features = this->alarm_control_panel_->get_supported_features();
|
|
60
61
|
if (acp_supported_features & ACP_FEAT_ARM_AWAY) {
|
|
61
62
|
supported_features.add("arm_away");
|
|
@@ -30,6 +30,7 @@ MQTTBinarySensorComponent::MQTTBinarySensorComponent(binary_sensor::BinarySensor
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
void MQTTBinarySensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
33
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
33
34
|
if (!this->binary_sensor_->get_device_class().empty())
|
|
34
35
|
root[MQTT_DEVICE_CLASS] = this->binary_sensor_->get_device_class();
|
|
35
36
|
if (this->binary_sensor_->is_status_binary_sensor())
|
|
@@ -31,9 +31,12 @@ void MQTTButtonComponent::dump_config() {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
void MQTTButtonComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
34
|
+
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
34
35
|
config.state_topic = false;
|
|
35
|
-
if (!this->button_->get_device_class().empty())
|
|
36
|
+
if (!this->button_->get_device_class().empty()) {
|
|
36
37
|
root[MQTT_DEVICE_CLASS] = this->button_->get_device_class();
|
|
38
|
+
}
|
|
39
|
+
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
std::string MQTTButtonComponent::component_type() const { return "button"; }
|
|
@@ -92,6 +92,7 @@ void MQTTClientComponent::send_device_info_() {
|
|
|
92
92
|
std::string topic = "esphome/discover/";
|
|
93
93
|
topic.append(App.get_name());
|
|
94
94
|
|
|
95
|
+
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
95
96
|
this->publish_json(
|
|
96
97
|
topic,
|
|
97
98
|
[](JsonObject root) {
|
|
@@ -147,6 +148,7 @@ void MQTTClientComponent::send_device_info_() {
|
|
|
147
148
|
#endif
|
|
148
149
|
},
|
|
149
150
|
2, this->discovery_info_.retain);
|
|
151
|
+
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
void MQTTClientComponent::dump_config() {
|
|
@@ -14,6 +14,7 @@ static const char *const TAG = "mqtt.climate";
|
|
|
14
14
|
using namespace esphome::climate;
|
|
15
15
|
|
|
16
16
|
void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
17
|
+
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
17
18
|
auto traits = this->device_->get_traits();
|
|
18
19
|
// current_temperature_topic
|
|
19
20
|
if (traits.get_supports_current_temperature()) {
|
|
@@ -28,7 +29,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
|
|
|
28
29
|
// mode_state_topic
|
|
29
30
|
root[MQTT_MODE_STATE_TOPIC] = this->get_mode_state_topic();
|
|
30
31
|
// modes
|
|
31
|
-
JsonArray modes = root.
|
|
32
|
+
JsonArray modes = root[MQTT_MODES].to<JsonArray>();
|
|
32
33
|
// sort array for nice UI in HA
|
|
33
34
|
if (traits.supports_mode(CLIMATE_MODE_AUTO))
|
|
34
35
|
modes.add("auto");
|
|
@@ -89,7 +90,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
|
|
|
89
90
|
// preset_mode_state_topic
|
|
90
91
|
root[MQTT_PRESET_MODE_STATE_TOPIC] = this->get_preset_state_topic();
|
|
91
92
|
// presets
|
|
92
|
-
JsonArray presets = root
|
|
93
|
+
JsonArray presets = root["preset_modes"].to<JsonArray>();
|
|
93
94
|
if (traits.supports_preset(CLIMATE_PRESET_HOME))
|
|
94
95
|
presets.add("home");
|
|
95
96
|
if (traits.supports_preset(CLIMATE_PRESET_AWAY))
|
|
@@ -119,7 +120,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
|
|
|
119
120
|
// fan_mode_state_topic
|
|
120
121
|
root[MQTT_FAN_MODE_STATE_TOPIC] = this->get_fan_mode_state_topic();
|
|
121
122
|
// fan_modes
|
|
122
|
-
JsonArray fan_modes = root
|
|
123
|
+
JsonArray fan_modes = root["fan_modes"].to<JsonArray>();
|
|
123
124
|
if (traits.supports_fan_mode(CLIMATE_FAN_ON))
|
|
124
125
|
fan_modes.add("on");
|
|
125
126
|
if (traits.supports_fan_mode(CLIMATE_FAN_OFF))
|
|
@@ -150,7 +151,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
|
|
|
150
151
|
// swing_mode_state_topic
|
|
151
152
|
root[MQTT_SWING_MODE_STATE_TOPIC] = this->get_swing_mode_state_topic();
|
|
152
153
|
// swing_modes
|
|
153
|
-
JsonArray swing_modes = root
|
|
154
|
+
JsonArray swing_modes = root["swing_modes"].to<JsonArray>();
|
|
154
155
|
if (traits.supports_swing_mode(CLIMATE_SWING_OFF))
|
|
155
156
|
swing_modes.add("off");
|
|
156
157
|
if (traits.supports_swing_mode(CLIMATE_SWING_BOTH))
|
|
@@ -163,6 +164,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
|
|
|
163
164
|
|
|
164
165
|
config.state_topic = false;
|
|
165
166
|
config.command_topic = false;
|
|
167
|
+
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
|
166
168
|
}
|
|
167
169
|
void MQTTClimateComponent::setup() {
|
|
168
170
|
auto traits = this->device_->get_traits();
|
|
@@ -70,6 +70,7 @@ bool MQTTComponent::send_discovery_() {
|
|
|
70
70
|
|
|
71
71
|
ESP_LOGV(TAG, "'%s': Sending discovery", this->friendly_name().c_str());
|
|
72
72
|
|
|
73
|
+
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
73
74
|
return global_mqtt_client->publish_json(
|
|
74
75
|
this->get_discovery_topic_(discovery_info),
|
|
75
76
|
[this](JsonObject root) {
|
|
@@ -155,7 +156,7 @@ bool MQTTComponent::send_discovery_() {
|
|
|
155
156
|
}
|
|
156
157
|
std::string node_area = App.get_area();
|
|
157
158
|
|
|
158
|
-
JsonObject device_info = root.
|
|
159
|
+
JsonObject device_info = root[MQTT_DEVICE].to<JsonObject>();
|
|
159
160
|
const auto mac = get_mac_address();
|
|
160
161
|
device_info[MQTT_DEVICE_IDENTIFIERS] = mac;
|
|
161
162
|
device_info[MQTT_DEVICE_NAME] = node_friendly_name;
|
|
@@ -192,6 +193,7 @@ bool MQTTComponent::send_discovery_() {
|
|
|
192
193
|
device_info[MQTT_DEVICE_CONNECTIONS][0][1] = mac;
|
|
193
194
|
},
|
|
194
195
|
this->qos_, discovery_info.retain);
|
|
196
|
+
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
|
195
197
|
}
|
|
196
198
|
|
|
197
199
|
uint8_t MQTTComponent::get_qos() const { return this->qos_; }
|
|
@@ -67,6 +67,7 @@ void MQTTCoverComponent::dump_config() {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
void MQTTCoverComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
70
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
70
71
|
if (!this->cover_->get_device_class().empty())
|
|
71
72
|
root[MQTT_DEVICE_CLASS] = this->cover_->get_device_class();
|
|
72
73
|
|
|
@@ -20,13 +20,13 @@ MQTTDateComponent::MQTTDateComponent(DateEntity *date) : date_(date) {}
|
|
|
20
20
|
void MQTTDateComponent::setup() {
|
|
21
21
|
this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) {
|
|
22
22
|
auto call = this->date_->make_call();
|
|
23
|
-
if (root
|
|
23
|
+
if (root["year"].is<uint16_t>()) {
|
|
24
24
|
call.set_year(root["year"]);
|
|
25
25
|
}
|
|
26
|
-
if (root
|
|
26
|
+
if (root["month"].is<uint8_t>()) {
|
|
27
27
|
call.set_month(root["month"]);
|
|
28
28
|
}
|
|
29
|
-
if (root
|
|
29
|
+
if (root["day"].is<uint8_t>()) {
|
|
30
30
|
call.set_day(root["day"]);
|
|
31
31
|
}
|
|
32
32
|
call.perform();
|
|
@@ -55,6 +55,7 @@ bool MQTTDateComponent::send_initial_state() {
|
|
|
55
55
|
}
|
|
56
56
|
bool MQTTDateComponent::publish_state(uint16_t year, uint8_t month, uint8_t day) {
|
|
57
57
|
return this->publish_json(this->get_state_topic_(), [year, month, day](JsonObject root) {
|
|
58
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
58
59
|
root["year"] = year;
|
|
59
60
|
root["month"] = month;
|
|
60
61
|
root["day"] = day;
|
|
@@ -20,22 +20,22 @@ MQTTDateTimeComponent::MQTTDateTimeComponent(DateTimeEntity *datetime) : datetim
|
|
|
20
20
|
void MQTTDateTimeComponent::setup() {
|
|
21
21
|
this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) {
|
|
22
22
|
auto call = this->datetime_->make_call();
|
|
23
|
-
if (root
|
|
23
|
+
if (root["year"].is<uint16_t>()) {
|
|
24
24
|
call.set_year(root["year"]);
|
|
25
25
|
}
|
|
26
|
-
if (root
|
|
26
|
+
if (root["month"].is<uint8_t>()) {
|
|
27
27
|
call.set_month(root["month"]);
|
|
28
28
|
}
|
|
29
|
-
if (root
|
|
29
|
+
if (root["day"].is<uint8_t>()) {
|
|
30
30
|
call.set_day(root["day"]);
|
|
31
31
|
}
|
|
32
|
-
if (root
|
|
32
|
+
if (root["hour"].is<uint8_t>()) {
|
|
33
33
|
call.set_hour(root["hour"]);
|
|
34
34
|
}
|
|
35
|
-
if (root
|
|
35
|
+
if (root["minute"].is<uint8_t>()) {
|
|
36
36
|
call.set_minute(root["minute"]);
|
|
37
37
|
}
|
|
38
|
-
if (root
|
|
38
|
+
if (root["second"].is<uint8_t>()) {
|
|
39
39
|
call.set_second(root["second"]);
|
|
40
40
|
}
|
|
41
41
|
call.perform();
|
|
@@ -68,6 +68,7 @@ bool MQTTDateTimeComponent::send_initial_state() {
|
|
|
68
68
|
bool MQTTDateTimeComponent::publish_state(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute,
|
|
69
69
|
uint8_t second) {
|
|
70
70
|
return this->publish_json(this->get_state_topic_(), [year, month, day, hour, minute, second](JsonObject root) {
|
|
71
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
71
72
|
root["year"] = year;
|
|
72
73
|
root["month"] = month;
|
|
73
74
|
root["day"] = day;
|
|
@@ -16,7 +16,8 @@ using namespace esphome::event;
|
|
|
16
16
|
MQTTEventComponent::MQTTEventComponent(event::Event *event) : event_(event) {}
|
|
17
17
|
|
|
18
18
|
void MQTTEventComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
19
|
-
|
|
19
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
20
|
+
JsonArray event_types = root[MQTT_EVENT_TYPES].to<JsonArray>();
|
|
20
21
|
for (const auto &event_type : this->event_->get_event_types())
|
|
21
22
|
event_types.add(event_type);
|
|
22
23
|
|
|
@@ -40,8 +41,10 @@ void MQTTEventComponent::dump_config() {
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
bool MQTTEventComponent::publish_event_(const std::string &event_type) {
|
|
43
|
-
return this->publish_json(this->get_state_topic_(),
|
|
44
|
-
|
|
44
|
+
return this->publish_json(this->get_state_topic_(), [event_type](JsonObject root) {
|
|
45
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
46
|
+
root[MQTT_EVENT_TYPE] = event_type;
|
|
47
|
+
});
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
std::string MQTTEventComponent::component_type() const { return "event"; }
|
|
@@ -143,6 +143,7 @@ void MQTTFanComponent::dump_config() {
|
|
|
143
143
|
bool MQTTFanComponent::send_initial_state() { return this->publish_state(); }
|
|
144
144
|
|
|
145
145
|
void MQTTFanComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
146
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
146
147
|
if (this->state_->get_traits().supports_direction()) {
|
|
147
148
|
root[MQTT_DIRECTION_COMMAND_TOPIC] = this->get_direction_command_topic();
|
|
148
149
|
root[MQTT_DIRECTION_STATE_TOPIC] = this->get_direction_state_topic();
|
|
@@ -32,17 +32,21 @@ void MQTTJSONLightComponent::setup() {
|
|
|
32
32
|
MQTTJSONLightComponent::MQTTJSONLightComponent(LightState *state) : state_(state) {}
|
|
33
33
|
|
|
34
34
|
bool MQTTJSONLightComponent::publish_state_() {
|
|
35
|
-
return this->publish_json(this->get_state_topic_(),
|
|
36
|
-
|
|
35
|
+
return this->publish_json(this->get_state_topic_(), [this](JsonObject root) {
|
|
36
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
37
|
+
LightJSONSchema::dump_json(*this->state_, root);
|
|
38
|
+
});
|
|
37
39
|
}
|
|
38
40
|
LightState *MQTTJSONLightComponent::get_state() const { return this->state_; }
|
|
39
41
|
|
|
40
42
|
void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
43
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
41
44
|
root["schema"] = "json";
|
|
42
45
|
auto traits = this->state_->get_traits();
|
|
43
46
|
|
|
44
47
|
root[MQTT_COLOR_MODE] = true;
|
|
45
|
-
|
|
48
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
49
|
+
JsonArray color_modes = root["supported_color_modes"].to<JsonArray>();
|
|
46
50
|
if (traits.supports_color_mode(ColorMode::ON_OFF))
|
|
47
51
|
color_modes.add("onoff");
|
|
48
52
|
if (traits.supports_color_mode(ColorMode::BRIGHTNESS))
|
|
@@ -67,7 +71,7 @@ void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscovery
|
|
|
67
71
|
|
|
68
72
|
if (this->state_->supports_effects()) {
|
|
69
73
|
root["effect"] = true;
|
|
70
|
-
JsonArray effect_list = root.
|
|
74
|
+
JsonArray effect_list = root[MQTT_EFFECT_LIST].to<JsonArray>();
|
|
71
75
|
for (auto *effect : this->state_->get_effects())
|
|
72
76
|
effect_list.add(effect->get_name());
|
|
73
77
|
effect_list.add("None");
|
|
@@ -38,8 +38,10 @@ void MQTTLockComponent::dump_config() {
|
|
|
38
38
|
std::string MQTTLockComponent::component_type() const { return "lock"; }
|
|
39
39
|
const EntityBase *MQTTLockComponent::get_entity() const { return this->lock_; }
|
|
40
40
|
void MQTTLockComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
41
|
-
|
|
41
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
42
|
+
if (this->lock_->traits.get_assumed_state()) {
|
|
42
43
|
root[MQTT_OPTIMISTIC] = true;
|
|
44
|
+
}
|
|
43
45
|
if (this->lock_->traits.get_supports_open())
|
|
44
46
|
root[MQTT_PAYLOAD_OPEN] = "OPEN";
|
|
45
47
|
}
|
|
@@ -40,6 +40,7 @@ const EntityBase *MQTTNumberComponent::get_entity() const { return this->number_
|
|
|
40
40
|
void MQTTNumberComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
41
41
|
const auto &traits = number_->traits;
|
|
42
42
|
// https://www.home-assistant.io/integrations/number.mqtt/
|
|
43
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
43
44
|
root[MQTT_MIN] = traits.get_min_value();
|
|
44
45
|
root[MQTT_MAX] = traits.get_max_value();
|
|
45
46
|
root[MQTT_STEP] = traits.get_step();
|
|
@@ -35,7 +35,8 @@ const EntityBase *MQTTSelectComponent::get_entity() const { return this->select_
|
|
|
35
35
|
void MQTTSelectComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
|
36
36
|
const auto &traits = select_->traits;
|
|
37
37
|
// https://www.home-assistant.io/integrations/select.mqtt/
|
|
38
|
-
|
|
38
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
39
|
+
JsonArray options = root[MQTT_OPTIONS].to<JsonArray>();
|
|
39
40
|
for (const auto &option : traits.get_options())
|
|
40
41
|
options.add(option);
|
|
41
42
|
|