Merge branch 'dev' into light-gamma-lut

This commit is contained in:
J. Nick Koston
2026-02-19 15:21:41 -06:00
committed by GitHub
20 changed files with 436 additions and 333 deletions
+2 -2
View File
@@ -264,9 +264,9 @@ template<typename... Ts> class APIRespondAction : public Action<Ts...> {
// Build and send JSON response
json::JsonBuilder builder;
this->json_builder_(x..., builder.root());
std::string json_str = builder.serialize();
auto json_buf = builder.serialize();
this->parent_->send_action_response(call_id, success, StringRef(error_message),
reinterpret_cast<const uint8_t *>(json_str.data()), json_str.size());
reinterpret_cast<const uint8_t *>(json_buf.data()), json_buf.size());
return;
}
#endif
@@ -85,6 +85,10 @@ esp_err_t AudioDecoder::start(AudioFileType audio_file_type) {
#ifdef USE_AUDIO_FLAC_SUPPORT
case AudioFileType::FLAC:
this->flac_decoder_ = make_unique<esp_audio_libs::flac::FLACDecoder>();
// CRC check slows down decoding by 15-20% on an ESP32-S3. FLAC sources in ESPHome are either from an http source
// or built into the firmware, so the data integrity is already verified by the time it gets to the decoder,
// making the CRC check unnecessary.
this->flac_decoder_->set_crc_check_enabled(false);
this->free_buffer_required_ =
this->output_transfer_buffer_->capacity(); // Adjusted and reallocated after reading the header
break;
+14 -54
View File
@@ -25,7 +25,6 @@ from esphome.const import (
CONF_PLATFORM_VERSION,
CONF_PLATFORMIO_OPTIONS,
CONF_REF,
CONF_REFRESH,
CONF_SAFE_MODE,
CONF_SOURCE,
CONF_TYPE,
@@ -41,7 +40,7 @@ from esphome.const import (
ThreadModel,
__version__,
)
from esphome.core import CORE, HexInt, TimePeriod
from esphome.core import CORE, HexInt
from esphome.coroutine import CoroPriority, coroutine_with_priority
import esphome.final_validate as fv
from esphome.helpers import copy_file_if_changed, rmtree, write_file_if_changed
@@ -499,49 +498,24 @@ def add_idf_component(
repo: str | None = None,
ref: str | None = None,
path: str | None = None,
refresh: TimePeriod | None = None,
components: list[str] | None = None,
submodules: list[str] | None = None,
):
"""Add an esp-idf component to the project."""
if not repo and not ref and not path:
raise ValueError("Requires at least one of repo, ref or path")
if refresh or submodules or components:
_LOGGER.warning(
"The refresh, components and submodules parameters in add_idf_component() are "
"deprecated and will be removed in ESPHome 2026.1. If you are seeing this, report "
"an issue to the external_component author and ask them to update it."
)
components_registry = CORE.data[KEY_ESP32][KEY_COMPONENTS]
if components:
for comp in components:
existing = components_registry.get(comp)
if existing and existing.get(KEY_REF) != ref:
_LOGGER.warning(
"IDF component %s version conflict %s replaced by %s",
comp,
existing.get(KEY_REF),
ref,
)
components_registry[comp] = {
KEY_REPO: repo,
KEY_REF: ref,
KEY_PATH: f"{path}/{comp}" if path else comp,
}
else:
existing = components_registry.get(name)
if existing and existing.get(KEY_REF) != ref:
_LOGGER.warning(
"IDF component %s version conflict %s replaced by %s",
name,
existing.get(KEY_REF),
ref,
)
components_registry[name] = {
KEY_REPO: repo,
KEY_REF: ref,
KEY_PATH: path,
}
existing = components_registry.get(name)
if existing and existing.get(KEY_REF) != ref:
_LOGGER.warning(
"IDF component %s version conflict %s replaced by %s",
name,
existing.get(KEY_REF),
ref,
)
components_registry[name] = {
KEY_REPO: repo,
KEY_REF: ref,
KEY_PATH: path,
}
def exclude_builtin_idf_component(name: str) -> None:
@@ -1037,16 +1011,6 @@ def _parse_idf_component(value: str) -> ConfigType:
)
def _validate_idf_component(config: ConfigType) -> ConfigType:
"""Validate IDF component config and warn about deprecated options."""
if CONF_REFRESH in config:
_LOGGER.warning(
"The 'refresh' option for IDF components is deprecated and has no effect. "
"It will be removed in ESPHome 2026.1. Please remove it from your configuration."
)
return config
FRAMEWORK_ESP_IDF = "esp-idf"
FRAMEWORK_ARDUINO = "arduino"
FRAMEWORK_SCHEMA = cv.Schema(
@@ -1135,13 +1099,9 @@ FRAMEWORK_SCHEMA = cv.Schema(
cv.Optional(CONF_SOURCE): cv.git_ref,
cv.Optional(CONF_REF): cv.string,
cv.Optional(CONF_PATH): cv.string,
cv.Optional(CONF_REFRESH): cv.All(
cv.string, cv.source_refresh
),
}
),
),
_validate_idf_component,
)
),
}
+10
View File
@@ -9,6 +9,7 @@ from esphome import automation
import esphome.codegen as cg
from esphome.components import socket
from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant
from esphome.components.esp32.const import VARIANT_ESP32C2
import esphome.config_validation as cv
from esphome.const import (
CONF_ENABLE_ON_BOOT,
@@ -387,6 +388,15 @@ def final_validation(config):
f"Name '{name}' is too long, maximum length is {max_length} characters"
)
# ESP32-C2 has very limited RAM (~272KB). Without releasing BLE IRAM,
# esp_bt_controller_init fails with ESP_ERR_NO_MEM.
# CONFIG_BT_RELEASE_IRAM changes the memory layout so IRAM and DRAM share
# space more flexibly, giving the BT controller enough contiguous memory.
# This requires CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT to be disabled.
if get_esp32_variant() == VARIANT_ESP32C2:
add_idf_sdkconfig_option("CONFIG_BT_RELEASE_IRAM", True)
add_idf_sdkconfig_option("CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT", False)
# Set GATT Client/Server sdkconfig options based on which components are loaded
full_config = fv.full_config.get()
+11 -4
View File
@@ -218,12 +218,19 @@ def _validate(config):
)
elif config[CONF_TYPE] != "OPENETH":
if CONF_CLK_MODE in config:
mode, pin = CLK_MODES_DEPRECATED[config[CONF_CLK_MODE]]
LOGGER.warning(
"[ethernet] The 'clk_mode' option is deprecated and will be removed in ESPHome 2026.1. "
"Please update your configuration to use 'clk' instead."
"[ethernet] The 'clk_mode' option is deprecated. "
"Please replace 'clk_mode: %s' with:\n"
" clk:\n"
" mode: %s\n"
" pin: %s\n"
"Removal scheduled for 2026.7.0.",
config[CONF_CLK_MODE],
mode,
pin,
)
mode = CLK_MODES_DEPRECATED[config[CONF_CLK_MODE]]
config[CONF_CLK] = CLK_SCHEMA({CONF_MODE: mode[0], CONF_PIN: mode[1]})
config[CONF_CLK] = CLK_SCHEMA({CONF_MODE: mode, CONF_PIN: pin})
del config[CONF_CLK_MODE]
elif CONF_CLK not in config:
raise cv.Invalid("'clk' is a required option for [ethernet].")
-31
View File
@@ -267,37 +267,6 @@ class I2CDevice {
bool write_byte_16(uint8_t a_register, uint16_t data) const { return write_bytes_16(a_register, &data, 1); }
// Deprecated functions
ESPDEPRECATED("The stop argument is no longer used. This will be removed from ESPHome 2026.3.0", "2025.9.0")
ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len, bool stop) {
return this->read_register(a_register, data, len);
}
ESPDEPRECATED("The stop argument is no longer used. This will be removed from ESPHome 2026.3.0", "2025.9.0")
ErrorCode read_register16(uint16_t a_register, uint8_t *data, size_t len, bool stop) {
return this->read_register16(a_register, data, len);
}
ESPDEPRECATED("The stop argument is no longer used; use write_read() for consecutive write and read. This will be "
"removed from ESPHome 2026.3.0",
"2025.9.0")
ErrorCode write(const uint8_t *data, size_t len, bool stop) const { return this->write(data, len); }
ESPDEPRECATED("The stop argument is no longer used; use write_read() for consecutive write and read. This will be "
"removed from ESPHome 2026.3.0",
"2025.9.0")
ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len, bool stop) const {
return this->write_register(a_register, data, len);
}
ESPDEPRECATED("The stop argument is no longer used; use write_read() for consecutive write and read. This will be "
"removed from ESPHome 2026.3.0",
"2025.9.0")
ErrorCode write_register16(uint16_t a_register, const uint8_t *data, size_t len, bool stop) const {
return this->write_register16(a_register, data, len);
}
protected:
uint8_t address_{0x00}; ///< store the address of the device on the bus
I2CBus *bus_{nullptr}; ///< pointer to I2CBus instance
-58
View File
@@ -1,8 +1,6 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <utility>
#include <vector>
@@ -24,18 +22,6 @@ enum ErrorCode {
ERROR_CRC = 7, ///< bytes received with a CRC error
};
/// @brief the ReadBuffer structure stores a pointer to a read buffer and its length
struct ReadBuffer {
uint8_t *data; ///< pointer to the read buffer
size_t len; ///< length of the buffer
};
/// @brief the WriteBuffer structure stores a pointer to a write buffer and its length
struct WriteBuffer {
const uint8_t *data; ///< pointer to the write buffer
size_t len; ///< length of the buffer
};
/// @brief This Class provides the methods to read and write bytes from an I2CBus.
/// @note The I2CBus virtual class follows a *Factory design pattern* that provides all the interfaces methods required
/// by clients while deferring the actual implementation of these methods to a subclasses. I2C-bus specification and
@@ -68,50 +54,6 @@ class I2CBus {
return this->write_readv(address, buffer, len, nullptr, 0);
}
ESPDEPRECATED("This method is deprecated and will be removed in ESPHome 2026.3.0. Use write_readv() instead.",
"2025.9.0")
ErrorCode readv(uint8_t address, ReadBuffer *read_buffers, size_t count) {
size_t total_len = 0;
for (size_t i = 0; i != count; i++) {
total_len += read_buffers[i].len;
}
SmallBufferWithHeapFallback<128> buffer_alloc(total_len); // Most I2C reads are small
uint8_t *buffer = buffer_alloc.get();
auto err = this->write_readv(address, nullptr, 0, buffer, total_len);
if (err != ERROR_OK)
return err;
size_t pos = 0;
for (size_t i = 0; i != count; i++) {
if (read_buffers[i].len != 0) {
std::memcpy(read_buffers[i].data, buffer + pos, read_buffers[i].len);
pos += read_buffers[i].len;
}
}
return ERROR_OK;
}
ESPDEPRECATED("This method is deprecated and will be removed in ESPHome 2026.3.0. Use write_readv() instead.",
"2025.9.0")
ErrorCode writev(uint8_t address, const WriteBuffer *write_buffers, size_t count, bool stop = true) {
size_t total_len = 0;
for (size_t i = 0; i != count; i++) {
total_len += write_buffers[i].len;
}
SmallBufferWithHeapFallback<128> buffer_alloc(total_len); // Most I2C writes are small
uint8_t *buffer = buffer_alloc.get();
size_t pos = 0;
for (size_t i = 0; i != count; i++) {
std::memcpy(buffer + pos, write_buffers[i].data, write_buffers[i].len);
pos += write_buffers[i].len;
}
return this->write_readv(address, buffer, total_len, nullptr, 0);
}
protected:
/// @brief Scans the I2C bus for devices. Devices presence is kept in an array of std::pair
/// that contains the address and the corresponding bool presence flag.
+75 -6
View File
@@ -15,7 +15,7 @@ static const char *const TAG = "json";
static SpiRamAllocator global_json_allocator;
#endif
std::string build_json(const json_build_t &f) {
SerializationBuffer<> build_json(const json_build_t &f) {
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
JsonBuilder builder;
JsonObject root = builder.root();
@@ -66,14 +66,83 @@ JsonDocument parse_json(const uint8_t *data, size_t len) {
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
}
std::string JsonBuilder::serialize() {
SerializationBuffer<> JsonBuilder::serialize() {
// ===========================================================================================
// CRITICAL: NRVO (Named Return Value Optimization) - DO NOT REFACTOR WITHOUT UNDERSTANDING
// ===========================================================================================
//
// This function is carefully structured to enable NRVO. The compiler constructs `result`
// directly in the caller's stack frame, eliminating the move constructor call entirely.
//
// WITHOUT NRVO: Each return would trigger SerializationBuffer's move constructor, which
// must memcpy up to 512 bytes of stack buffer content. This happens on EVERY JSON
// serialization (sensor updates, web server responses, MQTT publishes, etc.).
//
// WITH NRVO: Zero memcpy, zero move constructor overhead. The buffer lives directly
// where the caller needs it.
//
// Requirements for NRVO to work:
// 1. Single named variable (`result`) returned from ALL paths
// 2. All paths must return the SAME variable (not different variables)
// 3. No std::move() on the return statement
//
// If you must modify this function:
// - Keep a single `result` variable declared at the top
// - All code paths must return `result` (not a different variable)
// - Verify NRVO still works by checking the disassembly for move constructor calls
// - Test: objdump -d -C firmware.elf | grep "SerializationBuffer.*SerializationBuffer"
// Should show only destructor, NOT move constructor
//
// Try stack buffer first. 640 bytes covers 99.9% of JSON payloads (sensors ~200B,
// lights ~170B, climate ~500-700B). Only entities with 40+ options exceed this.
//
// IMPORTANT: ArduinoJson's serializeJson() with a bounded buffer returns the actual
// bytes written (truncated count), NOT the would-be size like snprintf(). When the
// payload exceeds the buffer, the return value equals the buffer capacity. The heap
// fallback doubles the buffer size until the payload fits. This avoids instantiating
// measureJson()'s DummyWriter templates (~736 bytes flash) at the cost of temporarily
// over-allocating heap (at most 2x) for the rare payloads that exceed 640 bytes.
//
// ===========================================================================================
constexpr size_t buf_size = SerializationBuffer<>::BUFFER_SIZE;
SerializationBuffer<> result(buf_size - 1); // Max content size (reserve 1 for null)
if (doc_.overflowed()) {
ESP_LOGE(TAG, "JSON document overflow");
return "{}";
auto *buf = result.data_writable_();
buf[0] = '{';
buf[1] = '}';
buf[2] = '\0';
result.set_size_(2);
return result;
}
std::string output;
serializeJson(doc_, output);
return output;
size_t size = serializeJson(doc_, result.data_writable_(), buf_size);
if (size < buf_size) {
// Fits in stack buffer - update size to actual length
result.set_size_(size);
return result;
}
// Payload exceeded stack buffer. Double the buffer and retry until it fits.
// In practice, one iteration (1024 bytes) covers all known entity types.
// Payloads exceeding 1024 bytes are not known to exist in real configurations.
// Cap at 5120 as a safety limit to prevent runaway allocation.
constexpr size_t max_heap_size = 5120;
size_t heap_size = buf_size * 2;
while (heap_size <= max_heap_size) {
result.reallocate_heap_(heap_size - 1);
size = serializeJson(doc_, result.data_writable_(), heap_size);
if (size < heap_size) {
result.set_size_(size);
return result;
}
heap_size *= 2;
}
// Payload exceeds 5120 bytes - return truncated result
ESP_LOGW(TAG, "JSON payload too large, truncated to %zu bytes", size);
result.set_size_(size);
return result;
}
} // namespace json
+109 -2
View File
@@ -1,5 +1,7 @@
#pragma once
#include <cstring>
#include <string>
#include <vector>
#include "esphome/core/defines.h"
@@ -14,6 +16,108 @@
namespace esphome {
namespace json {
/// Buffer for JSON serialization that uses stack allocation for small payloads.
/// Template parameter STACK_SIZE specifies the stack buffer size (default 512 bytes).
/// Supports move semantics for efficient return-by-value.
template<size_t STACK_SIZE = 640> class SerializationBuffer {
public:
static constexpr size_t BUFFER_SIZE = STACK_SIZE; ///< Stack buffer size for this instantiation
/// Construct with known size (typically from measureJson)
explicit SerializationBuffer(size_t size) : size_(size) {
if (size + 1 <= STACK_SIZE) {
buffer_ = stack_buffer_;
} else {
heap_buffer_ = new char[size + 1];
buffer_ = heap_buffer_;
}
buffer_[0] = '\0';
}
~SerializationBuffer() { delete[] heap_buffer_; }
// Move constructor - works with same template instantiation
SerializationBuffer(SerializationBuffer &&other) noexcept : heap_buffer_(other.heap_buffer_), size_(other.size_) {
if (other.buffer_ == other.stack_buffer_) {
// Stack buffer - must copy content
std::memcpy(stack_buffer_, other.stack_buffer_, size_ + 1);
buffer_ = stack_buffer_;
} else {
// Heap buffer - steal ownership
buffer_ = heap_buffer_;
other.heap_buffer_ = nullptr;
}
// Leave moved-from object in valid empty state
other.stack_buffer_[0] = '\0';
other.buffer_ = other.stack_buffer_;
other.size_ = 0;
}
// Move assignment
SerializationBuffer &operator=(SerializationBuffer &&other) noexcept {
if (this != &other) {
delete[] heap_buffer_;
heap_buffer_ = other.heap_buffer_;
size_ = other.size_;
if (other.buffer_ == other.stack_buffer_) {
std::memcpy(stack_buffer_, other.stack_buffer_, size_ + 1);
buffer_ = stack_buffer_;
} else {
buffer_ = heap_buffer_;
other.heap_buffer_ = nullptr;
}
// Leave moved-from object in valid empty state
other.stack_buffer_[0] = '\0';
other.buffer_ = other.stack_buffer_;
other.size_ = 0;
}
return *this;
}
// Delete copy operations
SerializationBuffer(const SerializationBuffer &) = delete;
SerializationBuffer &operator=(const SerializationBuffer &) = delete;
/// Get null-terminated C string
const char *c_str() const { return buffer_; }
/// Get data pointer
const char *data() const { return buffer_; }
/// Get string length (excluding null terminator)
size_t size() const { return size_; }
/// Implicit conversion to std::string for backward compatibility
/// WARNING: This allocates a new std::string on the heap. Prefer using
/// c_str() or data()/size() directly when possible to avoid allocation.
operator std::string() const { return std::string(buffer_, size_); } // NOLINT(google-explicit-constructor)
private:
friend class JsonBuilder; ///< Allows JsonBuilder::serialize() to call private methods
/// Get writable buffer (for serialization)
char *data_writable_() { return buffer_; }
/// Set actual size after serialization (must not exceed allocated size)
/// Also ensures null termination for c_str() safety
void set_size_(size_t size) {
size_ = size;
buffer_[size] = '\0';
}
/// Reallocate to heap buffer with new size (for when stack buffer is too small)
/// This invalidates any previous buffer content. Used by JsonBuilder::serialize().
void reallocate_heap_(size_t size) {
delete[] heap_buffer_;
heap_buffer_ = new char[size + 1];
buffer_ = heap_buffer_;
size_ = size;
buffer_[0] = '\0';
}
char stack_buffer_[STACK_SIZE];
char *heap_buffer_{nullptr};
char *buffer_;
size_t size_;
};
#ifdef USE_PSRAM
// Build an allocator for the JSON Library using the RAMAllocator class
// This is only compiled when PSRAM is enabled
@@ -47,7 +151,8 @@ using json_parse_t = std::function<bool(JsonObject)>;
using json_build_t = std::function<void(JsonObject)>;
/// Build a JSON string with the provided json build function.
std::string build_json(const json_build_t &f);
/// Returns SerializationBuffer for stack-first allocation; implicitly converts to std::string.
SerializationBuffer<> build_json(const json_build_t &f);
/// Parse a JSON string and run the provided json parse function if it's valid.
bool parse_json(const std::string &data, const json_parse_t &f);
@@ -72,7 +177,9 @@ class JsonBuilder {
return root_;
}
std::string serialize();
/// Serialize the JSON document to a SerializationBuffer (stack-first allocation)
/// Uses 512-byte stack buffer by default, falls back to heap for larger JSON
SerializationBuffer<> serialize();
private:
#ifdef USE_PSRAM
+2 -2
View File
@@ -543,8 +543,8 @@ bool MQTTClientComponent::publish(const char *topic, const char *payload, size_t
}
bool MQTTClientComponent::publish_json(const char *topic, const json::json_build_t &f, uint8_t qos, bool retain) {
std::string message = json::build_json(f);
return this->publish(topic, message.c_str(), message.length(), qos, retain);
auto message = json::build_json(f);
return this->publish(topic, message.c_str(), message.size(), qos, retain);
}
void MQTTClientComponent::enable() {
@@ -8,10 +8,10 @@
#if defined(USE_ESP32)
#include <soc/soc_caps.h>
#ifdef SOC_PCNT_SUPPORTED
#if defined(SOC_PCNT_SUPPORTED) && __has_include(<driver/pulse_cnt.h>)
#include <driver/pulse_cnt.h>
#define HAS_PCNT
#endif // SOC_PCNT_SUPPORTED
#endif // defined(SOC_PCNT_SUPPORTED) && __has_include(<driver/pulse_cnt.h>)
#endif // USE_ESP32
namespace esphome {
@@ -11,6 +11,7 @@
#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK)
#include <esp_ota_ops.h>
#include <esp_system.h>
#endif
namespace esphome::safe_mode {
@@ -54,6 +55,10 @@ void SafeModeComponent::dump_config() {
"OTA rollback detected! Rolled back from partition '%s'\n"
"The device reset before the boot was marked successful",
last_invalid->label);
if (esp_reset_reason() == ESP_RST_BROWNOUT) {
ESP_LOGW(TAG, "Last reset was due to brownout - check your power supply!\n"
"See https://esphome.io/guides/faq.html#brownout-detector-was-triggered");
}
}
#endif
}
+96 -95
View File
@@ -214,7 +214,7 @@ DeferredUpdateEventSource::deq_push_back_with_dedup_(void *source, message_gener
void DeferredUpdateEventSource::process_deferred_queue_() {
while (!deferred_queue_.empty()) {
DeferredEvent &de = deferred_queue_.front();
std::string message = de.message_generator_(web_server_, de.source_);
auto message = de.message_generator_(web_server_, de.source_);
if (this->send(message.c_str(), "state") != DISCARDED) {
// O(n) but memory efficiency is more important than speed here which is why std::vector was chosen
deferred_queue_.erase(deferred_queue_.begin());
@@ -271,7 +271,7 @@ void DeferredUpdateEventSource::deferrable_send_state(void *source, const char *
// deferred queue still not empty which means downstream event queue full, no point trying to send first
deq_push_back_with_dedup_(source, message_generator);
} else {
std::string message = message_generator(web_server_, source);
auto message = message_generator(web_server_, source);
if (this->send(message.c_str(), "state") == DISCARDED) {
deq_push_back_with_dedup_(source, message_generator);
} else {
@@ -325,7 +325,7 @@ void DeferredUpdateEventSourceList::on_client_connect_(DeferredUpdateEventSource
ws->defer([ws, source]() {
// Configure reconnect timeout and send config
// this should always go through since the AsyncEventSourceClient event queue is empty on connect
std::string message = ws->get_config_json();
auto message = ws->get_config_json();
source->try_send_nodefer(message.c_str(), "ping", millis(), 30000);
#ifdef USE_WEBSERVER_SORTING
@@ -334,10 +334,10 @@ void DeferredUpdateEventSourceList::on_client_connect_(DeferredUpdateEventSource
JsonObject root = builder.root();
root[ESPHOME_F("name")] = group.second.name;
root[ESPHOME_F("sorting_weight")] = group.second.weight;
message = builder.serialize();
auto group_msg = builder.serialize();
// up to 31 groups should be able to be queued initially without defer
source->try_send_nodefer(message.c_str(), "sorting_group");
source->try_send_nodefer(group_msg.c_str(), "sorting_group");
}
#endif
@@ -370,7 +370,7 @@ void WebServer::set_css_include(const char *css_include) { this->css_include_ =
void WebServer::set_js_include(const char *js_include) { this->js_include_ = js_include; }
#endif
std::string WebServer::get_config_json() {
json::SerializationBuffer<> WebServer::get_config_json() {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -606,20 +606,20 @@ void WebServer::handle_sensor_request(AsyncWebServerRequest *request, const UrlM
// Note: request->method() is always HTTP_GET here (canHandle ensures this)
if (entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->sensor_json_(obj, obj->state, detail);
auto data = this->sensor_json_(obj, obj->state, detail);
request->send(200, "application/json", data.c_str());
return;
}
}
request->send(404);
}
std::string WebServer::sensor_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::sensor_state_json_generator(WebServer *web_server, void *source) {
return web_server->sensor_json_((sensor::Sensor *) (source), ((sensor::Sensor *) (source))->state, DETAIL_STATE);
}
std::string WebServer::sensor_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::sensor_all_json_generator(WebServer *web_server, void *source) {
return web_server->sensor_json_((sensor::Sensor *) (source), ((sensor::Sensor *) (source))->state, DETAIL_ALL);
}
std::string WebServer::sensor_json_(sensor::Sensor *obj, float value, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::sensor_json_(sensor::Sensor *obj, float value, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -653,23 +653,23 @@ void WebServer::handle_text_sensor_request(AsyncWebServerRequest *request, const
// Note: request->method() is always HTTP_GET here (canHandle ensures this)
if (entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->text_sensor_json_(obj, obj->state, detail);
auto data = this->text_sensor_json_(obj, obj->state, detail);
request->send(200, "application/json", data.c_str());
return;
}
}
request->send(404);
}
std::string WebServer::text_sensor_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::text_sensor_state_json_generator(WebServer *web_server, void *source) {
return web_server->text_sensor_json_((text_sensor::TextSensor *) (source),
((text_sensor::TextSensor *) (source))->state, DETAIL_STATE);
}
std::string WebServer::text_sensor_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::text_sensor_all_json_generator(WebServer *web_server, void *source) {
return web_server->text_sensor_json_((text_sensor::TextSensor *) (source),
((text_sensor::TextSensor *) (source))->state, DETAIL_ALL);
}
std::string WebServer::text_sensor_json_(text_sensor::TextSensor *obj, const std::string &value,
JsonDetail start_config) {
json::SerializationBuffer<> WebServer::text_sensor_json_(text_sensor::TextSensor *obj, const std::string &value,
JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -714,7 +714,7 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->switch_json_(obj, obj->state, detail);
auto data = this->switch_json_(obj, obj->state, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -739,13 +739,13 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM
}
request->send(404);
}
std::string WebServer::switch_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::switch_state_json_generator(WebServer *web_server, void *source) {
return web_server->switch_json_((switch_::Switch *) (source), ((switch_::Switch *) (source))->state, DETAIL_STATE);
}
std::string WebServer::switch_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::switch_all_json_generator(WebServer *web_server, void *source) {
return web_server->switch_json_((switch_::Switch *) (source), ((switch_::Switch *) (source))->state, DETAIL_ALL);
}
std::string WebServer::switch_json_(switch_::Switch *obj, bool value, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::switch_json_(switch_::Switch *obj, bool value, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -767,7 +767,7 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM
continue;
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->button_json_(obj, detail);
auto data = this->button_json_(obj, detail);
request->send(200, "application/json", data.c_str());
} else if (match.method_equals(ESPHOME_F("press"))) {
DEFER_ACTION(obj, obj->press());
@@ -780,10 +780,10 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM
}
request->send(404);
}
std::string WebServer::button_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::button_all_json_generator(WebServer *web_server, void *source) {
return web_server->button_json_((button::Button *) (source), DETAIL_ALL);
}
std::string WebServer::button_json_(button::Button *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::button_json_(button::Button *obj, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -810,22 +810,23 @@ void WebServer::handle_binary_sensor_request(AsyncWebServerRequest *request, con
// Note: request->method() is always HTTP_GET here (canHandle ensures this)
if (entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->binary_sensor_json_(obj, obj->state, detail);
auto data = this->binary_sensor_json_(obj, obj->state, detail);
request->send(200, "application/json", data.c_str());
return;
}
}
request->send(404);
}
std::string WebServer::binary_sensor_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::binary_sensor_state_json_generator(WebServer *web_server, void *source) {
return web_server->binary_sensor_json_((binary_sensor::BinarySensor *) (source),
((binary_sensor::BinarySensor *) (source))->state, DETAIL_STATE);
}
std::string WebServer::binary_sensor_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::binary_sensor_all_json_generator(WebServer *web_server, void *source) {
return web_server->binary_sensor_json_((binary_sensor::BinarySensor *) (source),
((binary_sensor::BinarySensor *) (source))->state, DETAIL_ALL);
}
std::string WebServer::binary_sensor_json_(binary_sensor::BinarySensor *obj, bool value, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::binary_sensor_json_(binary_sensor::BinarySensor *obj, bool value,
JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -852,7 +853,7 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->fan_json_(obj, detail);
auto data = this->fan_json_(obj, detail);
request->send(200, "application/json", data.c_str());
} else if (match.method_equals(ESPHOME_F("toggle"))) {
DEFER_ACTION(obj, obj->toggle().perform());
@@ -893,13 +894,13 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc
}
request->send(404);
}
std::string WebServer::fan_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::fan_state_json_generator(WebServer *web_server, void *source) {
return web_server->fan_json_((fan::Fan *) (source), DETAIL_STATE);
}
std::string WebServer::fan_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::fan_all_json_generator(WebServer *web_server, void *source) {
return web_server->fan_json_((fan::Fan *) (source), DETAIL_ALL);
}
std::string WebServer::fan_json_(fan::Fan *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::fan_json_(fan::Fan *obj, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -933,7 +934,7 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->light_json_(obj, detail);
auto data = this->light_json_(obj, detail);
request->send(200, "application/json", data.c_str());
} else if (match.method_equals(ESPHOME_F("toggle"))) {
DEFER_ACTION(obj, obj->toggle().perform());
@@ -972,13 +973,13 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa
}
request->send(404);
}
std::string WebServer::light_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::light_state_json_generator(WebServer *web_server, void *source) {
return web_server->light_json_((light::LightState *) (source), DETAIL_STATE);
}
std::string WebServer::light_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::light_all_json_generator(WebServer *web_server, void *source) {
return web_server->light_json_((light::LightState *) (source), DETAIL_ALL);
}
std::string WebServer::light_json_(light::LightState *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::light_json_(light::LightState *obj, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1012,7 +1013,7 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->cover_json_(obj, detail);
auto data = this->cover_json_(obj, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1060,13 +1061,13 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa
}
request->send(404);
}
std::string WebServer::cover_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::cover_state_json_generator(WebServer *web_server, void *source) {
return web_server->cover_json_((cover::Cover *) (source), DETAIL_STATE);
}
std::string WebServer::cover_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::cover_all_json_generator(WebServer *web_server, void *source) {
return web_server->cover_json_((cover::Cover *) (source), DETAIL_ALL);
}
std::string WebServer::cover_json_(cover::Cover *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::cover_json_(cover::Cover *obj, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1101,7 +1102,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->number_json_(obj, obj->state, detail);
auto data = this->number_json_(obj, obj->state, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1120,13 +1121,13 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM
request->send(404);
}
std::string WebServer::number_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::number_state_json_generator(WebServer *web_server, void *source) {
return web_server->number_json_((number::Number *) (source), ((number::Number *) (source))->state, DETAIL_STATE);
}
std::string WebServer::number_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::number_all_json_generator(WebServer *web_server, void *source) {
return web_server->number_json_((number::Number *) (source), ((number::Number *) (source))->state, DETAIL_ALL);
}
std::string WebServer::number_json_(number::Number *obj, float value, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::number_json_(number::Number *obj, float value, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1168,7 +1169,7 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat
continue;
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->date_json_(obj, detail);
auto data = this->date_json_(obj, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1194,13 +1195,13 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat
request->send(404);
}
std::string WebServer::date_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::date_state_json_generator(WebServer *web_server, void *source) {
return web_server->date_json_((datetime::DateEntity *) (source), DETAIL_STATE);
}
std::string WebServer::date_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::date_all_json_generator(WebServer *web_server, void *source) {
return web_server->date_json_((datetime::DateEntity *) (source), DETAIL_ALL);
}
std::string WebServer::date_json_(datetime::DateEntity *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::date_json_(datetime::DateEntity *obj, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1229,7 +1230,7 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat
continue;
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->time_json_(obj, detail);
auto data = this->time_json_(obj, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1254,13 +1255,13 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat
}
request->send(404);
}
std::string WebServer::time_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::time_state_json_generator(WebServer *web_server, void *source) {
return web_server->time_json_((datetime::TimeEntity *) (source), DETAIL_STATE);
}
std::string WebServer::time_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::time_all_json_generator(WebServer *web_server, void *source) {
return web_server->time_json_((datetime::TimeEntity *) (source), DETAIL_ALL);
}
std::string WebServer::time_json_(datetime::TimeEntity *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::time_json_(datetime::TimeEntity *obj, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1289,7 +1290,7 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur
continue;
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->datetime_json_(obj, detail);
auto data = this->datetime_json_(obj, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1314,13 +1315,13 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur
}
request->send(404);
}
std::string WebServer::datetime_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::datetime_state_json_generator(WebServer *web_server, void *source) {
return web_server->datetime_json_((datetime::DateTimeEntity *) (source), DETAIL_STATE);
}
std::string WebServer::datetime_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::datetime_all_json_generator(WebServer *web_server, void *source) {
return web_server->datetime_json_((datetime::DateTimeEntity *) (source), DETAIL_ALL);
}
std::string WebServer::datetime_json_(datetime::DateTimeEntity *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::datetime_json_(datetime::DateTimeEntity *obj, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1351,7 +1352,7 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->text_json_(obj, obj->state, detail);
auto data = this->text_json_(obj, obj->state, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1370,13 +1371,13 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat
request->send(404);
}
std::string WebServer::text_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::text_state_json_generator(WebServer *web_server, void *source) {
return web_server->text_json_((text::Text *) (source), ((text::Text *) (source))->state, DETAIL_STATE);
}
std::string WebServer::text_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::text_all_json_generator(WebServer *web_server, void *source) {
return web_server->text_json_((text::Text *) (source), ((text::Text *) (source))->state, DETAIL_ALL);
}
std::string WebServer::text_json_(text::Text *obj, const std::string &value, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::text_json_(text::Text *obj, const std::string &value, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1408,7 +1409,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), detail);
auto data = this->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1427,15 +1428,15 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM
}
request->send(404);
}
std::string WebServer::select_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::select_state_json_generator(WebServer *web_server, void *source) {
auto *obj = (select::Select *) (source);
return web_server->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), DETAIL_STATE);
}
std::string WebServer::select_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::select_all_json_generator(WebServer *web_server, void *source) {
auto *obj = (select::Select *) (source);
return web_server->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), DETAIL_ALL);
}
std::string WebServer::select_json_(select::Select *obj, StringRef value, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::select_json_(select::Select *obj, StringRef value, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1467,7 +1468,7 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->climate_json_(obj, detail);
auto data = this->climate_json_(obj, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1500,15 +1501,15 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url
}
request->send(404);
}
std::string WebServer::climate_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::climate_state_json_generator(WebServer *web_server, void *source) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
return web_server->climate_json_((climate::Climate *) (source), DETAIL_STATE);
}
std::string WebServer::climate_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::climate_all_json_generator(WebServer *web_server, void *source) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
return web_server->climate_json_((climate::Climate *) (source), DETAIL_ALL);
}
std::string WebServer::climate_json_(climate::Climate *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::climate_json_(climate::Climate *obj, JsonDetail start_config) {
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1641,7 +1642,7 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->lock_json_(obj, obj->state, detail);
auto data = this->lock_json_(obj, obj->state, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1666,13 +1667,13 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat
}
request->send(404);
}
std::string WebServer::lock_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::lock_state_json_generator(WebServer *web_server, void *source) {
return web_server->lock_json_((lock::Lock *) (source), ((lock::Lock *) (source))->state, DETAIL_STATE);
}
std::string WebServer::lock_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::lock_all_json_generator(WebServer *web_server, void *source) {
return web_server->lock_json_((lock::Lock *) (source), ((lock::Lock *) (source))->state, DETAIL_ALL);
}
std::string WebServer::lock_json_(lock::Lock *obj, lock::LockState value, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::lock_json_(lock::Lock *obj, lock::LockState value, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1700,7 +1701,7 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->valve_json_(obj, detail);
auto data = this->valve_json_(obj, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1746,13 +1747,13 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa
}
request->send(404);
}
std::string WebServer::valve_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::valve_state_json_generator(WebServer *web_server, void *source) {
return web_server->valve_json_((valve::Valve *) (source), DETAIL_STATE);
}
std::string WebServer::valve_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::valve_all_json_generator(WebServer *web_server, void *source) {
return web_server->valve_json_((valve::Valve *) (source), DETAIL_ALL);
}
std::string WebServer::valve_json_(valve::Valve *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::valve_json_(valve::Valve *obj, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1785,7 +1786,7 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->alarm_control_panel_json_(obj, obj->get_state(), detail);
auto data = this->alarm_control_panel_json_(obj, obj->get_state(), detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1825,19 +1826,19 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques
}
request->send(404);
}
std::string WebServer::alarm_control_panel_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::alarm_control_panel_state_json_generator(WebServer *web_server, void *source) {
return web_server->alarm_control_panel_json_((alarm_control_panel::AlarmControlPanel *) (source),
((alarm_control_panel::AlarmControlPanel *) (source))->get_state(),
DETAIL_STATE);
}
std::string WebServer::alarm_control_panel_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::alarm_control_panel_all_json_generator(WebServer *web_server, void *source) {
return web_server->alarm_control_panel_json_((alarm_control_panel::AlarmControlPanel *) (source),
((alarm_control_panel::AlarmControlPanel *) (source))->get_state(),
DETAIL_ALL);
}
std::string WebServer::alarm_control_panel_json_(alarm_control_panel::AlarmControlPanel *obj,
alarm_control_panel::AlarmControlPanelState value,
JsonDetail start_config) {
json::SerializationBuffer<> WebServer::alarm_control_panel_json_(alarm_control_panel::AlarmControlPanel *obj,
alarm_control_panel::AlarmControlPanelState value,
JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -1866,7 +1867,7 @@ void WebServer::handle_water_heater_request(AsyncWebServerRequest *request, cons
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->water_heater_json_(obj, detail);
auto data = this->water_heater_json_(obj, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -1902,14 +1903,14 @@ void WebServer::handle_water_heater_request(AsyncWebServerRequest *request, cons
request->send(404);
}
std::string WebServer::water_heater_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::water_heater_state_json_generator(WebServer *web_server, void *source) {
return web_server->water_heater_json_(static_cast<water_heater::WaterHeater *>(source), DETAIL_STATE);
}
std::string WebServer::water_heater_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::water_heater_all_json_generator(WebServer *web_server, void *source) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
return web_server->water_heater_json_(static_cast<water_heater::WaterHeater *>(source), DETAIL_ALL);
}
std::string WebServer::water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
char buf[PSTR_LOCAL_SIZE];
@@ -1971,7 +1972,7 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->infrared_json_(obj, detail);
auto data = this->infrared_json_(obj, detail);
request->send(200, ESPHOME_F("application/json"), data.c_str());
return;
}
@@ -2031,12 +2032,12 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur
request->send(404);
}
std::string WebServer::infrared_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::infrared_all_json_generator(WebServer *web_server, void *source) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
return web_server->infrared_json_(static_cast<infrared::Infrared *>(source), DETAIL_ALL);
}
std::string WebServer::infrared_json_(infrared::Infrared *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::infrared_json_(infrared::Infrared *obj, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -2071,7 +2072,7 @@ void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMa
// Note: request->method() is always HTTP_GET here (canHandle ensures this)
if (entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->event_json_(obj, StringRef(), detail);
auto data = this->event_json_(obj, StringRef(), detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -2081,16 +2082,16 @@ void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMa
static StringRef get_event_type(event::Event *event) { return event ? event->get_last_event_type() : StringRef(); }
std::string WebServer::event_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::event_state_json_generator(WebServer *web_server, void *source) {
auto *event = static_cast<event::Event *>(source);
return web_server->event_json_(event, get_event_type(event), DETAIL_STATE);
}
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
std::string WebServer::event_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::event_all_json_generator(WebServer *web_server, void *source) {
auto *event = static_cast<event::Event *>(source);
return web_server->event_json_(event, get_event_type(event), DETAIL_ALL);
}
std::string WebServer::event_json_(event::Event *obj, StringRef event_type, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::event_json_(event::Event *obj, StringRef event_type, JsonDetail start_config) {
json::JsonBuilder builder;
JsonObject root = builder.root();
@@ -2124,7 +2125,7 @@ void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlM
if (request->method() == HTTP_GET && entity_match.action_is_empty) {
auto detail = get_request_detail(request);
std::string data = this->update_json_(obj, detail);
auto data = this->update_json_(obj, detail);
request->send(200, "application/json", data.c_str());
return;
}
@@ -2140,15 +2141,15 @@ void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlM
}
request->send(404);
}
std::string WebServer::update_state_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::update_state_json_generator(WebServer *web_server, void *source) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
return web_server->update_json_((update::UpdateEntity *) (source), DETAIL_STATE);
}
std::string WebServer::update_all_json_generator(WebServer *web_server, void *source) {
json::SerializationBuffer<> WebServer::update_all_json_generator(WebServer *web_server, void *source) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
return web_server->update_json_((update::UpdateEntity *) (source), DETAIL_STATE);
}
std::string WebServer::update_json_(update::UpdateEntity *obj, JsonDetail start_config) {
json::SerializationBuffer<> WebServer::update_json_(update::UpdateEntity *obj, JsonDetail start_config) {
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
json::JsonBuilder builder;
JsonObject root = builder.root();
+71 -67
View File
@@ -2,6 +2,7 @@
#include "list_entities.h"
#include "esphome/components/json/json_util.h"
#include "esphome/components/web_server_base/web_server_base.h"
#ifdef USE_WEBSERVER
#include "esphome/core/component.h"
@@ -103,7 +104,7 @@ enum JsonDetail { DETAIL_ALL, DETAIL_STATE };
can be forgotten.
*/
#if !defined(USE_ESP32) && defined(USE_ARDUINO)
using message_generator_t = std::string(WebServer *, void *);
using message_generator_t = json::SerializationBuffer<>(WebServer *, void *);
class DeferredUpdateEventSourceList;
class DeferredUpdateEventSource : public AsyncEventSource {
@@ -257,7 +258,7 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
void handle_index_request(AsyncWebServerRequest *request);
/// Return the webserver configuration as JSON.
std::string get_config_json();
json::SerializationBuffer<> get_config_json();
#ifdef USE_WEBSERVER_CSS_INCLUDE
/// Handle included css request under '/0.css'.
@@ -279,8 +280,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a sensor request under '/sensor/<id>'.
void handle_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string sensor_state_json_generator(WebServer *web_server, void *source);
static std::string sensor_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> sensor_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> sensor_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_SWITCH
@@ -289,8 +290,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a switch request under '/switch/<id>/</turn_on/turn_off/toggle>'.
void handle_switch_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string switch_state_json_generator(WebServer *web_server, void *source);
static std::string switch_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> switch_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> switch_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_BUTTON
@@ -298,7 +299,7 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
void handle_button_request(AsyncWebServerRequest *request, const UrlMatch &match);
// Buttons are stateless, so there is no button_state_json_generator
static std::string button_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> button_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_BINARY_SENSOR
@@ -307,8 +308,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a binary sensor request under '/binary_sensor/<id>'.
void handle_binary_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string binary_sensor_state_json_generator(WebServer *web_server, void *source);
static std::string binary_sensor_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> binary_sensor_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> binary_sensor_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_FAN
@@ -317,8 +318,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a fan request under '/fan/<id>/</turn_on/turn_off/toggle>'.
void handle_fan_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string fan_state_json_generator(WebServer *web_server, void *source);
static std::string fan_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> fan_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> fan_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_LIGHT
@@ -327,8 +328,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a light request under '/light/<id>/</turn_on/turn_off/toggle>'.
void handle_light_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string light_state_json_generator(WebServer *web_server, void *source);
static std::string light_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> light_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> light_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_TEXT_SENSOR
@@ -337,8 +338,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a text sensor request under '/text_sensor/<id>'.
void handle_text_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string text_sensor_state_json_generator(WebServer *web_server, void *source);
static std::string text_sensor_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> text_sensor_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> text_sensor_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_COVER
@@ -347,8 +348,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a cover request under '/cover/<id>/<open/close/stop/set>'.
void handle_cover_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string cover_state_json_generator(WebServer *web_server, void *source);
static std::string cover_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> cover_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> cover_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_NUMBER
@@ -356,8 +357,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a number request under '/number/<id>'.
void handle_number_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string number_state_json_generator(WebServer *web_server, void *source);
static std::string number_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> number_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> number_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_DATETIME_DATE
@@ -365,8 +366,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a date request under '/date/<id>'.
void handle_date_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string date_state_json_generator(WebServer *web_server, void *source);
static std::string date_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> date_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> date_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_DATETIME_TIME
@@ -374,8 +375,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a time request under '/time/<id>'.
void handle_time_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string time_state_json_generator(WebServer *web_server, void *source);
static std::string time_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> time_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> time_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_DATETIME_DATETIME
@@ -383,8 +384,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a datetime request under '/datetime/<id>'.
void handle_datetime_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string datetime_state_json_generator(WebServer *web_server, void *source);
static std::string datetime_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> datetime_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> datetime_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_TEXT
@@ -392,8 +393,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a text input request under '/text/<id>'.
void handle_text_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string text_state_json_generator(WebServer *web_server, void *source);
static std::string text_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> text_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> text_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_SELECT
@@ -401,8 +402,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a select request under '/select/<id>'.
void handle_select_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string select_state_json_generator(WebServer *web_server, void *source);
static std::string select_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> select_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> select_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_CLIMATE
@@ -410,8 +411,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a climate request under '/climate/<id>'.
void handle_climate_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string climate_state_json_generator(WebServer *web_server, void *source);
static std::string climate_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> climate_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> climate_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_LOCK
@@ -420,8 +421,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a lock request under '/lock/<id>/</lock/unlock/open>'.
void handle_lock_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string lock_state_json_generator(WebServer *web_server, void *source);
static std::string lock_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> lock_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> lock_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_VALVE
@@ -430,8 +431,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a valve request under '/valve/<id>/<open/close/stop/set>'.
void handle_valve_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string valve_state_json_generator(WebServer *web_server, void *source);
static std::string valve_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> valve_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> valve_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_ALARM_CONTROL_PANEL
@@ -440,8 +441,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a alarm_control_panel request under '/alarm_control_panel/<id>'.
void handle_alarm_control_panel_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string alarm_control_panel_state_json_generator(WebServer *web_server, void *source);
static std::string alarm_control_panel_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> alarm_control_panel_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> alarm_control_panel_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_WATER_HEATER
@@ -450,22 +451,22 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a water_heater request under '/water_heater/<id>/<mode/set>'.
void handle_water_heater_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string water_heater_state_json_generator(WebServer *web_server, void *source);
static std::string water_heater_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> water_heater_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> water_heater_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_INFRARED
/// Handle an infrared request under '/infrared/<id>/transmit'.
void handle_infrared_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string infrared_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> infrared_all_json_generator(WebServer *web_server, void *source);
#endif
#ifdef USE_EVENT
void on_event(event::Event *obj) override;
static std::string event_state_json_generator(WebServer *web_server, void *source);
static std::string event_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> event_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> event_all_json_generator(WebServer *web_server, void *source);
/// Handle a event request under '/event<id>'.
void handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match);
@@ -477,8 +478,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
/// Handle a update request under '/update/<id>'.
void handle_update_request(AsyncWebServerRequest *request, const UrlMatch &match);
static std::string update_state_json_generator(WebServer *web_server, void *source);
static std::string update_all_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> update_state_json_generator(WebServer *web_server, void *source);
static json::SerializationBuffer<> update_all_json_generator(WebServer *web_server, void *source);
#endif
/// Override the web handler's canHandle method.
@@ -586,71 +587,74 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
private:
#ifdef USE_SENSOR
std::string sensor_json_(sensor::Sensor *obj, float value, JsonDetail start_config);
json::SerializationBuffer<> sensor_json_(sensor::Sensor *obj, float value, JsonDetail start_config);
#endif
#ifdef USE_SWITCH
std::string switch_json_(switch_::Switch *obj, bool value, JsonDetail start_config);
json::SerializationBuffer<> switch_json_(switch_::Switch *obj, bool value, JsonDetail start_config);
#endif
#ifdef USE_BUTTON
std::string button_json_(button::Button *obj, JsonDetail start_config);
json::SerializationBuffer<> button_json_(button::Button *obj, JsonDetail start_config);
#endif
#ifdef USE_BINARY_SENSOR
std::string binary_sensor_json_(binary_sensor::BinarySensor *obj, bool value, JsonDetail start_config);
json::SerializationBuffer<> binary_sensor_json_(binary_sensor::BinarySensor *obj, bool value,
JsonDetail start_config);
#endif
#ifdef USE_FAN
std::string fan_json_(fan::Fan *obj, JsonDetail start_config);
json::SerializationBuffer<> fan_json_(fan::Fan *obj, JsonDetail start_config);
#endif
#ifdef USE_LIGHT
std::string light_json_(light::LightState *obj, JsonDetail start_config);
json::SerializationBuffer<> light_json_(light::LightState *obj, JsonDetail start_config);
#endif
#ifdef USE_TEXT_SENSOR
std::string text_sensor_json_(text_sensor::TextSensor *obj, const std::string &value, JsonDetail start_config);
json::SerializationBuffer<> text_sensor_json_(text_sensor::TextSensor *obj, const std::string &value,
JsonDetail start_config);
#endif
#ifdef USE_COVER
std::string cover_json_(cover::Cover *obj, JsonDetail start_config);
json::SerializationBuffer<> cover_json_(cover::Cover *obj, JsonDetail start_config);
#endif
#ifdef USE_NUMBER
std::string number_json_(number::Number *obj, float value, JsonDetail start_config);
json::SerializationBuffer<> number_json_(number::Number *obj, float value, JsonDetail start_config);
#endif
#ifdef USE_DATETIME_DATE
std::string date_json_(datetime::DateEntity *obj, JsonDetail start_config);
json::SerializationBuffer<> date_json_(datetime::DateEntity *obj, JsonDetail start_config);
#endif
#ifdef USE_DATETIME_TIME
std::string time_json_(datetime::TimeEntity *obj, JsonDetail start_config);
json::SerializationBuffer<> time_json_(datetime::TimeEntity *obj, JsonDetail start_config);
#endif
#ifdef USE_DATETIME_DATETIME
std::string datetime_json_(datetime::DateTimeEntity *obj, JsonDetail start_config);
json::SerializationBuffer<> datetime_json_(datetime::DateTimeEntity *obj, JsonDetail start_config);
#endif
#ifdef USE_TEXT
std::string text_json_(text::Text *obj, const std::string &value, JsonDetail start_config);
json::SerializationBuffer<> text_json_(text::Text *obj, const std::string &value, JsonDetail start_config);
#endif
#ifdef USE_SELECT
std::string select_json_(select::Select *obj, StringRef value, JsonDetail start_config);
json::SerializationBuffer<> select_json_(select::Select *obj, StringRef value, JsonDetail start_config);
#endif
#ifdef USE_CLIMATE
std::string climate_json_(climate::Climate *obj, JsonDetail start_config);
json::SerializationBuffer<> climate_json_(climate::Climate *obj, JsonDetail start_config);
#endif
#ifdef USE_LOCK
std::string lock_json_(lock::Lock *obj, lock::LockState value, JsonDetail start_config);
json::SerializationBuffer<> lock_json_(lock::Lock *obj, lock::LockState value, JsonDetail start_config);
#endif
#ifdef USE_VALVE
std::string valve_json_(valve::Valve *obj, JsonDetail start_config);
json::SerializationBuffer<> valve_json_(valve::Valve *obj, JsonDetail start_config);
#endif
#ifdef USE_ALARM_CONTROL_PANEL
std::string alarm_control_panel_json_(alarm_control_panel::AlarmControlPanel *obj,
alarm_control_panel::AlarmControlPanelState value, JsonDetail start_config);
json::SerializationBuffer<> alarm_control_panel_json_(alarm_control_panel::AlarmControlPanel *obj,
alarm_control_panel::AlarmControlPanelState value,
JsonDetail start_config);
#endif
#ifdef USE_EVENT
std::string event_json_(event::Event *obj, StringRef event_type, JsonDetail start_config);
json::SerializationBuffer<> event_json_(event::Event *obj, StringRef event_type, JsonDetail start_config);
#endif
#ifdef USE_WATER_HEATER
std::string water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config);
json::SerializationBuffer<> water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config);
#endif
#ifdef USE_INFRARED
std::string infrared_json_(infrared::Infrared *obj, JsonDetail start_config);
json::SerializationBuffer<> infrared_json_(infrared::Infrared *obj, JsonDetail start_config);
#endif
#ifdef USE_UPDATE
std::string update_json_(update::UpdateEntity *obj, JsonDetail start_config);
json::SerializationBuffer<> update_json_(update::UpdateEntity *obj, JsonDetail start_config);
#endif
};
@@ -563,7 +563,7 @@ AsyncEventSourceResponse::AsyncEventSourceResponse(const AsyncWebServerRequest *
// Configure reconnect timeout and send config
// this should always go through since the tcp send buffer is empty on connect
std::string message = ws->get_config_json();
auto message = ws->get_config_json();
this->try_send_nodefer(message.c_str(), "ping", millis(), 30000);
#ifdef USE_WEBSERVER_SORTING
@@ -617,7 +617,7 @@ void AsyncEventSourceResponse::deq_push_back_with_dedup_(void *source, message_g
void AsyncEventSourceResponse::process_deferred_queue_() {
while (!deferred_queue_.empty()) {
DeferredEvent &de = deferred_queue_.front();
std::string message = de.message_generator_(web_server_, de.source_);
auto message = de.message_generator_(web_server_, de.source_);
if (this->try_send_nodefer(message.c_str(), "state")) {
// O(n) but memory efficiency is more important than speed here which is why std::vector was chosen
deferred_queue_.erase(deferred_queue_.begin());
@@ -854,7 +854,7 @@ void AsyncEventSourceResponse::deferrable_send_state(void *source, const char *e
// trying to send first
deq_push_back_with_dedup_(source, message_generator);
} else {
std::string message = message_generator(web_server_, source);
auto message = message_generator(web_server_, source);
if (!this->try_send_nodefer(message.c_str(), "state")) {
deq_push_back_with_dedup_(source, message_generator);
}
@@ -16,6 +16,7 @@
#include <vector>
#ifdef USE_WEBSERVER
#include "esphome/components/json/json_util.h"
#include "esphome/components/web_server/list_entities.h"
#endif
@@ -250,7 +251,7 @@ class AsyncWebHandler {
class AsyncEventSource;
class AsyncEventSourceResponse;
using message_generator_t = std::string(esphome::web_server::WebServer *, void *);
using message_generator_t = json::SerializationBuffer<>(esphome::web_server::WebServer *, void *);
/*
This class holds a pointer to the source component that wants to publish a state event, and a pointer to a function
+8
View File
@@ -1,4 +1,5 @@
import logging
import math
from esphome import automation
from esphome.automation import Condition
@@ -493,6 +494,13 @@ async def to_code(config):
cg.add(var.set_passive_scan(True))
if CONF_OUTPUT_POWER in config:
cg.add(var.set_output_power(config[CONF_OUTPUT_POWER]))
if CORE.is_esp32:
# Set PHY max TX power to match output_power so calibration also uses
# reduced power. This prevents brownout during PHY init on marginal
# power supplies, which is critical for OTA updates with rollback enabled.
# Kconfig range is 10-20, ESPHome allows 8.5-20.5
phy_tx_power = max(10, min(20, math.ceil(config[CONF_OUTPUT_POWER])))
add_idf_sdkconfig_option("CONFIG_ESP_PHY_MAX_WIFI_TX_POWER", phy_tx_power)
# enable_on_boot defaults to true in C++ - only set if false
if not config[CONF_ENABLE_ON_BOOT]:
cg.add(var.set_enable_on_boot(False))
@@ -0,0 +1,5 @@
<<: !include common.yaml
esp32_ble:
io_capability: keyboard_only
disable_bt_logs: false
+7 -6
View File
@@ -4,15 +4,16 @@ interval:
- interval: 60s
then:
- lambda: |-
// Test build_json
std::string json_str = esphome::json::build_json([](JsonObject root) {
// Test build_json - returns SerializationBuffer, use auto to avoid heap allocation
auto json_buf = esphome::json::build_json([](JsonObject root) {
root["sensor"] = "temperature";
root["value"] = 23.5;
root["unit"] = "°C";
});
ESP_LOGD("test", "Built JSON: %s", json_str.c_str());
ESP_LOGD("test", "Built JSON: %s", json_buf.c_str());
// Test parse_json
// Test parse_json - implicit conversion to std::string for backward compatibility
std::string json_str = json_buf;
bool parse_ok = esphome::json::parse_json(json_str, [](JsonObject root) {
if (root["sensor"].is<const char*>() && root["value"].is<float>()) {
const char* sensor = root["sensor"];
@@ -26,10 +27,10 @@ interval:
});
ESP_LOGD("test", "Parse result (JSON syntax only): %s", parse_ok ? "success" : "failed");
// Test JsonBuilder class
// Test JsonBuilder class - returns SerializationBuffer
esphome::json::JsonBuilder builder;
JsonObject obj = builder.root();
obj["test"] = "direct_builder";
obj["count"] = 42;
std::string result = builder.serialize();
auto result = builder.serialize();
ESP_LOGD("test", "JsonBuilder result: %s", result.c_str());
@@ -0,0 +1,10 @@
sensor:
- platform: pulse_counter
name: Pulse Counter
pin: 4
use_pcnt: false
count_mode:
rising_edge: INCREMENT
falling_edge: DECREMENT
internal_filter: 13us
update_interval: 15s