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.

Files changed (49) hide show
  1. esphome/components/as3935_spi/as3935_spi.h +0 -2
  2. esphome/components/async_tcp/__init__.py +1 -1
  3. esphome/components/fan/fan.cpp +4 -0
  4. esphome/components/http_request/update/http_request_update.cpp +7 -7
  5. esphome/components/json/__init__.py +1 -1
  6. esphome/components/json/json_util.cpp +56 -63
  7. esphome/components/light/light_json_schema.cpp +17 -16
  8. esphome/components/mqtt/mqtt_alarm_control_panel.cpp +2 -1
  9. esphome/components/mqtt/mqtt_binary_sensor.cpp +1 -0
  10. esphome/components/mqtt/mqtt_button.cpp +4 -1
  11. esphome/components/mqtt/mqtt_client.cpp +2 -0
  12. esphome/components/mqtt/mqtt_climate.cpp +6 -4
  13. esphome/components/mqtt/mqtt_component.cpp +3 -1
  14. esphome/components/mqtt/mqtt_cover.cpp +1 -0
  15. esphome/components/mqtt/mqtt_date.cpp +4 -3
  16. esphome/components/mqtt/mqtt_datetime.cpp +7 -6
  17. esphome/components/mqtt/mqtt_event.cpp +6 -3
  18. esphome/components/mqtt/mqtt_fan.cpp +1 -0
  19. esphome/components/mqtt/mqtt_light.cpp +8 -4
  20. esphome/components/mqtt/mqtt_lock.cpp +3 -1
  21. esphome/components/mqtt/mqtt_number.cpp +1 -0
  22. esphome/components/mqtt/mqtt_select.cpp +2 -1
  23. esphome/components/mqtt/mqtt_sensor.cpp +3 -1
  24. esphome/components/mqtt/mqtt_switch.cpp +3 -1
  25. esphome/components/mqtt/mqtt_text.cpp +1 -0
  26. esphome/components/mqtt/mqtt_text_sensor.cpp +3 -1
  27. esphome/components/mqtt/mqtt_time.cpp +4 -3
  28. esphome/components/mqtt/mqtt_update.cpp +1 -0
  29. esphome/components/mqtt/mqtt_valve.cpp +3 -1
  30. esphome/components/ms8607/ms8607.cpp +1 -1
  31. esphome/components/online_image/__init__.py +4 -1
  32. esphome/components/online_image/online_image.cpp +11 -5
  33. esphome/components/online_image/online_image.h +6 -1
  34. esphome/components/opentherm/output/output.cpp +1 -1
  35. esphome/components/servo/servo.cpp +2 -2
  36. esphome/components/web_server/web_server.cpp +13 -9
  37. esphome/components/web_server_base/__init__.py +1 -1
  38. esphome/components/web_server_idf/web_server_idf.cpp +2 -0
  39. esphome/const.py +1 -1
  40. esphome/core/application.cpp +6 -0
  41. esphome/core/component.cpp +1 -0
  42. esphome/platformio_api.py +2 -0
  43. esphome/writer.py +23 -0
  44. {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/METADATA +1 -1
  45. {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/RECORD +49 -49
  46. {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/WHEEL +0 -0
  47. {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/entry_points.txt +0 -0
  48. {esphome-2025.7.0b3.dist-info → esphome-2025.7.0b5.dist-info}/licenses/LICENSE +0 -0
  49. {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.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")
@@ -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.containsKey("name") || !root.containsKey("version") || !root.containsKey("builds")) {
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.containsKey("chipFamily")) {
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.containsKey("ota")) {
99
+ if (!build["ota"].is<JsonObject>()) {
100
100
  ESP_LOGE(TAG, "Manifest does not contain required fields");
101
101
  return false;
102
102
  }
103
- auto ota = build["ota"];
104
- if (!ota.containsKey("path") || !ota.containsKey("md5")) {
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.containsKey("summary"))
111
+ if (ota["summary"].is<const char *>())
112
112
  this_update->update_info_.summary = ota["summary"].as<std::string>();
113
- if (ota.containsKey("release_url"))
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;
@@ -12,6 +12,6 @@ CONFIG_SCHEMA = cv.All(
12
12
 
13
13
  @coroutine_with_priority(1.0)
14
14
  async def to_code(config):
15
- cg.add_library("bblanchon/ArduinoJson", "6.18.5")
15
+ cg.add_library("bblanchon/ArduinoJson", "7.4.2")
16
16
  cg.add_define("USE_JSON")
17
17
  cg.add_global(json_ns.using)
@@ -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
- static std::vector<char> global_json_build_buffer; // NOLINT
10
- static const auto ALLOCATOR = RAMAllocator<uint8_t>(RAMAllocator<uint8_t>::ALLOC_INTERNAL);
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
- // Here we are allocating up to 5kb of memory,
14
- // with the heap size minus 2kb to be safe if less than 5kb
15
- // as we can not have a true dynamic sized document.
16
- // The excess memory is freed below with `shrinkToFit()`
17
- auto free_heap = ALLOCATOR.get_max_free_block_size();
18
- size_t request_size = std::min(free_heap, (size_t) 512);
19
- while (true) {
20
- ESP_LOGV(TAG, "Attempting to allocate %zu bytes for JSON serialization", request_size);
21
- DynamicJsonDocument json_document(request_size);
22
- if (json_document.capacity() == 0) {
23
- ESP_LOGE(TAG, "Could not allocate memory for document! Requested %zu bytes, largest free heap block: %zu bytes",
24
- request_size, free_heap);
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
- // Here we are allocating 1.5 times the data size,
48
- // with the heap size minus 2kb to be safe if less than that
49
- // as we can not have a true dynamic sized document.
50
- // The excess memory is freed below with `shrinkToFit()`
51
- auto free_heap = ALLOCATOR.get_max_free_block_size();
52
- size_t request_size = std::min(free_heap, (size_t) (data.size() * 1.5));
53
- while (true) {
54
- DynamicJsonDocument json_document(request_size);
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
- JsonObject root = json_document.as<JsonObject>();
63
+ JsonObject root = json_document.as<JsonObject>();
64
64
 
65
- if (err == DeserializationError::Ok) {
66
- return f(root);
67
- } else if (err == DeserializationError::NoMemory) {
68
- if (request_size * 2 >= free_heap) {
69
- ESP_LOGE(TAG, "Can not allocate more memory for deserialization. Consider making source string smaller");
70
- return false;
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.createNestedObject("color");
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.containsKey("state")) {
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.containsKey("brightness")) {
94
+ if (root["brightness"].is<uint8_t>()) {
94
95
  call.set_brightness(float(root["brightness"]) / 255.0f);
95
96
  }
96
97
 
97
- if (root.containsKey("color")) {
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.containsKey("r")) {
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.containsKey("g")) {
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.containsKey("b")) {
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.containsKey("r") || color.containsKey("g") || color.containsKey("b")) {
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.containsKey("c")) {
121
+ if (color["c"].is<uint8_t>()) {
121
122
  call.set_cold_white(float(color["c"]) / 255.0f);
122
123
  }
123
- if (color.containsKey("w")) {
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.containsKey("c")) {
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.containsKey("white_value")) { // legacy API
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.containsKey("color_temp")) {
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.containsKey("flash")) {
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.containsKey("transition")) {
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.containsKey("effect")) {
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
- JsonArray supported_features = root.createNestedArray(MQTT_SUPPORTED_FEATURES);
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.createNestedArray(MQTT_MODES);
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.createNestedArray("preset_modes");
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.createNestedArray("fan_modes");
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.createNestedArray("swing_modes");
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.createNestedObject(MQTT_DEVICE);
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.containsKey("year")) {
23
+ if (root["year"].is<uint16_t>()) {
24
24
  call.set_year(root["year"]);
25
25
  }
26
- if (root.containsKey("month")) {
26
+ if (root["month"].is<uint8_t>()) {
27
27
  call.set_month(root["month"]);
28
28
  }
29
- if (root.containsKey("day")) {
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.containsKey("year")) {
23
+ if (root["year"].is<uint16_t>()) {
24
24
  call.set_year(root["year"]);
25
25
  }
26
- if (root.containsKey("month")) {
26
+ if (root["month"].is<uint8_t>()) {
27
27
  call.set_month(root["month"]);
28
28
  }
29
- if (root.containsKey("day")) {
29
+ if (root["day"].is<uint8_t>()) {
30
30
  call.set_day(root["day"]);
31
31
  }
32
- if (root.containsKey("hour")) {
32
+ if (root["hour"].is<uint8_t>()) {
33
33
  call.set_hour(root["hour"]);
34
34
  }
35
- if (root.containsKey("minute")) {
35
+ if (root["minute"].is<uint8_t>()) {
36
36
  call.set_minute(root["minute"]);
37
37
  }
38
- if (root.containsKey("second")) {
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
- JsonArray event_types = root.createNestedArray(MQTT_EVENT_TYPES);
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
- [event_type](JsonObject root) { root[MQTT_EVENT_TYPE] = event_type; });
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
- [this](JsonObject root) { LightJSONSchema::dump_json(*this->state_, root); });
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
- JsonArray color_modes = root.createNestedArray("supported_color_modes");
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.createNestedArray(MQTT_EFFECT_LIST);
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
- if (this->lock_->traits.get_assumed_state())
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
- JsonArray options = root.createNestedArray(MQTT_OPTIONS);
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