mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	[json] Bump ArduinoJson library to 7.4.2 (#8857)
Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		
				
					committed by
					
						 Jesse Hills
						Jesse Hills
					
				
			
			
				
	
			
			
			
						parent
						
							78e8001aa8
						
					
				
				
					commit
					35b3f75f7c
				
			| @@ -83,7 +83,7 @@ void HttpRequestUpdate::update_task(void *params) { | ||||
|     container.reset();  // Release ownership of the container's shared_ptr | ||||
|  | ||||
|     valid = json::parse_json(response, [this_update](JsonObject root) -> bool { | ||||
|       if (!root.containsKey("name") || !root.containsKey("version") || !root.containsKey("builds")) { | ||||
|       if (!root["name"].is<const char *>() || !root["version"].is<const char *>() || !root["builds"].is<JsonArray>()) { | ||||
|         ESP_LOGE(TAG, "Manifest does not contain required fields"); | ||||
|         return false; | ||||
|       } | ||||
| @@ -91,26 +91,26 @@ void HttpRequestUpdate::update_task(void *params) { | ||||
|       this_update->update_info_.latest_version = root["version"].as<std::string>(); | ||||
|  | ||||
|       for (auto build : root["builds"].as<JsonArray>()) { | ||||
|         if (!build.containsKey("chipFamily")) { | ||||
|         if (!build["chipFamily"].is<const char *>()) { | ||||
|           ESP_LOGE(TAG, "Manifest does not contain required fields"); | ||||
|           return false; | ||||
|         } | ||||
|         if (build["chipFamily"] == ESPHOME_VARIANT) { | ||||
|           if (!build.containsKey("ota")) { | ||||
|           if (!build["ota"].is<JsonObject>()) { | ||||
|             ESP_LOGE(TAG, "Manifest does not contain required fields"); | ||||
|             return false; | ||||
|           } | ||||
|           auto ota = build["ota"]; | ||||
|           if (!ota.containsKey("path") || !ota.containsKey("md5")) { | ||||
|           JsonObject ota = build["ota"].as<JsonObject>(); | ||||
|           if (!ota["path"].is<const char *>() || !ota["md5"].is<const char *>()) { | ||||
|             ESP_LOGE(TAG, "Manifest does not contain required fields"); | ||||
|             return false; | ||||
|           } | ||||
|           this_update->update_info_.firmware_url = ota["path"].as<std::string>(); | ||||
|           this_update->update_info_.md5 = ota["md5"].as<std::string>(); | ||||
|  | ||||
|           if (ota.containsKey("summary")) | ||||
|           if (ota["summary"].is<const char *>()) | ||||
|             this_update->update_info_.summary = ota["summary"].as<std::string>(); | ||||
|           if (ota.containsKey("release_url")) | ||||
|           if (ota["release_url"].is<const char *>()) | ||||
|             this_update->update_info_.release_url = ota["release_url"].as<std::string>(); | ||||
|  | ||||
|           return true; | ||||
|   | ||||
| @@ -12,6 +12,6 @@ CONFIG_SCHEMA = cv.All( | ||||
|  | ||||
| @coroutine_with_priority(1.0) | ||||
| async def to_code(config): | ||||
|     cg.add_library("bblanchon/ArduinoJson", "6.18.5") | ||||
|     cg.add_library("bblanchon/ArduinoJson", "7.4.2") | ||||
|     cg.add_define("USE_JSON") | ||||
|     cg.add_global(json_ns.using) | ||||
|   | ||||
| @@ -1,83 +1,76 @@ | ||||
| #include "json_util.h" | ||||
| #include "esphome/core/log.h" | ||||
|  | ||||
| // ArduinoJson::Allocator is included via ArduinoJson.h in json_util.h | ||||
|  | ||||
| namespace esphome { | ||||
| namespace json { | ||||
|  | ||||
| static const char *const TAG = "json"; | ||||
|  | ||||
| static std::vector<char> global_json_build_buffer;  // NOLINT | ||||
| static const auto ALLOCATOR = RAMAllocator<uint8_t>(RAMAllocator<uint8_t>::ALLOC_INTERNAL); | ||||
| // Build an allocator for the JSON Library using the RAMAllocator class | ||||
| struct SpiRamAllocator : ArduinoJson::Allocator { | ||||
|   void *allocate(size_t size) override { return this->allocator_.allocate(size); } | ||||
|  | ||||
|   void deallocate(void *pointer) override { | ||||
|     // ArduinoJson's Allocator interface doesn't provide the size parameter in deallocate. | ||||
|     // RAMAllocator::deallocate() requires the size, which we don't have access to here. | ||||
|     // RAMAllocator::deallocate implementation just calls free() regardless of whether | ||||
|     // the memory was allocated with heap_caps_malloc or malloc. | ||||
|     // This is safe because ESP-IDF's heap implementation internally tracks the memory region | ||||
|     // and routes free() to the appropriate heap. | ||||
|     free(pointer);  // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc) | ||||
|   } | ||||
|  | ||||
|   void *reallocate(void *ptr, size_t new_size) override { | ||||
|     return this->allocator_.reallocate(static_cast<uint8_t *>(ptr), new_size); | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   RAMAllocator<uint8_t> allocator_{RAMAllocator<uint8_t>(RAMAllocator<uint8_t>::NONE)}; | ||||
| }; | ||||
|  | ||||
| std::string build_json(const json_build_t &f) { | ||||
|   // Here we are allocating up to 5kb of memory, | ||||
|   // with the heap size minus 2kb to be safe if less than 5kb | ||||
|   // as we can not have a true dynamic sized document. | ||||
|   // The excess memory is freed below with `shrinkToFit()` | ||||
|   auto free_heap = ALLOCATOR.get_max_free_block_size(); | ||||
|   size_t request_size = std::min(free_heap, (size_t) 512); | ||||
|   while (true) { | ||||
|     ESP_LOGV(TAG, "Attempting to allocate %zu bytes for JSON serialization", request_size); | ||||
|     DynamicJsonDocument json_document(request_size); | ||||
|     if (json_document.capacity() == 0) { | ||||
|       ESP_LOGE(TAG, "Could not allocate memory for document! Requested %zu bytes, largest free heap block: %zu bytes", | ||||
|                request_size, free_heap); | ||||
|   // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   auto doc_allocator = SpiRamAllocator(); | ||||
|   JsonDocument json_document(&doc_allocator); | ||||
|   if (json_document.overflowed()) { | ||||
|     ESP_LOGE(TAG, "Could not allocate memory for JSON document!"); | ||||
|     return "{}"; | ||||
|   } | ||||
|   JsonObject root = json_document.to<JsonObject>(); | ||||
|   f(root); | ||||
|   if (json_document.overflowed()) { | ||||
|       if (request_size == free_heap) { | ||||
|         ESP_LOGE(TAG, "Could not allocate memory for document! Overflowed largest free heap block: %zu bytes", | ||||
|                  free_heap); | ||||
|     ESP_LOGE(TAG, "Could not allocate memory for JSON document!"); | ||||
|     return "{}"; | ||||
|   } | ||||
|       request_size = std::min(request_size * 2, free_heap); | ||||
|       continue; | ||||
|     } | ||||
|     json_document.shrinkToFit(); | ||||
|     ESP_LOGV(TAG, "Size after shrink %zu bytes", json_document.capacity()); | ||||
|   std::string output; | ||||
|   serializeJson(json_document, output); | ||||
|   return output; | ||||
|   } | ||||
|   // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) | ||||
| } | ||||
|  | ||||
| bool parse_json(const std::string &data, const json_parse_t &f) { | ||||
|   // Here we are allocating 1.5 times the data size, | ||||
|   // with the heap size minus 2kb to be safe if less than that | ||||
|   // as we can not have a true dynamic sized document. | ||||
|   // The excess memory is freed below with `shrinkToFit()` | ||||
|   auto free_heap = ALLOCATOR.get_max_free_block_size(); | ||||
|   size_t request_size = std::min(free_heap, (size_t) (data.size() * 1.5)); | ||||
|   while (true) { | ||||
|     DynamicJsonDocument json_document(request_size); | ||||
|     if (json_document.capacity() == 0) { | ||||
|       ESP_LOGE(TAG, "Could not allocate memory for document! Requested %zu bytes, free heap: %zu", request_size, | ||||
|                free_heap); | ||||
|   // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   auto doc_allocator = SpiRamAllocator(); | ||||
|   JsonDocument json_document(&doc_allocator); | ||||
|   if (json_document.overflowed()) { | ||||
|     ESP_LOGE(TAG, "Could not allocate memory for JSON document!"); | ||||
|     return false; | ||||
|   } | ||||
|   DeserializationError err = deserializeJson(json_document, data); | ||||
|     json_document.shrinkToFit(); | ||||
|  | ||||
|   JsonObject root = json_document.as<JsonObject>(); | ||||
|  | ||||
|   if (err == DeserializationError::Ok) { | ||||
|     return f(root); | ||||
|   } else if (err == DeserializationError::NoMemory) { | ||||
|       if (request_size * 2 >= free_heap) { | ||||
|     ESP_LOGE(TAG, "Can not allocate more memory for deserialization. Consider making source string smaller"); | ||||
|     return false; | ||||
|   } | ||||
|       ESP_LOGV(TAG, "Increasing memory allocation."); | ||||
|       request_size *= 2; | ||||
|       continue; | ||||
|     } else { | ||||
|   ESP_LOGE(TAG, "Parse error: %s", err.c_str()); | ||||
|   return false; | ||||
|     } | ||||
|   }; | ||||
|   return false; | ||||
|   // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) | ||||
| } | ||||
|  | ||||
| }  // namespace json | ||||
|   | ||||
| @@ -9,6 +9,7 @@ namespace light { | ||||
| // See https://www.home-assistant.io/integrations/light.mqtt/#json-schema for documentation on the schema | ||||
|  | ||||
| void LightJSONSchema::dump_json(LightState &state, JsonObject root) { | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   if (state.supports_effects()) | ||||
|     root["effect"] = state.get_effect_name(); | ||||
|  | ||||
| @@ -52,7 +53,7 @@ void LightJSONSchema::dump_json(LightState &state, JsonObject root) { | ||||
|   if (values.get_color_mode() & ColorCapability::BRIGHTNESS) | ||||
|     root["brightness"] = uint8_t(values.get_brightness() * 255); | ||||
|  | ||||
|   JsonObject color = root.createNestedObject("color"); | ||||
|   JsonObject color = root["color"].to<JsonObject>(); | ||||
|   if (values.get_color_mode() & ColorCapability::RGB) { | ||||
|     color["r"] = uint8_t(values.get_color_brightness() * values.get_red() * 255); | ||||
|     color["g"] = uint8_t(values.get_color_brightness() * values.get_green() * 255); | ||||
| @@ -73,7 +74,7 @@ void LightJSONSchema::dump_json(LightState &state, JsonObject root) { | ||||
| } | ||||
|  | ||||
| void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonObject root) { | ||||
|   if (root.containsKey("state")) { | ||||
|   if (root["state"].is<const char *>()) { | ||||
|     auto val = parse_on_off(root["state"]); | ||||
|     switch (val) { | ||||
|       case PARSE_ON: | ||||
| @@ -90,40 +91,40 @@ void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonO | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (root.containsKey("brightness")) { | ||||
|   if (root["brightness"].is<uint8_t>()) { | ||||
|     call.set_brightness(float(root["brightness"]) / 255.0f); | ||||
|   } | ||||
|  | ||||
|   if (root.containsKey("color")) { | ||||
|   if (root["color"].is<JsonObject>()) { | ||||
|     JsonObject color = root["color"]; | ||||
|     // HA also encodes brightness information in the r, g, b values, so extract that and set it as color brightness. | ||||
|     float max_rgb = 0.0f; | ||||
|     if (color.containsKey("r")) { | ||||
|     if (color["r"].is<uint8_t>()) { | ||||
|       float r = float(color["r"]) / 255.0f; | ||||
|       max_rgb = fmaxf(max_rgb, r); | ||||
|       call.set_red(r); | ||||
|     } | ||||
|     if (color.containsKey("g")) { | ||||
|     if (color["g"].is<uint8_t>()) { | ||||
|       float g = float(color["g"]) / 255.0f; | ||||
|       max_rgb = fmaxf(max_rgb, g); | ||||
|       call.set_green(g); | ||||
|     } | ||||
|     if (color.containsKey("b")) { | ||||
|     if (color["b"].is<uint8_t>()) { | ||||
|       float b = float(color["b"]) / 255.0f; | ||||
|       max_rgb = fmaxf(max_rgb, b); | ||||
|       call.set_blue(b); | ||||
|     } | ||||
|     if (color.containsKey("r") || color.containsKey("g") || color.containsKey("b")) { | ||||
|     if (color["r"].is<uint8_t>() || color["g"].is<uint8_t>() || color["b"].is<uint8_t>()) { | ||||
|       call.set_color_brightness(max_rgb); | ||||
|     } | ||||
|  | ||||
|     if (color.containsKey("c")) { | ||||
|     if (color["c"].is<uint8_t>()) { | ||||
|       call.set_cold_white(float(color["c"]) / 255.0f); | ||||
|     } | ||||
|     if (color.containsKey("w")) { | ||||
|     if (color["w"].is<uint8_t>()) { | ||||
|       // the HA scheme is ambiguous here, the same key is used for white channel in RGBW and warm | ||||
|       // white channel in RGBWW. | ||||
|       if (color.containsKey("c")) { | ||||
|       if (color["c"].is<uint8_t>()) { | ||||
|         call.set_warm_white(float(color["w"]) / 255.0f); | ||||
|       } else { | ||||
|         call.set_white(float(color["w"]) / 255.0f); | ||||
| @@ -131,11 +132,11 @@ void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonO | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (root.containsKey("white_value")) {  // legacy API | ||||
|   if (root["white_value"].is<uint8_t>()) {  // legacy API | ||||
|     call.set_white(float(root["white_value"]) / 255.0f); | ||||
|   } | ||||
|  | ||||
|   if (root.containsKey("color_temp")) { | ||||
|   if (root["color_temp"].is<uint16_t>()) { | ||||
|     call.set_color_temperature(float(root["color_temp"])); | ||||
|   } | ||||
| } | ||||
| @@ -143,17 +144,17 @@ void LightJSONSchema::parse_color_json(LightState &state, LightCall &call, JsonO | ||||
| void LightJSONSchema::parse_json(LightState &state, LightCall &call, JsonObject root) { | ||||
|   LightJSONSchema::parse_color_json(state, call, root); | ||||
|  | ||||
|   if (root.containsKey("flash")) { | ||||
|   if (root["flash"].is<uint32_t>()) { | ||||
|     auto length = uint32_t(float(root["flash"]) * 1000); | ||||
|     call.set_flash_length(length); | ||||
|   } | ||||
|  | ||||
|   if (root.containsKey("transition")) { | ||||
|   if (root["transition"].is<uint16_t>()) { | ||||
|     auto length = uint32_t(float(root["transition"]) * 1000); | ||||
|     call.set_transition_length(length); | ||||
|   } | ||||
|  | ||||
|   if (root.containsKey("effect")) { | ||||
|   if (root["effect"].is<const char *>()) { | ||||
|     const char *effect = root["effect"]; | ||||
|     call.set_effect(effect); | ||||
|   } | ||||
|   | ||||
| @@ -55,7 +55,8 @@ void MQTTAlarmControlPanelComponent::dump_config() { | ||||
| } | ||||
|  | ||||
| void MQTTAlarmControlPanelComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   JsonArray supported_features = root.createNestedArray(MQTT_SUPPORTED_FEATURES); | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   JsonArray supported_features = root[MQTT_SUPPORTED_FEATURES].to<JsonArray>(); | ||||
|   const uint32_t acp_supported_features = this->alarm_control_panel_->get_supported_features(); | ||||
|   if (acp_supported_features & ACP_FEAT_ARM_AWAY) { | ||||
|     supported_features.add("arm_away"); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ MQTTBinarySensorComponent::MQTTBinarySensorComponent(binary_sensor::BinarySensor | ||||
| } | ||||
|  | ||||
| void MQTTBinarySensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   if (!this->binary_sensor_->get_device_class().empty()) | ||||
|     root[MQTT_DEVICE_CLASS] = this->binary_sensor_->get_device_class(); | ||||
|   if (this->binary_sensor_->is_status_binary_sensor()) | ||||
|   | ||||
| @@ -31,10 +31,13 @@ void MQTTButtonComponent::dump_config() { | ||||
| } | ||||
|  | ||||
| void MQTTButtonComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   config.state_topic = false; | ||||
|   if (!this->button_->get_device_class().empty()) | ||||
|   if (!this->button_->get_device_class().empty()) { | ||||
|     root[MQTT_DEVICE_CLASS] = this->button_->get_device_class(); | ||||
|   } | ||||
|   // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) | ||||
| } | ||||
|  | ||||
| std::string MQTTButtonComponent::component_type() const { return "button"; } | ||||
| const EntityBase *MQTTButtonComponent::get_entity() const { return this->button_; } | ||||
|   | ||||
| @@ -92,6 +92,7 @@ void MQTTClientComponent::send_device_info_() { | ||||
|   std::string topic = "esphome/discover/"; | ||||
|   topic.append(App.get_name()); | ||||
|  | ||||
|   // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   this->publish_json( | ||||
|       topic, | ||||
|       [](JsonObject root) { | ||||
| @@ -147,6 +148,7 @@ void MQTTClientComponent::send_device_info_() { | ||||
| #endif | ||||
|       }, | ||||
|       2, this->discovery_info_.retain); | ||||
|   // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) | ||||
| } | ||||
|  | ||||
| void MQTTClientComponent::dump_config() { | ||||
|   | ||||
| @@ -14,6 +14,7 @@ static const char *const TAG = "mqtt.climate"; | ||||
| using namespace esphome::climate; | ||||
|  | ||||
| void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   auto traits = this->device_->get_traits(); | ||||
|   // current_temperature_topic | ||||
|   if (traits.get_supports_current_temperature()) { | ||||
| @@ -28,7 +29,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo | ||||
|   // mode_state_topic | ||||
|   root[MQTT_MODE_STATE_TOPIC] = this->get_mode_state_topic(); | ||||
|   // modes | ||||
|   JsonArray modes = root.createNestedArray(MQTT_MODES); | ||||
|   JsonArray modes = root[MQTT_MODES].to<JsonArray>(); | ||||
|   // sort array for nice UI in HA | ||||
|   if (traits.supports_mode(CLIMATE_MODE_AUTO)) | ||||
|     modes.add("auto"); | ||||
| @@ -89,7 +90,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo | ||||
|     // preset_mode_state_topic | ||||
|     root[MQTT_PRESET_MODE_STATE_TOPIC] = this->get_preset_state_topic(); | ||||
|     // presets | ||||
|     JsonArray presets = root.createNestedArray("preset_modes"); | ||||
|     JsonArray presets = root["preset_modes"].to<JsonArray>(); | ||||
|     if (traits.supports_preset(CLIMATE_PRESET_HOME)) | ||||
|       presets.add("home"); | ||||
|     if (traits.supports_preset(CLIMATE_PRESET_AWAY)) | ||||
| @@ -119,7 +120,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo | ||||
|     // fan_mode_state_topic | ||||
|     root[MQTT_FAN_MODE_STATE_TOPIC] = this->get_fan_mode_state_topic(); | ||||
|     // fan_modes | ||||
|     JsonArray fan_modes = root.createNestedArray("fan_modes"); | ||||
|     JsonArray fan_modes = root["fan_modes"].to<JsonArray>(); | ||||
|     if (traits.supports_fan_mode(CLIMATE_FAN_ON)) | ||||
|       fan_modes.add("on"); | ||||
|     if (traits.supports_fan_mode(CLIMATE_FAN_OFF)) | ||||
| @@ -150,7 +151,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo | ||||
|     // swing_mode_state_topic | ||||
|     root[MQTT_SWING_MODE_STATE_TOPIC] = this->get_swing_mode_state_topic(); | ||||
|     // swing_modes | ||||
|     JsonArray swing_modes = root.createNestedArray("swing_modes"); | ||||
|     JsonArray swing_modes = root["swing_modes"].to<JsonArray>(); | ||||
|     if (traits.supports_swing_mode(CLIMATE_SWING_OFF)) | ||||
|       swing_modes.add("off"); | ||||
|     if (traits.supports_swing_mode(CLIMATE_SWING_BOTH)) | ||||
| @@ -163,6 +164,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo | ||||
|  | ||||
|   config.state_topic = false; | ||||
|   config.command_topic = false; | ||||
|   // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) | ||||
| } | ||||
| void MQTTClimateComponent::setup() { | ||||
|   auto traits = this->device_->get_traits(); | ||||
|   | ||||
| @@ -70,6 +70,7 @@ bool MQTTComponent::send_discovery_() { | ||||
|  | ||||
|   ESP_LOGV(TAG, "'%s': Sending discovery", this->friendly_name().c_str()); | ||||
|  | ||||
|   // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   return global_mqtt_client->publish_json( | ||||
|       this->get_discovery_topic_(discovery_info), | ||||
|       [this](JsonObject root) { | ||||
| @@ -155,7 +156,7 @@ bool MQTTComponent::send_discovery_() { | ||||
|         } | ||||
|         std::string node_area = App.get_area(); | ||||
|  | ||||
|         JsonObject device_info = root.createNestedObject(MQTT_DEVICE); | ||||
|         JsonObject device_info = root[MQTT_DEVICE].to<JsonObject>(); | ||||
|         const auto mac = get_mac_address(); | ||||
|         device_info[MQTT_DEVICE_IDENTIFIERS] = mac; | ||||
|         device_info[MQTT_DEVICE_NAME] = node_friendly_name; | ||||
| @@ -192,6 +193,7 @@ bool MQTTComponent::send_discovery_() { | ||||
|         device_info[MQTT_DEVICE_CONNECTIONS][0][1] = mac; | ||||
|       }, | ||||
|       this->qos_, discovery_info.retain); | ||||
|   // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) | ||||
| } | ||||
|  | ||||
| uint8_t MQTTComponent::get_qos() const { return this->qos_; } | ||||
|   | ||||
| @@ -67,6 +67,7 @@ void MQTTCoverComponent::dump_config() { | ||||
|   } | ||||
| } | ||||
| void MQTTCoverComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   if (!this->cover_->get_device_class().empty()) | ||||
|     root[MQTT_DEVICE_CLASS] = this->cover_->get_device_class(); | ||||
|  | ||||
|   | ||||
| @@ -20,13 +20,13 @@ MQTTDateComponent::MQTTDateComponent(DateEntity *date) : date_(date) {} | ||||
| void MQTTDateComponent::setup() { | ||||
|   this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) { | ||||
|     auto call = this->date_->make_call(); | ||||
|     if (root.containsKey("year")) { | ||||
|     if (root["year"].is<uint16_t>()) { | ||||
|       call.set_year(root["year"]); | ||||
|     } | ||||
|     if (root.containsKey("month")) { | ||||
|     if (root["month"].is<uint8_t>()) { | ||||
|       call.set_month(root["month"]); | ||||
|     } | ||||
|     if (root.containsKey("day")) { | ||||
|     if (root["day"].is<uint8_t>()) { | ||||
|       call.set_day(root["day"]); | ||||
|     } | ||||
|     call.perform(); | ||||
| @@ -55,6 +55,7 @@ bool MQTTDateComponent::send_initial_state() { | ||||
| } | ||||
| bool MQTTDateComponent::publish_state(uint16_t year, uint8_t month, uint8_t day) { | ||||
|   return this->publish_json(this->get_state_topic_(), [year, month, day](JsonObject root) { | ||||
|     // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|     root["year"] = year; | ||||
|     root["month"] = month; | ||||
|     root["day"] = day; | ||||
|   | ||||
| @@ -20,22 +20,22 @@ MQTTDateTimeComponent::MQTTDateTimeComponent(DateTimeEntity *datetime) : datetim | ||||
| void MQTTDateTimeComponent::setup() { | ||||
|   this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) { | ||||
|     auto call = this->datetime_->make_call(); | ||||
|     if (root.containsKey("year")) { | ||||
|     if (root["year"].is<uint16_t>()) { | ||||
|       call.set_year(root["year"]); | ||||
|     } | ||||
|     if (root.containsKey("month")) { | ||||
|     if (root["month"].is<uint8_t>()) { | ||||
|       call.set_month(root["month"]); | ||||
|     } | ||||
|     if (root.containsKey("day")) { | ||||
|     if (root["day"].is<uint8_t>()) { | ||||
|       call.set_day(root["day"]); | ||||
|     } | ||||
|     if (root.containsKey("hour")) { | ||||
|     if (root["hour"].is<uint8_t>()) { | ||||
|       call.set_hour(root["hour"]); | ||||
|     } | ||||
|     if (root.containsKey("minute")) { | ||||
|     if (root["minute"].is<uint8_t>()) { | ||||
|       call.set_minute(root["minute"]); | ||||
|     } | ||||
|     if (root.containsKey("second")) { | ||||
|     if (root["second"].is<uint8_t>()) { | ||||
|       call.set_second(root["second"]); | ||||
|     } | ||||
|     call.perform(); | ||||
| @@ -68,6 +68,7 @@ bool MQTTDateTimeComponent::send_initial_state() { | ||||
| bool MQTTDateTimeComponent::publish_state(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, | ||||
|                                           uint8_t second) { | ||||
|   return this->publish_json(this->get_state_topic_(), [year, month, day, hour, minute, second](JsonObject root) { | ||||
|     // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|     root["year"] = year; | ||||
|     root["month"] = month; | ||||
|     root["day"] = day; | ||||
|   | ||||
| @@ -16,7 +16,8 @@ using namespace esphome::event; | ||||
| MQTTEventComponent::MQTTEventComponent(event::Event *event) : event_(event) {} | ||||
|  | ||||
| void MQTTEventComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   JsonArray event_types = root.createNestedArray(MQTT_EVENT_TYPES); | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   JsonArray event_types = root[MQTT_EVENT_TYPES].to<JsonArray>(); | ||||
|   for (const auto &event_type : this->event_->get_event_types()) | ||||
|     event_types.add(event_type); | ||||
|  | ||||
| @@ -40,8 +41,10 @@ void MQTTEventComponent::dump_config() { | ||||
| } | ||||
|  | ||||
| bool MQTTEventComponent::publish_event_(const std::string &event_type) { | ||||
|   return this->publish_json(this->get_state_topic_(), | ||||
|                             [event_type](JsonObject root) { root[MQTT_EVENT_TYPE] = event_type; }); | ||||
|   return this->publish_json(this->get_state_topic_(), [event_type](JsonObject root) { | ||||
|     // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|     root[MQTT_EVENT_TYPE] = event_type; | ||||
|   }); | ||||
| } | ||||
|  | ||||
| std::string MQTTEventComponent::component_type() const { return "event"; } | ||||
|   | ||||
| @@ -143,6 +143,7 @@ void MQTTFanComponent::dump_config() { | ||||
| bool MQTTFanComponent::send_initial_state() { return this->publish_state(); } | ||||
|  | ||||
| void MQTTFanComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   if (this->state_->get_traits().supports_direction()) { | ||||
|     root[MQTT_DIRECTION_COMMAND_TOPIC] = this->get_direction_command_topic(); | ||||
|     root[MQTT_DIRECTION_STATE_TOPIC] = this->get_direction_state_topic(); | ||||
|   | ||||
| @@ -32,17 +32,21 @@ void MQTTJSONLightComponent::setup() { | ||||
| MQTTJSONLightComponent::MQTTJSONLightComponent(LightState *state) : state_(state) {} | ||||
|  | ||||
| bool MQTTJSONLightComponent::publish_state_() { | ||||
|   return this->publish_json(this->get_state_topic_(), | ||||
|                             [this](JsonObject root) { LightJSONSchema::dump_json(*this->state_, root); }); | ||||
|   return this->publish_json(this->get_state_topic_(), [this](JsonObject root) { | ||||
|     // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|     LightJSONSchema::dump_json(*this->state_, root); | ||||
|   }); | ||||
| } | ||||
| LightState *MQTTJSONLightComponent::get_state() const { return this->state_; } | ||||
|  | ||||
| void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   root["schema"] = "json"; | ||||
|   auto traits = this->state_->get_traits(); | ||||
|  | ||||
|   root[MQTT_COLOR_MODE] = true; | ||||
|   JsonArray color_modes = root.createNestedArray("supported_color_modes"); | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   JsonArray color_modes = root["supported_color_modes"].to<JsonArray>(); | ||||
|   if (traits.supports_color_mode(ColorMode::ON_OFF)) | ||||
|     color_modes.add("onoff"); | ||||
|   if (traits.supports_color_mode(ColorMode::BRIGHTNESS)) | ||||
| @@ -67,7 +71,7 @@ void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscovery | ||||
|  | ||||
|   if (this->state_->supports_effects()) { | ||||
|     root["effect"] = true; | ||||
|     JsonArray effect_list = root.createNestedArray(MQTT_EFFECT_LIST); | ||||
|     JsonArray effect_list = root[MQTT_EFFECT_LIST].to<JsonArray>(); | ||||
|     for (auto *effect : this->state_->get_effects()) | ||||
|       effect_list.add(effect->get_name()); | ||||
|     effect_list.add("None"); | ||||
|   | ||||
| @@ -38,8 +38,10 @@ void MQTTLockComponent::dump_config() { | ||||
| std::string MQTTLockComponent::component_type() const { return "lock"; } | ||||
| const EntityBase *MQTTLockComponent::get_entity() const { return this->lock_; } | ||||
| void MQTTLockComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   if (this->lock_->traits.get_assumed_state()) | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   if (this->lock_->traits.get_assumed_state()) { | ||||
|     root[MQTT_OPTIMISTIC] = true; | ||||
|   } | ||||
|   if (this->lock_->traits.get_supports_open()) | ||||
|     root[MQTT_PAYLOAD_OPEN] = "OPEN"; | ||||
| } | ||||
|   | ||||
| @@ -40,6 +40,7 @@ const EntityBase *MQTTNumberComponent::get_entity() const { return this->number_ | ||||
| void MQTTNumberComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   const auto &traits = number_->traits; | ||||
|   // https://www.home-assistant.io/integrations/number.mqtt/ | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   root[MQTT_MIN] = traits.get_min_value(); | ||||
|   root[MQTT_MAX] = traits.get_max_value(); | ||||
|   root[MQTT_STEP] = traits.get_step(); | ||||
|   | ||||
| @@ -35,7 +35,8 @@ const EntityBase *MQTTSelectComponent::get_entity() const { return this->select_ | ||||
| void MQTTSelectComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   const auto &traits = select_->traits; | ||||
|   // https://www.home-assistant.io/integrations/select.mqtt/ | ||||
|   JsonArray options = root.createNestedArray(MQTT_OPTIONS); | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   JsonArray options = root[MQTT_OPTIONS].to<JsonArray>(); | ||||
|   for (const auto &option : traits.get_options()) | ||||
|     options.add(option); | ||||
|  | ||||
|   | ||||
| @@ -44,8 +44,10 @@ void MQTTSensorComponent::set_expire_after(uint32_t expire_after) { this->expire | ||||
| void MQTTSensorComponent::disable_expire_after() { this->expire_after_ = 0; } | ||||
|  | ||||
| void MQTTSensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   if (!this->sensor_->get_device_class().empty()) | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   if (!this->sensor_->get_device_class().empty()) { | ||||
|     root[MQTT_DEVICE_CLASS] = this->sensor_->get_device_class(); | ||||
|   } | ||||
|  | ||||
|   if (!this->sensor_->get_unit_of_measurement().empty()) | ||||
|     root[MQTT_UNIT_OF_MEASUREMENT] = this->sensor_->get_unit_of_measurement(); | ||||
|   | ||||
| @@ -45,9 +45,11 @@ void MQTTSwitchComponent::dump_config() { | ||||
| std::string MQTTSwitchComponent::component_type() const { return "switch"; } | ||||
| const EntityBase *MQTTSwitchComponent::get_entity() const { return this->switch_; } | ||||
| void MQTTSwitchComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   if (this->switch_->assumed_state()) | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   if (this->switch_->assumed_state()) { | ||||
|     root[MQTT_OPTIMISTIC] = true; | ||||
|   } | ||||
| } | ||||
| bool MQTTSwitchComponent::send_initial_state() { return this->publish_state(this->switch_->state); } | ||||
|  | ||||
| bool MQTTSwitchComponent::publish_state(bool state) { | ||||
|   | ||||
| @@ -34,6 +34,7 @@ std::string MQTTTextComponent::component_type() const { return "text"; } | ||||
| const EntityBase *MQTTTextComponent::get_entity() const { return this->text_; } | ||||
|  | ||||
| void MQTTTextComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   switch (this->text_->traits.get_mode()) { | ||||
|     case TEXT_MODE_TEXT: | ||||
|       root[MQTT_MODE] = "text"; | ||||
|   | ||||
| @@ -15,8 +15,10 @@ using namespace esphome::text_sensor; | ||||
|  | ||||
| MQTTTextSensor::MQTTTextSensor(TextSensor *sensor) : sensor_(sensor) {} | ||||
| void MQTTTextSensor::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   if (!this->sensor_->get_device_class().empty()) | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   if (!this->sensor_->get_device_class().empty()) { | ||||
|     root[MQTT_DEVICE_CLASS] = this->sensor_->get_device_class(); | ||||
|   } | ||||
|   config.command_topic = false; | ||||
| } | ||||
| void MQTTTextSensor::setup() { | ||||
|   | ||||
| @@ -20,13 +20,13 @@ MQTTTimeComponent::MQTTTimeComponent(TimeEntity *time) : time_(time) {} | ||||
| void MQTTTimeComponent::setup() { | ||||
|   this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) { | ||||
|     auto call = this->time_->make_call(); | ||||
|     if (root.containsKey("hour")) { | ||||
|     if (root["hour"].is<uint8_t>()) { | ||||
|       call.set_hour(root["hour"]); | ||||
|     } | ||||
|     if (root.containsKey("minute")) { | ||||
|     if (root["minute"].is<uint8_t>()) { | ||||
|       call.set_minute(root["minute"]); | ||||
|     } | ||||
|     if (root.containsKey("second")) { | ||||
|     if (root["second"].is<uint8_t>()) { | ||||
|       call.set_second(root["second"]); | ||||
|     } | ||||
|     call.perform(); | ||||
| @@ -55,6 +55,7 @@ bool MQTTTimeComponent::send_initial_state() { | ||||
| } | ||||
| bool MQTTTimeComponent::publish_state(uint8_t hour, uint8_t minute, uint8_t second) { | ||||
|   return this->publish_json(this->get_state_topic_(), [hour, minute, second](JsonObject root) { | ||||
|     // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|     root["hour"] = hour; | ||||
|     root["minute"] = minute; | ||||
|     root["second"] = second; | ||||
|   | ||||
| @@ -41,6 +41,7 @@ bool MQTTUpdateComponent::publish_state() { | ||||
| } | ||||
|  | ||||
| void MQTTUpdateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   root["schema"] = "json"; | ||||
|   root[MQTT_PAYLOAD_INSTALL] = "INSTALL"; | ||||
| } | ||||
|   | ||||
| @@ -49,8 +49,10 @@ void MQTTValveComponent::dump_config() { | ||||
|   } | ||||
| } | ||||
| void MQTTValveComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||
|   if (!this->valve_->get_device_class().empty()) | ||||
|   // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   if (!this->valve_->get_device_class().empty()) { | ||||
|     root[MQTT_DEVICE_CLASS] = this->valve_->get_device_class(); | ||||
|   } | ||||
|  | ||||
|   auto traits = this->valve_->get_traits(); | ||||
|   if (traits.get_is_assumed_state()) { | ||||
|   | ||||
| @@ -792,7 +792,7 @@ std::string WebServer::light_json(light::LightState *obj, JsonDetail start_confi | ||||
|  | ||||
|     light::LightJSONSchema::dump_json(*obj, root); | ||||
|     if (start_config == DETAIL_ALL) { | ||||
|       JsonArray opt = root.createNestedArray("effects"); | ||||
|       JsonArray opt = root["effects"].to<JsonArray>(); | ||||
|       opt.add("None"); | ||||
|       for (auto const &option : obj->get_effects()) { | ||||
|         opt.add(option->get_name()); | ||||
| @@ -1238,7 +1238,7 @@ std::string WebServer::select_json(select::Select *obj, const std::string &value | ||||
|   return json::build_json([this, obj, value, start_config](JsonObject root) { | ||||
|     set_json_icon_state_value(root, obj, "select-" + obj->get_object_id(), value, value, start_config); | ||||
|     if (start_config == DETAIL_ALL) { | ||||
|       JsonArray opt = root.createNestedArray("option"); | ||||
|       JsonArray opt = root["option"].to<JsonArray>(); | ||||
|       for (auto &option : obj->traits.get_options()) { | ||||
|         opt.add(option); | ||||
|       } | ||||
| @@ -1322,6 +1322,7 @@ std::string WebServer::climate_all_json_generator(WebServer *web_server, void *s | ||||
|   return web_server->climate_json((climate::Climate *) (source), DETAIL_ALL); | ||||
| } | ||||
| std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_config) { | ||||
|   // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   return json::build_json([this, obj, start_config](JsonObject root) { | ||||
|     set_json_id(root, obj, "climate-" + obj->get_object_id(), start_config); | ||||
|     const auto traits = obj->get_traits(); | ||||
| @@ -1330,32 +1331,32 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf | ||||
|     char buf[16]; | ||||
|  | ||||
|     if (start_config == DETAIL_ALL) { | ||||
|       JsonArray opt = root.createNestedArray("modes"); | ||||
|       JsonArray opt = root["modes"].to<JsonArray>(); | ||||
|       for (climate::ClimateMode m : traits.get_supported_modes()) | ||||
|         opt.add(PSTR_LOCAL(climate::climate_mode_to_string(m))); | ||||
|       if (!traits.get_supported_custom_fan_modes().empty()) { | ||||
|         JsonArray opt = root.createNestedArray("fan_modes"); | ||||
|         JsonArray opt = root["fan_modes"].to<JsonArray>(); | ||||
|         for (climate::ClimateFanMode m : traits.get_supported_fan_modes()) | ||||
|           opt.add(PSTR_LOCAL(climate::climate_fan_mode_to_string(m))); | ||||
|       } | ||||
|  | ||||
|       if (!traits.get_supported_custom_fan_modes().empty()) { | ||||
|         JsonArray opt = root.createNestedArray("custom_fan_modes"); | ||||
|         JsonArray opt = root["custom_fan_modes"].to<JsonArray>(); | ||||
|         for (auto const &custom_fan_mode : traits.get_supported_custom_fan_modes()) | ||||
|           opt.add(custom_fan_mode); | ||||
|       } | ||||
|       if (traits.get_supports_swing_modes()) { | ||||
|         JsonArray opt = root.createNestedArray("swing_modes"); | ||||
|         JsonArray opt = root["swing_modes"].to<JsonArray>(); | ||||
|         for (auto swing_mode : traits.get_supported_swing_modes()) | ||||
|           opt.add(PSTR_LOCAL(climate::climate_swing_mode_to_string(swing_mode))); | ||||
|       } | ||||
|       if (traits.get_supports_presets() && obj->preset.has_value()) { | ||||
|         JsonArray opt = root.createNestedArray("presets"); | ||||
|         JsonArray opt = root["presets"].to<JsonArray>(); | ||||
|         for (climate::ClimatePreset m : traits.get_supported_presets()) | ||||
|           opt.add(PSTR_LOCAL(climate::climate_preset_to_string(m))); | ||||
|       } | ||||
|       if (!traits.get_supported_custom_presets().empty() && obj->custom_preset.has_value()) { | ||||
|         JsonArray opt = root.createNestedArray("custom_presets"); | ||||
|         JsonArray opt = root["custom_presets"].to<JsonArray>(); | ||||
|         for (auto const &custom_preset : traits.get_supported_custom_presets()) | ||||
|           opt.add(custom_preset); | ||||
|       } | ||||
| @@ -1407,6 +1408,7 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf | ||||
|         root["state"] = root["target_temperature"]; | ||||
|     } | ||||
|   }); | ||||
|   // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) | ||||
| } | ||||
| #endif | ||||
|  | ||||
| @@ -1635,7 +1637,7 @@ std::string WebServer::event_json(event::Event *obj, const std::string &event_ty | ||||
|       root["event_type"] = event_type; | ||||
|     } | ||||
|     if (start_config == DETAIL_ALL) { | ||||
|       JsonArray event_types = root.createNestedArray("event_types"); | ||||
|       JsonArray event_types = root["event_types"].to<JsonArray>(); | ||||
|       for (auto const &event_type : obj->get_event_types()) { | ||||
|         event_types.add(event_type); | ||||
|       } | ||||
| @@ -1682,6 +1684,7 @@ std::string WebServer::update_all_json_generator(WebServer *web_server, void *so | ||||
|   return web_server->update_json((update::UpdateEntity *) (source), DETAIL_STATE); | ||||
| } | ||||
| std::string WebServer::update_json(update::UpdateEntity *obj, JsonDetail start_config) { | ||||
|   // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson | ||||
|   return json::build_json([this, obj, start_config](JsonObject root) { | ||||
|     set_json_id(root, obj, "update-" + obj->get_object_id(), start_config); | ||||
|     root["value"] = obj->update_info.latest_version; | ||||
| @@ -1707,6 +1710,7 @@ std::string WebServer::update_json(update::UpdateEntity *obj, JsonDetail start_c | ||||
|       this->add_sorting_info_(root, obj); | ||||
|     } | ||||
|   }); | ||||
|   // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) | ||||
| } | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -35,7 +35,7 @@ build_flags = | ||||
| lib_deps = | ||||
|     esphome/noise-c@0.1.10                  ; api | ||||
|     improv/Improv@1.2.4                    ; improv_serial / esp32_improv | ||||
|     bblanchon/ArduinoJson@6.18.5           ; json | ||||
|     bblanchon/ArduinoJson@7.4.2            ; json | ||||
|     wjtje/qr-code-generator-library@1.7.0  ; qr_code | ||||
|     functionpointer/arduino-MLX90393@1.0.2 ; mlx90393 | ||||
|     pavlodn/HaierProtocol@0.9.31           ; haier | ||||
|   | ||||
		Reference in New Issue
	
	Block a user