esphome 2025.9.3__py3-none-any.whl → 2025.10.0b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +94 -31
- esphome/address_cache.py +142 -0
- esphome/automation.py +130 -32
- esphome/build_gen/platformio.py +1 -3
- esphome/codegen.py +1 -0
- esphome/components/animation/animation.cpp +2 -2
- esphome/components/api/__init__.py +166 -3
- esphome/components/api/api_connection.cpp +84 -41
- esphome/components/api/api_connection.h +22 -16
- esphome/components/api/api_frame_helper.cpp +33 -19
- esphome/components/api/api_frame_helper.h +19 -4
- esphome/components/api/api_frame_helper_noise.cpp +41 -53
- esphome/components/api/api_frame_helper_noise.h +1 -1
- esphome/components/api/api_frame_helper_plaintext.cpp +22 -31
- esphome/components/api/api_frame_helper_plaintext.h +1 -1
- esphome/components/api/api_pb2.cpp +189 -15
- esphome/components/api/api_pb2.h +132 -20
- esphome/components/api/api_pb2_dump.cpp +97 -9
- esphome/components/api/api_pb2_service.cpp +118 -160
- esphome/components/api/api_pb2_service.h +31 -3
- esphome/components/api/api_server.cpp +68 -10
- esphome/components/api/api_server.h +32 -4
- esphome/components/api/custom_api_device.h +8 -8
- esphome/components/api/homeassistant_service.h +123 -6
- esphome/components/api/proto.h +6 -2
- esphome/components/api/user_services.h +2 -2
- esphome/components/as7341/sensor.py +1 -1
- esphome/components/audio/__init__.py +1 -1
- esphome/components/audio/audio.cpp +1 -1
- esphome/components/audio/audio_decoder.cpp +9 -9
- esphome/components/bl0906/bl0906.cpp +2 -2
- esphome/components/bl0942/bl0942.cpp +2 -2
- esphome/components/ble_client/__init__.py +1 -1
- esphome/components/bluetooth_proxy/__init__.py +4 -30
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +11 -4
- esphome/components/bluetooth_proxy/bluetooth_connection.h +2 -2
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +2 -2
- esphome/components/camera_encoder/__init__.py +2 -4
- esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +4 -2
- esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +3 -1
- esphome/components/canbus/canbus.cpp +7 -5
- esphome/components/canbus/canbus.h +7 -7
- esphome/components/captive_portal/__init__.py +18 -1
- esphome/components/captive_portal/captive_portal.cpp +40 -46
- esphome/components/captive_portal/captive_portal.h +20 -22
- esphome/components/captive_portal/dns_server_esp32_idf.cpp +205 -0
- esphome/components/captive_portal/dns_server_esp32_idf.h +27 -0
- esphome/components/ccs811/ccs811.cpp +1 -1
- esphome/components/climate/climate.cpp +10 -7
- esphome/components/cm1106/cm1106.cpp +1 -1
- esphome/components/copy/lock/copy_lock.cpp +1 -1
- esphome/components/cover/cover.cpp +1 -0
- esphome/components/daikin_arc/daikin_arc.cpp +19 -12
- esphome/components/dashboard_import/dashboard_import.cpp +1 -1
- esphome/components/dashboard_import/dashboard_import.h +1 -1
- esphome/components/deep_sleep/__init__.py +9 -2
- esphome/components/deep_sleep/deep_sleep_component.h +11 -9
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +51 -27
- esphome/components/ektf2232/touchscreen/__init__.py +8 -5
- esphome/components/ektf2232/touchscreen/ektf2232.cpp +4 -4
- esphome/components/ektf2232/touchscreen/ektf2232.h +2 -2
- esphome/components/epaper_spi/__init__.py +1 -0
- esphome/components/epaper_spi/display.py +80 -0
- esphome/components/epaper_spi/epaper_spi.cpp +227 -0
- esphome/components/epaper_spi/epaper_spi.h +93 -0
- esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.cpp +42 -0
- esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.h +45 -0
- esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +135 -0
- esphome/components/epaper_spi/epaper_spi_spectra_e6.h +23 -0
- esphome/components/es7210/es7210.cpp +3 -3
- esphome/components/esp32/__init__.py +256 -340
- esphome/components/esp32/boards.py +81 -0
- esphome/components/esp32/preferences.cpp +23 -17
- esphome/components/esp32_ble/__init__.py +167 -44
- esphome/components/esp32_ble/ble.cpp +47 -3
- esphome/components/esp32_ble/ble.h +18 -0
- esphome/components/esp32_ble/ble_advertising.cpp +7 -3
- esphome/components/esp32_ble/ble_advertising.h +4 -0
- esphome/components/esp32_ble/ble_uuid.cpp +16 -42
- esphome/components/esp32_ble_beacon/__init__.py +3 -4
- esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +0 -4
- esphome/components/esp32_ble_client/ble_client_base.cpp +14 -12
- esphome/components/esp32_ble_server/__init__.py +28 -14
- esphome/components/esp32_ble_server/ble_characteristic.cpp +67 -57
- esphome/components/esp32_ble_server/ble_characteristic.h +27 -16
- esphome/components/esp32_ble_server/ble_descriptor.cpp +4 -3
- esphome/components/esp32_ble_server/ble_descriptor.h +13 -9
- esphome/components/esp32_ble_server/ble_server.cpp +59 -24
- esphome/components/esp32_ble_server/ble_server.h +38 -20
- esphome/components/esp32_ble_server/ble_server_automations.cpp +49 -33
- esphome/components/esp32_ble_server/ble_server_automations.h +39 -24
- esphome/components/esp32_ble_tracker/__init__.py +25 -80
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -8
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +0 -3
- esphome/components/esp32_camera/__init__.py +1 -3
- esphome/components/esp32_can/esp32_can.cpp +22 -4
- esphome/components/esp32_can/esp32_can.h +3 -0
- esphome/components/esp32_hosted/__init__.py +2 -1
- esphome/components/esp32_improv/esp32_improv_component.cpp +135 -65
- esphome/components/esp32_improv/esp32_improv_component.h +7 -1
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
- esphome/components/esp8266/__init__.py +3 -3
- esphome/components/esphome/ota/__init__.py +21 -2
- esphome/components/esphome/ota/ota_esphome.cpp +456 -146
- esphome/components/esphome/ota/ota_esphome.h +49 -2
- esphome/components/ethernet/__init__.py +39 -22
- esphome/components/ethernet/ethernet_component.cpp +28 -5
- esphome/components/ethernet/ethernet_component.h +5 -1
- esphome/components/external_components/__init__.py +8 -6
- esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
- esphome/components/fingerprint_grow/fingerprint_grow.h +2 -1
- esphome/components/font/__init__.py +5 -5
- esphome/components/graph/graph.cpp +1 -1
- esphome/components/graphical_display_menu/graphical_display_menu.cpp +3 -2
- esphome/components/haier/hon_climate.cpp +2 -2
- esphome/components/haier/hon_climate.h +1 -1
- esphome/components/hdc1080/hdc1080.cpp +42 -34
- esphome/components/hdc1080/hdc1080.h +1 -3
- esphome/components/homeassistant/number/homeassistant_number.cpp +2 -2
- esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
- esphome/components/http_request/__init__.py +3 -3
- esphome/components/htu21d/htu21d.cpp +13 -18
- esphome/components/htu21d/htu21d.h +1 -1
- esphome/components/i2s_audio/__init__.py +1 -2
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
- esphome/components/ili9xxx/ili9xxx_display.cpp +2 -2
- esphome/components/improv_serial/improv_serial_component.cpp +12 -15
- esphome/components/improv_serial/improv_serial_component.h +6 -8
- esphome/components/json/json_util.cpp +42 -44
- esphome/components/json/json_util.h +57 -0
- esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +2 -2
- esphome/components/key_collector/key_collector.h +4 -4
- esphome/components/libretiny/__init__.py +6 -6
- esphome/components/libretiny/preferences.cpp +23 -16
- esphome/components/light/light_call.cpp +98 -120
- esphome/components/light/light_call.h +17 -7
- esphome/components/lm75b/__init__.py +0 -0
- esphome/components/lm75b/lm75b.cpp +39 -0
- esphome/components/lm75b/lm75b.h +19 -0
- esphome/components/lm75b/sensor.py +34 -0
- esphome/components/lock/lock.h +12 -6
- esphome/components/logger/__init__.py +15 -27
- esphome/components/logger/logger.cpp +10 -20
- esphome/components/logger/logger.h +105 -62
- esphome/components/logger/logger_esp32.cpp +0 -48
- esphome/components/logger/logger_zephyr.cpp +2 -3
- esphome/components/logger/select/logger_level_select.cpp +6 -7
- esphome/components/logger/select/logger_level_select.h +7 -0
- esphome/components/ltr501/ltr501.cpp +7 -6
- esphome/components/ltr_als_ps/ltr_als_ps.cpp +7 -6
- esphome/components/matrix_keypad/matrix_keypad.h +4 -4
- esphome/components/max7219digit/max7219digit.cpp +1 -1
- esphome/components/mcp23xxx_base/mcp23xxx_base.h +3 -3
- esphome/components/mcp2515/mcp2515.cpp +31 -3
- esphome/components/mcp2515/mcp2515_defs.h +3 -1
- esphome/components/md5/md5.cpp +0 -26
- esphome/components/md5/md5.h +10 -20
- esphome/components/mdns/__init__.py +93 -19
- esphome/components/mdns/mdns_component.cpp +57 -94
- esphome/components/mdns/mdns_component.h +35 -11
- esphome/components/mdns/mdns_esp32.cpp +7 -13
- esphome/components/mdns/mdns_esp8266.cpp +7 -7
- esphome/components/mdns/mdns_libretiny.cpp +3 -4
- esphome/components/mdns/mdns_rp2040.cpp +3 -4
- esphome/components/mipi/__init__.py +1 -5
- esphome/components/mipi_spi/display.py +24 -8
- esphome/components/mipi_spi/mipi_spi.h +3 -3
- esphome/components/mixer/speaker/mixer_speaker.cpp +3 -3
- esphome/components/mmc5603/mmc5603.cpp +3 -3
- esphome/components/modbus/modbus.cpp +27 -13
- esphome/components/modbus/modbus.h +5 -3
- esphome/components/modbus/modbus_definitions.h +86 -0
- esphome/components/modbus_controller/__init__.py +29 -1
- esphome/components/modbus_controller/const.py +4 -0
- esphome/components/modbus_controller/modbus_controller.cpp +38 -13
- esphome/components/modbus_controller/modbus_controller.h +18 -29
- esphome/components/mpr121/mpr121.cpp +41 -42
- esphome/components/mpr121/mpr121.h +0 -1
- esphome/components/nau7802/nau7802.cpp +2 -2
- esphome/components/network/__init__.py +7 -3
- esphome/components/nextion/display.py +4 -4
- esphome/components/nextion/nextion.cpp +8 -8
- esphome/components/number/__init__.py +2 -0
- esphome/components/number/number_call.cpp +23 -12
- esphome/components/number/number_call.h +5 -0
- esphome/components/online_image/bmp_image.cpp +2 -1
- esphome/components/online_image/jpeg_image.cpp +4 -2
- esphome/components/opentherm/opentherm.cpp +5 -5
- esphome/components/opentherm/opentherm.h +3 -3
- esphome/components/openthread/openthread.cpp +11 -10
- esphome/components/openthread/openthread.h +0 -1
- esphome/components/ota/ota_backend.h +1 -0
- esphome/components/packages/__init__.py +10 -8
- esphome/components/packet_transport/packet_transport.cpp +2 -0
- esphome/components/pid/pid_controller.cpp +1 -1
- esphome/components/prometheus/prometheus_handler.cpp +239 -239
- esphome/components/psram/__init__.py +30 -28
- esphome/components/qmc5883l/qmc5883l.cpp +15 -0
- esphome/components/qmc5883l/qmc5883l.h +3 -0
- esphome/components/qmc5883l/sensor.py +31 -12
- esphome/components/remote_base/gobox_protocol.cpp +3 -3
- esphome/components/remote_receiver/__init__.py +14 -2
- esphome/components/remote_receiver/{remote_receiver_esp8266.cpp → remote_receiver.cpp} +2 -2
- esphome/components/remote_receiver/remote_receiver.h +4 -0
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +18 -1
- esphome/components/remote_transmitter/__init__.py +2 -2
- esphome/components/remote_transmitter/remote_transmitter.cpp +103 -0
- esphome/components/rp2040/__init__.py +11 -11
- esphome/components/rtttl/rtttl.cpp +2 -2
- esphome/components/scd30/sensor.py +1 -1
- esphome/components/script/__init__.py +1 -1
- esphome/components/script/script.h +7 -7
- esphome/components/select/select.cpp +5 -4
- esphome/components/select/select_call.cpp +1 -1
- esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
- esphome/components/sensor/__init__.py +2 -0
- esphome/components/sha256/__init__.py +22 -0
- esphome/components/sha256/sha256.cpp +116 -0
- esphome/components/sha256/sha256.h +60 -0
- esphome/components/socket/lwip_raw_tcp_impl.cpp +34 -6
- esphome/components/sonoff_d1/sonoff_d1.cpp +1 -1
- esphome/components/spi/__init__.py +0 -3
- esphome/components/split_buffer/__init__.py +5 -0
- esphome/components/split_buffer/split_buffer.cpp +133 -0
- esphome/components/split_buffer/split_buffer.h +40 -0
- esphome/components/sps30/sps30.cpp +14 -10
- esphome/components/sps30/sps30.h +2 -0
- esphome/components/st7567_i2c/st7567_i2c.cpp +3 -1
- esphome/components/st7789v/st7789v.cpp +3 -2
- esphome/components/statsd/statsd.cpp +1 -1
- esphome/components/substitutions/__init__.py +3 -1
- esphome/components/substitutions/jinja.py +13 -3
- esphome/components/sx126x/__init__.py +16 -0
- esphome/components/sx126x/sx126x.cpp +15 -1
- esphome/components/sx126x/sx126x.h +9 -1
- esphome/components/sx126x/sx126x_reg.h +2 -0
- esphome/components/text_sensor/text_sensor.cpp +16 -0
- esphome/components/text_sensor/text_sensor.h +3 -10
- esphome/components/tormatic/tormatic_cover.cpp +1 -1
- esphome/components/tuya/select/tuya_select.cpp +1 -1
- esphome/components/tuya/tuya.cpp +29 -4
- esphome/components/uart/__init__.py +37 -27
- esphome/components/uart/uart.h +6 -0
- esphome/components/uart/uart_component.cpp +8 -0
- esphome/components/uart/uart_component.h +28 -0
- esphome/components/uart/uart_component_esp_idf.cpp +64 -10
- esphome/components/uart/uart_component_esp_idf.h +5 -2
- esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
- esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +1 -1
- esphome/components/uponor_smatrix/uponor_smatrix.cpp +3 -3
- esphome/components/usb_host/__init__.py +12 -2
- esphome/components/usb_host/usb_host.h +89 -14
- esphome/components/usb_host/usb_host_client.cpp +157 -22
- esphome/components/usb_host/usb_host_component.cpp +1 -1
- esphome/components/usb_uart/__init__.py +0 -1
- esphome/components/usb_uart/ch34x.cpp +4 -4
- esphome/components/usb_uart/cp210x.cpp +3 -3
- esphome/components/usb_uart/usb_uart.cpp +88 -32
- esphome/components/usb_uart/usb_uart.h +30 -6
- esphome/components/valve/valve.cpp +1 -0
- esphome/components/veml7700/veml7700.cpp +7 -6
- esphome/components/version/version_text_sensor.cpp +2 -1
- esphome/components/voice_assistant/voice_assistant.cpp +3 -2
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +4 -4
- esphome/components/web_server/list_entities.cpp +3 -4
- esphome/components/web_server/list_entities.h +8 -10
- esphome/components/web_server/ota/__init__.py +1 -1
- esphome/components/web_server/ota/ota_web_server.cpp +9 -3
- esphome/components/web_server/web_server.cpp +509 -404
- esphome/components/web_server/web_server.h +5 -6
- esphome/components/web_server/web_server_v1.cpp +21 -19
- esphome/components/web_server_base/__init__.py +5 -2
- esphome/components/web_server_base/web_server_base.h +27 -7
- esphome/components/web_server_idf/__init__.py +1 -1
- esphome/components/web_server_idf/multipart.cpp +2 -2
- esphome/components/web_server_idf/multipart.h +2 -2
- esphome/components/web_server_idf/utils.cpp +2 -2
- esphome/components/web_server_idf/utils.h +2 -2
- esphome/components/web_server_idf/web_server_idf.cpp +118 -26
- esphome/components/web_server_idf/web_server_idf.h +12 -10
- esphome/components/wifi/__init__.py +13 -11
- esphome/components/wifi/wifi_component.cpp +74 -56
- esphome/components/wifi/wifi_component.h +4 -4
- esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
- esphome/components/wifi/wifi_component_esp_idf.cpp +24 -4
- esphome/components/wireguard/__init__.py +1 -1
- esphome/components/wts01/__init__.py +0 -0
- esphome/components/wts01/sensor.py +41 -0
- esphome/components/wts01/wts01.cpp +91 -0
- esphome/components/wts01/wts01.h +27 -0
- esphome/components/zephyr/__init__.py +5 -5
- esphome/components/zwave_proxy/__init__.py +43 -0
- esphome/components/zwave_proxy/zwave_proxy.cpp +346 -0
- esphome/components/zwave_proxy/zwave_proxy.h +93 -0
- esphome/config.py +79 -24
- esphome/config_validation.py +13 -15
- esphome/const.py +9 -2
- esphome/core/__init__.py +33 -22
- esphome/core/component.cpp +28 -18
- esphome/core/component_iterator.h +2 -1
- esphome/core/config.py +15 -15
- esphome/core/defines.h +21 -0
- esphome/core/entity_helpers.py +9 -6
- esphome/core/hash_base.h +56 -0
- esphome/core/helpers.cpp +19 -3
- esphome/core/helpers.h +26 -0
- esphome/core/scheduler.cpp +5 -21
- esphome/core/scheduler.h +19 -8
- esphome/core/string_ref.h +1 -1
- esphome/core/time.cpp +5 -5
- esphome/cpp_generator.py +4 -29
- esphome/dashboard/const.py +21 -4
- esphome/dashboard/core.py +10 -8
- esphome/dashboard/dns.py +15 -0
- esphome/dashboard/entries.py +15 -21
- esphome/dashboard/models.py +76 -0
- esphome/dashboard/settings.py +7 -7
- esphome/dashboard/status/mdns.py +46 -2
- esphome/dashboard/web_server.py +367 -93
- esphome/espota2.py +112 -32
- esphome/external_files.py +6 -7
- esphome/git.py +8 -0
- esphome/helpers.py +124 -77
- esphome/loader.py +8 -9
- esphome/pins.py +2 -2
- esphome/platformio_api.py +56 -18
- esphome/storage_json.py +26 -21
- esphome/types.py +30 -2
- esphome/util.py +32 -16
- esphome/vscode.py +8 -8
- esphome/wizard.py +10 -10
- esphome/writer.py +50 -15
- esphome/yaml_util.py +37 -31
- esphome/zeroconf.py +12 -3
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/METADATA +12 -12
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/RECORD +340 -320
- esphome/components/event_emitter/__init__.py +0 -5
- esphome/components/event_emitter/event_emitter.cpp +0 -14
- esphome/components/event_emitter/event_emitter.h +0 -63
- esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -125
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +0 -107
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +0 -110
- esphome/components/uart/uart_component_esp32_arduino.cpp +0 -214
- esphome/components/uart/uart_component_esp32_arduino.h +0 -60
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +0 -860
- esphome/core/string_ref.cpp +0 -12
- esphome/dashboard/util/file.py +0 -63
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/WHEEL +0 -0
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/entry_points.txt +0 -0
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,7 @@
|
|
8
8
|
#include "esphome/core/log.h"
|
9
9
|
#include "esphome/core/util.h"
|
10
10
|
|
11
|
-
#
|
11
|
+
#if !defined(USE_ESP32) && defined(USE_ARDUINO)
|
12
12
|
#include "StreamString.h"
|
13
13
|
#endif
|
14
14
|
|
@@ -103,19 +103,19 @@ static UrlMatch match_url(const char *url_ptr, size_t url_len, bool only_domain)
|
|
103
103
|
return match;
|
104
104
|
}
|
105
105
|
|
106
|
-
#
|
106
|
+
#if !defined(USE_ESP32) && defined(USE_ARDUINO)
|
107
107
|
// helper for allowing only unique entries in the queue
|
108
108
|
void DeferredUpdateEventSource::deq_push_back_with_dedup_(void *source, message_generator_t *message_generator) {
|
109
109
|
DeferredEvent item(source, message_generator);
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
this->deferred_queue_.push_back(item);
|
111
|
+
// Use range-based for loop instead of std::find_if to reduce template instantiation overhead and binary size
|
112
|
+
for (auto &event : this->deferred_queue_) {
|
113
|
+
if (event == item) {
|
114
|
+
event = item;
|
115
|
+
return;
|
116
|
+
}
|
118
117
|
}
|
118
|
+
this->deferred_queue_.push_back(item);
|
119
119
|
}
|
120
120
|
|
121
121
|
void DeferredUpdateEventSource::process_deferred_queue_() {
|
@@ -127,6 +127,10 @@ void DeferredUpdateEventSource::process_deferred_queue_() {
|
|
127
127
|
deferred_queue_.erase(deferred_queue_.begin());
|
128
128
|
this->consecutive_send_failures_ = 0; // Reset failure count on successful send
|
129
129
|
} else {
|
130
|
+
// NOTE: Similar logic exists in web_server_idf/web_server_idf.cpp in AsyncEventSourceResponse::process_buffer_()
|
131
|
+
// The implementations differ due to platform-specific APIs (DISCARDED vs HTTPD_SOCK_ERR_TIMEOUT, close() vs
|
132
|
+
// fd_.store(0)), but the failure counting and timeout logic should be kept in sync. If you change this logic,
|
133
|
+
// also update the ESP-IDF implementation.
|
130
134
|
this->consecutive_send_failures_++;
|
131
135
|
if (this->consecutive_send_failures_ >= MAX_CONSECUTIVE_SEND_FAILURES) {
|
132
136
|
// Too many failures, connection is likely dead
|
@@ -228,10 +232,11 @@ void DeferredUpdateEventSourceList::on_client_connect_(WebServer *ws, DeferredUp
|
|
228
232
|
|
229
233
|
#ifdef USE_WEBSERVER_SORTING
|
230
234
|
for (auto &group : ws->sorting_groups_) {
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
+
json::JsonBuilder builder;
|
236
|
+
JsonObject root = builder.root();
|
237
|
+
root["name"] = group.second.name;
|
238
|
+
root["sorting_weight"] = group.second.weight;
|
239
|
+
message = builder.serialize();
|
235
240
|
|
236
241
|
// up to 31 groups should be able to be queued initially without defer
|
237
242
|
source->try_send_nodefer(message.c_str(), "sorting_group");
|
@@ -265,17 +270,20 @@ void WebServer::set_js_include(const char *js_include) { this->js_include_ = js_
|
|
265
270
|
#endif
|
266
271
|
|
267
272
|
std::string WebServer::get_config_json() {
|
268
|
-
|
269
|
-
|
270
|
-
|
273
|
+
json::JsonBuilder builder;
|
274
|
+
JsonObject root = builder.root();
|
275
|
+
|
276
|
+
root["title"] = App.get_friendly_name().empty() ? App.get_name() : App.get_friendly_name();
|
277
|
+
root["comment"] = App.get_comment();
|
271
278
|
#if defined(USE_WEBSERVER_OTA_DISABLED) || !defined(USE_WEBSERVER_OTA)
|
272
|
-
|
279
|
+
root["ota"] = false; // Note: USE_WEBSERVER_OTA_DISABLED only affects web_server, not captive_portal
|
273
280
|
#else
|
274
|
-
|
281
|
+
root["ota"] = true;
|
275
282
|
#endif
|
276
|
-
|
277
|
-
|
278
|
-
|
283
|
+
root["log"] = this->expose_log_;
|
284
|
+
root["lang"] = "en";
|
285
|
+
|
286
|
+
return builder.serialize();
|
279
287
|
}
|
280
288
|
|
281
289
|
void WebServer::setup() {
|
@@ -293,7 +301,7 @@ void WebServer::setup() {
|
|
293
301
|
}
|
294
302
|
#endif
|
295
303
|
|
296
|
-
#ifdef
|
304
|
+
#ifdef USE_ESP32
|
297
305
|
this->base_->add_handler(&this->events_);
|
298
306
|
#endif
|
299
307
|
this->base_->add_handler(this);
|
@@ -377,11 +385,14 @@ void WebServer::handle_js_request(AsyncWebServerRequest *request) {
|
|
377
385
|
#endif
|
378
386
|
|
379
387
|
// Helper functions to reduce code size by avoiding macro expansion
|
380
|
-
static void set_json_id(JsonObject &root, EntityBase *obj, const
|
381
|
-
|
388
|
+
static void set_json_id(JsonObject &root, EntityBase *obj, const char *prefix, JsonDetail start_config) {
|
389
|
+
char id_buf[160]; // object_id can be up to 128 chars + prefix + dash + null
|
390
|
+
const auto &object_id = obj->get_object_id();
|
391
|
+
snprintf(id_buf, sizeof(id_buf), "%s-%s", prefix, object_id.c_str());
|
392
|
+
root["id"] = id_buf;
|
382
393
|
if (start_config == DETAIL_ALL) {
|
383
394
|
root["name"] = obj->get_name();
|
384
|
-
root["icon"] = obj->
|
395
|
+
root["icon"] = obj->get_icon_ref();
|
385
396
|
root["entity_category"] = obj->get_entity_category();
|
386
397
|
bool is_disabled = obj->is_disabled_by_default();
|
387
398
|
if (is_disabled)
|
@@ -389,17 +400,19 @@ static void set_json_id(JsonObject &root, EntityBase *obj, const std::string &id
|
|
389
400
|
}
|
390
401
|
}
|
391
402
|
|
403
|
+
// Keep as separate function even though only used once: reduces code size by ~48 bytes
|
404
|
+
// by allowing compiler to share code between template instantiations (bool, float, etc.)
|
392
405
|
template<typename T>
|
393
|
-
static void set_json_value(JsonObject &root, EntityBase *obj, const
|
406
|
+
static void set_json_value(JsonObject &root, EntityBase *obj, const char *prefix, const T &value,
|
394
407
|
JsonDetail start_config) {
|
395
|
-
set_json_id(root, obj,
|
408
|
+
set_json_id(root, obj, prefix, start_config);
|
396
409
|
root["value"] = value;
|
397
410
|
}
|
398
411
|
|
399
412
|
template<typename T>
|
400
|
-
static void set_json_icon_state_value(JsonObject &root, EntityBase *obj, const std::string &
|
401
|
-
const
|
402
|
-
set_json_value(root, obj,
|
413
|
+
static void set_json_icon_state_value(JsonObject &root, EntityBase *obj, const char *prefix, const std::string &state,
|
414
|
+
const T &value, JsonDetail start_config) {
|
415
|
+
set_json_value(root, obj, prefix, value, start_config);
|
403
416
|
root["state"] = state;
|
404
417
|
}
|
405
418
|
|
@@ -435,22 +448,26 @@ std::string WebServer::sensor_all_json_generator(WebServer *web_server, void *so
|
|
435
448
|
return web_server->sensor_json((sensor::Sensor *) (source), ((sensor::Sensor *) (source))->state, DETAIL_ALL);
|
436
449
|
}
|
437
450
|
std::string WebServer::sensor_json(sensor::Sensor *obj, float value, JsonDetail start_config) {
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
451
|
+
json::JsonBuilder builder;
|
452
|
+
JsonObject root = builder.root();
|
453
|
+
|
454
|
+
const auto uom_ref = obj->get_unit_of_measurement_ref();
|
455
|
+
|
456
|
+
// Build JSON directly inline
|
457
|
+
std::string state;
|
458
|
+
if (std::isnan(value)) {
|
459
|
+
state = "NA";
|
460
|
+
} else {
|
461
|
+
state = value_accuracy_with_uom_to_string(value, obj->get_accuracy_decimals(), uom_ref);
|
462
|
+
}
|
463
|
+
set_json_icon_state_value(root, obj, "sensor", state, value, start_config);
|
464
|
+
if (start_config == DETAIL_ALL) {
|
465
|
+
this->add_sorting_info_(root, obj);
|
466
|
+
if (!uom_ref.empty())
|
467
|
+
root["uom"] = uom_ref;
|
468
|
+
}
|
469
|
+
|
470
|
+
return builder.serialize();
|
454
471
|
}
|
455
472
|
#endif
|
456
473
|
|
@@ -483,12 +500,15 @@ std::string WebServer::text_sensor_all_json_generator(WebServer *web_server, voi
|
|
483
500
|
}
|
484
501
|
std::string WebServer::text_sensor_json(text_sensor::TextSensor *obj, const std::string &value,
|
485
502
|
JsonDetail start_config) {
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
503
|
+
json::JsonBuilder builder;
|
504
|
+
JsonObject root = builder.root();
|
505
|
+
|
506
|
+
set_json_icon_state_value(root, obj, "text_sensor", value, value, start_config);
|
507
|
+
if (start_config == DETAIL_ALL) {
|
508
|
+
this->add_sorting_info_(root, obj);
|
509
|
+
}
|
510
|
+
|
511
|
+
return builder.serialize();
|
492
512
|
}
|
493
513
|
#endif
|
494
514
|
|
@@ -553,13 +573,16 @@ std::string WebServer::switch_all_json_generator(WebServer *web_server, void *so
|
|
553
573
|
return web_server->switch_json((switch_::Switch *) (source), ((switch_::Switch *) (source))->state, DETAIL_ALL);
|
554
574
|
}
|
555
575
|
std::string WebServer::switch_json(switch_::Switch *obj, bool value, JsonDetail start_config) {
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
576
|
+
json::JsonBuilder builder;
|
577
|
+
JsonObject root = builder.root();
|
578
|
+
|
579
|
+
set_json_icon_state_value(root, obj, "switch", value ? "ON" : "OFF", value, start_config);
|
580
|
+
if (start_config == DETAIL_ALL) {
|
581
|
+
root["assumed_state"] = obj->assumed_state();
|
582
|
+
this->add_sorting_info_(root, obj);
|
583
|
+
}
|
584
|
+
|
585
|
+
return builder.serialize();
|
563
586
|
}
|
564
587
|
#endif
|
565
588
|
|
@@ -590,12 +613,15 @@ std::string WebServer::button_all_json_generator(WebServer *web_server, void *so
|
|
590
613
|
return web_server->button_json((button::Button *) (source), DETAIL_ALL);
|
591
614
|
}
|
592
615
|
std::string WebServer::button_json(button::Button *obj, JsonDetail start_config) {
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
616
|
+
json::JsonBuilder builder;
|
617
|
+
JsonObject root = builder.root();
|
618
|
+
|
619
|
+
set_json_id(root, obj, "button", start_config);
|
620
|
+
if (start_config == DETAIL_ALL) {
|
621
|
+
this->add_sorting_info_(root, obj);
|
622
|
+
}
|
623
|
+
|
624
|
+
return builder.serialize();
|
599
625
|
}
|
600
626
|
#endif
|
601
627
|
|
@@ -627,13 +653,15 @@ std::string WebServer::binary_sensor_all_json_generator(WebServer *web_server, v
|
|
627
653
|
((binary_sensor::BinarySensor *) (source))->state, DETAIL_ALL);
|
628
654
|
}
|
629
655
|
std::string WebServer::binary_sensor_json(binary_sensor::BinarySensor *obj, bool value, JsonDetail start_config) {
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
}
|
656
|
+
json::JsonBuilder builder;
|
657
|
+
JsonObject root = builder.root();
|
658
|
+
|
659
|
+
set_json_icon_state_value(root, obj, "binary_sensor", value ? "ON" : "OFF", value, start_config);
|
660
|
+
if (start_config == DETAIL_ALL) {
|
661
|
+
this->add_sorting_info_(root, obj);
|
662
|
+
}
|
663
|
+
|
664
|
+
return builder.serialize();
|
637
665
|
}
|
638
666
|
#endif
|
639
667
|
|
@@ -694,20 +722,22 @@ std::string WebServer::fan_all_json_generator(WebServer *web_server, void *sourc
|
|
694
722
|
return web_server->fan_json((fan::Fan *) (source), DETAIL_ALL);
|
695
723
|
}
|
696
724
|
std::string WebServer::fan_json(fan::Fan *obj, JsonDetail start_config) {
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
}
|
725
|
+
json::JsonBuilder builder;
|
726
|
+
JsonObject root = builder.root();
|
727
|
+
|
728
|
+
set_json_icon_state_value(root, obj, "fan", obj->state ? "ON" : "OFF", obj->state, start_config);
|
729
|
+
const auto traits = obj->get_traits();
|
730
|
+
if (traits.supports_speed()) {
|
731
|
+
root["speed_level"] = obj->speed;
|
732
|
+
root["speed_count"] = traits.supported_speed_count();
|
733
|
+
}
|
734
|
+
if (obj->get_traits().supports_oscillation())
|
735
|
+
root["oscillation"] = obj->oscillating;
|
736
|
+
if (start_config == DETAIL_ALL) {
|
737
|
+
this->add_sorting_info_(root, obj);
|
738
|
+
}
|
739
|
+
|
740
|
+
return builder.serialize();
|
711
741
|
}
|
712
742
|
#endif
|
713
743
|
|
@@ -767,20 +797,23 @@ std::string WebServer::light_all_json_generator(WebServer *web_server, void *sou
|
|
767
797
|
return web_server->light_json((light::LightState *) (source), DETAIL_ALL);
|
768
798
|
}
|
769
799
|
std::string WebServer::light_json(light::LightState *obj, JsonDetail start_config) {
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
800
|
+
json::JsonBuilder builder;
|
801
|
+
JsonObject root = builder.root();
|
802
|
+
|
803
|
+
set_json_id(root, obj, "light", start_config);
|
804
|
+
root["state"] = obj->remote_values.is_on() ? "ON" : "OFF";
|
805
|
+
|
806
|
+
light::LightJSONSchema::dump_json(*obj, root);
|
807
|
+
if (start_config == DETAIL_ALL) {
|
808
|
+
JsonArray opt = root["effects"].to<JsonArray>();
|
809
|
+
opt.add("None");
|
810
|
+
for (auto const &option : obj->get_effects()) {
|
811
|
+
opt.add(option->get_name());
|
782
812
|
}
|
783
|
-
|
813
|
+
this->add_sorting_info_(root, obj);
|
814
|
+
}
|
815
|
+
|
816
|
+
return builder.serialize();
|
784
817
|
}
|
785
818
|
#endif
|
786
819
|
|
@@ -803,15 +836,28 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa
|
|
803
836
|
}
|
804
837
|
|
805
838
|
auto call = obj->make_call();
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
839
|
+
|
840
|
+
// Lookup table for cover methods
|
841
|
+
static const struct {
|
842
|
+
const char *name;
|
843
|
+
cover::CoverCall &(cover::CoverCall::*action)();
|
844
|
+
} METHODS[] = {
|
845
|
+
{"open", &cover::CoverCall::set_command_open},
|
846
|
+
{"close", &cover::CoverCall::set_command_close},
|
847
|
+
{"stop", &cover::CoverCall::set_command_stop},
|
848
|
+
{"toggle", &cover::CoverCall::set_command_toggle},
|
849
|
+
};
|
850
|
+
|
851
|
+
bool found = false;
|
852
|
+
for (const auto &method : METHODS) {
|
853
|
+
if (match.method_equals(method.name)) {
|
854
|
+
(call.*method.action)();
|
855
|
+
found = true;
|
856
|
+
break;
|
857
|
+
}
|
858
|
+
}
|
859
|
+
|
860
|
+
if (!found && !match.method_equals("set")) {
|
815
861
|
request->send(404);
|
816
862
|
return;
|
817
863
|
}
|
@@ -839,19 +885,22 @@ std::string WebServer::cover_all_json_generator(WebServer *web_server, void *sou
|
|
839
885
|
return web_server->cover_json((cover::Cover *) (source), DETAIL_ALL);
|
840
886
|
}
|
841
887
|
std::string WebServer::cover_json(cover::Cover *obj, JsonDetail start_config) {
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
888
|
+
json::JsonBuilder builder;
|
889
|
+
JsonObject root = builder.root();
|
890
|
+
|
891
|
+
set_json_icon_state_value(root, obj, "cover", obj->is_fully_closed() ? "CLOSED" : "OPEN", obj->position,
|
892
|
+
start_config);
|
893
|
+
root["current_operation"] = cover::cover_operation_to_str(obj->current_operation);
|
894
|
+
|
895
|
+
if (obj->get_traits().get_supports_position())
|
896
|
+
root["position"] = obj->position;
|
897
|
+
if (obj->get_traits().get_supports_tilt())
|
898
|
+
root["tilt"] = obj->tilt;
|
899
|
+
if (start_config == DETAIL_ALL) {
|
900
|
+
this->add_sorting_info_(root, obj);
|
901
|
+
}
|
902
|
+
|
903
|
+
return builder.serialize();
|
855
904
|
}
|
856
905
|
#endif
|
857
906
|
|
@@ -894,31 +943,33 @@ std::string WebServer::number_all_json_generator(WebServer *web_server, void *so
|
|
894
943
|
return web_server->number_json((number::Number *) (source), ((number::Number *) (source))->state, DETAIL_ALL);
|
895
944
|
}
|
896
945
|
std::string WebServer::number_json(number::Number *obj, float value, JsonDetail start_config) {
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
}
|
946
|
+
json::JsonBuilder builder;
|
947
|
+
JsonObject root = builder.root();
|
948
|
+
|
949
|
+
const auto uom_ref = obj->traits.get_unit_of_measurement_ref();
|
950
|
+
|
951
|
+
set_json_id(root, obj, "number", start_config);
|
952
|
+
if (start_config == DETAIL_ALL) {
|
953
|
+
root["min_value"] =
|
954
|
+
value_accuracy_to_string(obj->traits.get_min_value(), step_to_accuracy_decimals(obj->traits.get_step()));
|
955
|
+
root["max_value"] =
|
956
|
+
value_accuracy_to_string(obj->traits.get_max_value(), step_to_accuracy_decimals(obj->traits.get_step()));
|
957
|
+
root["step"] = value_accuracy_to_string(obj->traits.get_step(), step_to_accuracy_decimals(obj->traits.get_step()));
|
958
|
+
root["mode"] = (int) obj->traits.get_mode();
|
959
|
+
if (!uom_ref.empty())
|
960
|
+
root["uom"] = uom_ref;
|
961
|
+
this->add_sorting_info_(root, obj);
|
962
|
+
}
|
963
|
+
if (std::isnan(value)) {
|
964
|
+
root["value"] = "\"NaN\"";
|
965
|
+
root["state"] = "NA";
|
966
|
+
} else {
|
967
|
+
root["value"] = value_accuracy_to_string(value, step_to_accuracy_decimals(obj->traits.get_step()));
|
968
|
+
root["state"] =
|
969
|
+
value_accuracy_with_uom_to_string(value, step_to_accuracy_decimals(obj->traits.get_step()), uom_ref);
|
970
|
+
}
|
971
|
+
|
972
|
+
return builder.serialize();
|
922
973
|
}
|
923
974
|
#endif
|
924
975
|
|
@@ -966,15 +1017,18 @@ std::string WebServer::date_all_json_generator(WebServer *web_server, void *sour
|
|
966
1017
|
return web_server->date_json((datetime::DateEntity *) (source), DETAIL_ALL);
|
967
1018
|
}
|
968
1019
|
std::string WebServer::date_json(datetime::DateEntity *obj, JsonDetail start_config) {
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
1020
|
+
json::JsonBuilder builder;
|
1021
|
+
JsonObject root = builder.root();
|
1022
|
+
|
1023
|
+
set_json_id(root, obj, "date", start_config);
|
1024
|
+
std::string value = str_sprintf("%d-%02d-%02d", obj->year, obj->month, obj->day);
|
1025
|
+
root["value"] = value;
|
1026
|
+
root["state"] = value;
|
1027
|
+
if (start_config == DETAIL_ALL) {
|
1028
|
+
this->add_sorting_info_(root, obj);
|
1029
|
+
}
|
1030
|
+
|
1031
|
+
return builder.serialize();
|
978
1032
|
}
|
979
1033
|
#endif // USE_DATETIME_DATE
|
980
1034
|
|
@@ -1021,15 +1075,18 @@ std::string WebServer::time_all_json_generator(WebServer *web_server, void *sour
|
|
1021
1075
|
return web_server->time_json((datetime::TimeEntity *) (source), DETAIL_ALL);
|
1022
1076
|
}
|
1023
1077
|
std::string WebServer::time_json(datetime::TimeEntity *obj, JsonDetail start_config) {
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1078
|
+
json::JsonBuilder builder;
|
1079
|
+
JsonObject root = builder.root();
|
1080
|
+
|
1081
|
+
set_json_id(root, obj, "time", start_config);
|
1082
|
+
std::string value = str_sprintf("%02d:%02d:%02d", obj->hour, obj->minute, obj->second);
|
1083
|
+
root["value"] = value;
|
1084
|
+
root["state"] = value;
|
1085
|
+
if (start_config == DETAIL_ALL) {
|
1086
|
+
this->add_sorting_info_(root, obj);
|
1087
|
+
}
|
1088
|
+
|
1089
|
+
return builder.serialize();
|
1033
1090
|
}
|
1034
1091
|
#endif // USE_DATETIME_TIME
|
1035
1092
|
|
@@ -1076,16 +1133,19 @@ std::string WebServer::datetime_all_json_generator(WebServer *web_server, void *
|
|
1076
1133
|
return web_server->datetime_json((datetime::DateTimeEntity *) (source), DETAIL_ALL);
|
1077
1134
|
}
|
1078
1135
|
std::string WebServer::datetime_json(datetime::DateTimeEntity *obj, JsonDetail start_config) {
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1136
|
+
json::JsonBuilder builder;
|
1137
|
+
JsonObject root = builder.root();
|
1138
|
+
|
1139
|
+
set_json_id(root, obj, "datetime", start_config);
|
1140
|
+
std::string value =
|
1141
|
+
str_sprintf("%d-%02d-%02d %02d:%02d:%02d", obj->year, obj->month, obj->day, obj->hour, obj->minute, obj->second);
|
1142
|
+
root["value"] = value;
|
1143
|
+
root["state"] = value;
|
1144
|
+
if (start_config == DETAIL_ALL) {
|
1145
|
+
this->add_sorting_info_(root, obj);
|
1146
|
+
}
|
1147
|
+
|
1148
|
+
return builder.serialize();
|
1089
1149
|
}
|
1090
1150
|
#endif // USE_DATETIME_DATETIME
|
1091
1151
|
|
@@ -1128,22 +1188,25 @@ std::string WebServer::text_all_json_generator(WebServer *web_server, void *sour
|
|
1128
1188
|
return web_server->text_json((text::Text *) (source), ((text::Text *) (source))->state, DETAIL_ALL);
|
1129
1189
|
}
|
1130
1190
|
std::string WebServer::text_json(text::Text *obj, const std::string &value, JsonDetail start_config) {
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
root["
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1191
|
+
json::JsonBuilder builder;
|
1192
|
+
JsonObject root = builder.root();
|
1193
|
+
|
1194
|
+
set_json_id(root, obj, "text", start_config);
|
1195
|
+
root["min_length"] = obj->traits.get_min_length();
|
1196
|
+
root["max_length"] = obj->traits.get_max_length();
|
1197
|
+
root["pattern"] = obj->traits.get_pattern();
|
1198
|
+
if (obj->traits.get_mode() == text::TextMode::TEXT_MODE_PASSWORD) {
|
1199
|
+
root["state"] = "********";
|
1200
|
+
} else {
|
1201
|
+
root["state"] = value;
|
1202
|
+
}
|
1203
|
+
root["value"] = value;
|
1204
|
+
if (start_config == DETAIL_ALL) {
|
1205
|
+
root["mode"] = (int) obj->traits.get_mode();
|
1206
|
+
this->add_sorting_info_(root, obj);
|
1207
|
+
}
|
1208
|
+
|
1209
|
+
return builder.serialize();
|
1147
1210
|
}
|
1148
1211
|
#endif
|
1149
1212
|
|
@@ -1186,21 +1249,24 @@ std::string WebServer::select_all_json_generator(WebServer *web_server, void *so
|
|
1186
1249
|
return web_server->select_json((select::Select *) (source), ((select::Select *) (source))->state, DETAIL_ALL);
|
1187
1250
|
}
|
1188
1251
|
std::string WebServer::select_json(select::Select *obj, const std::string &value, JsonDetail start_config) {
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1252
|
+
json::JsonBuilder builder;
|
1253
|
+
JsonObject root = builder.root();
|
1254
|
+
|
1255
|
+
set_json_icon_state_value(root, obj, "select", value, value, start_config);
|
1256
|
+
if (start_config == DETAIL_ALL) {
|
1257
|
+
JsonArray opt = root["option"].to<JsonArray>();
|
1258
|
+
for (auto &option : obj->traits.get_options()) {
|
1259
|
+
opt.add(option);
|
1197
1260
|
}
|
1198
|
-
|
1261
|
+
this->add_sorting_info_(root, obj);
|
1262
|
+
}
|
1263
|
+
|
1264
|
+
return builder.serialize();
|
1199
1265
|
}
|
1200
1266
|
#endif
|
1201
1267
|
|
1202
1268
|
// Longest: HORIZONTAL
|
1203
|
-
#define PSTR_LOCAL(mode_s)
|
1269
|
+
#define PSTR_LOCAL(mode_s) ESPHOME_strncpy_P(buf, (ESPHOME_PGM_P) ((mode_s)), 15)
|
1204
1270
|
|
1205
1271
|
#ifdef USE_CLIMATE
|
1206
1272
|
void WebServer::on_climate_update(climate::Climate *obj) {
|
@@ -1244,98 +1310,102 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url
|
|
1244
1310
|
request->send(404);
|
1245
1311
|
}
|
1246
1312
|
std::string WebServer::climate_state_json_generator(WebServer *web_server, void *source) {
|
1313
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
1247
1314
|
return web_server->climate_json((climate::Climate *) (source), DETAIL_STATE);
|
1248
1315
|
}
|
1249
1316
|
std::string WebServer::climate_all_json_generator(WebServer *web_server, void *source) {
|
1317
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
1250
1318
|
return web_server->climate_json((climate::Climate *) (source), DETAIL_ALL);
|
1251
1319
|
}
|
1252
1320
|
std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_config) {
|
1253
1321
|
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
if (start_config == DETAIL_ALL) {
|
1262
|
-
JsonArray opt = root["modes"].to<JsonArray>();
|
1263
|
-
for (climate::ClimateMode m : traits.get_supported_modes())
|
1264
|
-
opt.add(PSTR_LOCAL(climate::climate_mode_to_string(m)));
|
1265
|
-
if (!traits.get_supported_custom_fan_modes().empty()) {
|
1266
|
-
JsonArray opt = root["fan_modes"].to<JsonArray>();
|
1267
|
-
for (climate::ClimateFanMode m : traits.get_supported_fan_modes())
|
1268
|
-
opt.add(PSTR_LOCAL(climate::climate_fan_mode_to_string(m)));
|
1269
|
-
}
|
1322
|
+
json::JsonBuilder builder;
|
1323
|
+
JsonObject root = builder.root();
|
1324
|
+
set_json_id(root, obj, "climate", start_config);
|
1325
|
+
const auto traits = obj->get_traits();
|
1326
|
+
int8_t target_accuracy = traits.get_target_temperature_accuracy_decimals();
|
1327
|
+
int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals();
|
1328
|
+
char buf[16];
|
1270
1329
|
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
opt.add(PSTR_LOCAL(climate::climate_swing_mode_to_string(swing_mode)));
|
1280
|
-
}
|
1281
|
-
if (traits.get_supports_presets() && obj->preset.has_value()) {
|
1282
|
-
JsonArray opt = root["presets"].to<JsonArray>();
|
1283
|
-
for (climate::ClimatePreset m : traits.get_supported_presets())
|
1284
|
-
opt.add(PSTR_LOCAL(climate::climate_preset_to_string(m)));
|
1285
|
-
}
|
1286
|
-
if (!traits.get_supported_custom_presets().empty() && obj->custom_preset.has_value()) {
|
1287
|
-
JsonArray opt = root["custom_presets"].to<JsonArray>();
|
1288
|
-
for (auto const &custom_preset : traits.get_supported_custom_presets())
|
1289
|
-
opt.add(custom_preset);
|
1290
|
-
}
|
1291
|
-
this->add_sorting_info_(root, obj);
|
1330
|
+
if (start_config == DETAIL_ALL) {
|
1331
|
+
JsonArray opt = root["modes"].to<JsonArray>();
|
1332
|
+
for (climate::ClimateMode m : traits.get_supported_modes())
|
1333
|
+
opt.add(PSTR_LOCAL(climate::climate_mode_to_string(m)));
|
1334
|
+
if (!traits.get_supported_custom_fan_modes().empty()) {
|
1335
|
+
JsonArray opt = root["fan_modes"].to<JsonArray>();
|
1336
|
+
for (climate::ClimateFanMode m : traits.get_supported_fan_modes())
|
1337
|
+
opt.add(PSTR_LOCAL(climate::climate_fan_mode_to_string(m)));
|
1292
1338
|
}
|
1293
1339
|
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
root["step"] = traits.get_visual_target_temperature_step();
|
1299
|
-
if (traits.get_supports_action()) {
|
1300
|
-
root["action"] = PSTR_LOCAL(climate_action_to_string(obj->action));
|
1301
|
-
root["state"] = root["action"];
|
1302
|
-
has_state = true;
|
1340
|
+
if (!traits.get_supported_custom_fan_modes().empty()) {
|
1341
|
+
JsonArray opt = root["custom_fan_modes"].to<JsonArray>();
|
1342
|
+
for (auto const &custom_fan_mode : traits.get_supported_custom_fan_modes())
|
1343
|
+
opt.add(custom_fan_mode);
|
1303
1344
|
}
|
1304
|
-
if (traits.
|
1305
|
-
root["
|
1306
|
-
|
1307
|
-
|
1308
|
-
root["custom_fan_mode"] = obj->custom_fan_mode.value().c_str();
|
1345
|
+
if (traits.get_supports_swing_modes()) {
|
1346
|
+
JsonArray opt = root["swing_modes"].to<JsonArray>();
|
1347
|
+
for (auto swing_mode : traits.get_supported_swing_modes())
|
1348
|
+
opt.add(PSTR_LOCAL(climate::climate_swing_mode_to_string(swing_mode)));
|
1309
1349
|
}
|
1310
1350
|
if (traits.get_supports_presets() && obj->preset.has_value()) {
|
1311
|
-
root["
|
1351
|
+
JsonArray opt = root["presets"].to<JsonArray>();
|
1352
|
+
for (climate::ClimatePreset m : traits.get_supported_presets())
|
1353
|
+
opt.add(PSTR_LOCAL(climate::climate_preset_to_string(m)));
|
1312
1354
|
}
|
1313
1355
|
if (!traits.get_supported_custom_presets().empty() && obj->custom_preset.has_value()) {
|
1314
|
-
root["
|
1356
|
+
JsonArray opt = root["custom_presets"].to<JsonArray>();
|
1357
|
+
for (auto const &custom_preset : traits.get_supported_custom_presets())
|
1358
|
+
opt.add(custom_preset);
|
1315
1359
|
}
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1360
|
+
this->add_sorting_info_(root, obj);
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
bool has_state = false;
|
1364
|
+
root["mode"] = PSTR_LOCAL(climate_mode_to_string(obj->mode));
|
1365
|
+
root["max_temp"] = value_accuracy_to_string(traits.get_visual_max_temperature(), target_accuracy);
|
1366
|
+
root["min_temp"] = value_accuracy_to_string(traits.get_visual_min_temperature(), target_accuracy);
|
1367
|
+
root["step"] = traits.get_visual_target_temperature_step();
|
1368
|
+
if (traits.get_supports_action()) {
|
1369
|
+
root["action"] = PSTR_LOCAL(climate_action_to_string(obj->action));
|
1370
|
+
root["state"] = root["action"];
|
1371
|
+
has_state = true;
|
1372
|
+
}
|
1373
|
+
if (traits.get_supports_fan_modes() && obj->fan_mode.has_value()) {
|
1374
|
+
root["fan_mode"] = PSTR_LOCAL(climate_fan_mode_to_string(obj->fan_mode.value()));
|
1375
|
+
}
|
1376
|
+
if (!traits.get_supported_custom_fan_modes().empty() && obj->custom_fan_mode.has_value()) {
|
1377
|
+
root["custom_fan_mode"] = obj->custom_fan_mode.value().c_str();
|
1378
|
+
}
|
1379
|
+
if (traits.get_supports_presets() && obj->preset.has_value()) {
|
1380
|
+
root["preset"] = PSTR_LOCAL(climate_preset_to_string(obj->preset.value()));
|
1381
|
+
}
|
1382
|
+
if (!traits.get_supported_custom_presets().empty() && obj->custom_preset.has_value()) {
|
1383
|
+
root["custom_preset"] = obj->custom_preset.value().c_str();
|
1384
|
+
}
|
1385
|
+
if (traits.get_supports_swing_modes()) {
|
1386
|
+
root["swing_mode"] = PSTR_LOCAL(climate_swing_mode_to_string(obj->swing_mode));
|
1387
|
+
}
|
1388
|
+
if (traits.get_supports_current_temperature()) {
|
1389
|
+
if (!std::isnan(obj->current_temperature)) {
|
1390
|
+
root["current_temperature"] = value_accuracy_to_string(obj->current_temperature, current_accuracy);
|
1333
1391
|
} else {
|
1334
|
-
root["
|
1335
|
-
if (!has_state)
|
1336
|
-
root["state"] = root["target_temperature"];
|
1392
|
+
root["current_temperature"] = "NA";
|
1337
1393
|
}
|
1338
|
-
}
|
1394
|
+
}
|
1395
|
+
if (traits.get_supports_two_point_target_temperature()) {
|
1396
|
+
root["target_temperature_low"] = value_accuracy_to_string(obj->target_temperature_low, target_accuracy);
|
1397
|
+
root["target_temperature_high"] = value_accuracy_to_string(obj->target_temperature_high, target_accuracy);
|
1398
|
+
if (!has_state) {
|
1399
|
+
root["state"] = value_accuracy_to_string((obj->target_temperature_high + obj->target_temperature_low) / 2.0f,
|
1400
|
+
target_accuracy);
|
1401
|
+
}
|
1402
|
+
} else {
|
1403
|
+
root["target_temperature"] = value_accuracy_to_string(obj->target_temperature, target_accuracy);
|
1404
|
+
if (!has_state)
|
1405
|
+
root["state"] = root["target_temperature"];
|
1406
|
+
}
|
1407
|
+
|
1408
|
+
return builder.serialize();
|
1339
1409
|
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
1340
1410
|
}
|
1341
1411
|
#endif
|
@@ -1401,13 +1471,15 @@ std::string WebServer::lock_all_json_generator(WebServer *web_server, void *sour
|
|
1401
1471
|
return web_server->lock_json((lock::Lock *) (source), ((lock::Lock *) (source))->state, DETAIL_ALL);
|
1402
1472
|
}
|
1403
1473
|
std::string WebServer::lock_json(lock::Lock *obj, lock::LockState value, JsonDetail start_config) {
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
}
|
1474
|
+
json::JsonBuilder builder;
|
1475
|
+
JsonObject root = builder.root();
|
1476
|
+
|
1477
|
+
set_json_icon_state_value(root, obj, "lock", lock::lock_state_to_string(value), value, start_config);
|
1478
|
+
if (start_config == DETAIL_ALL) {
|
1479
|
+
this->add_sorting_info_(root, obj);
|
1480
|
+
}
|
1481
|
+
|
1482
|
+
return builder.serialize();
|
1411
1483
|
}
|
1412
1484
|
#endif
|
1413
1485
|
|
@@ -1430,15 +1502,28 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa
|
|
1430
1502
|
}
|
1431
1503
|
|
1432
1504
|
auto call = obj->make_call();
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1505
|
+
|
1506
|
+
// Lookup table for valve methods
|
1507
|
+
static const struct {
|
1508
|
+
const char *name;
|
1509
|
+
valve::ValveCall &(valve::ValveCall::*action)();
|
1510
|
+
} METHODS[] = {
|
1511
|
+
{"open", &valve::ValveCall::set_command_open},
|
1512
|
+
{"close", &valve::ValveCall::set_command_close},
|
1513
|
+
{"stop", &valve::ValveCall::set_command_stop},
|
1514
|
+
{"toggle", &valve::ValveCall::set_command_toggle},
|
1515
|
+
};
|
1516
|
+
|
1517
|
+
bool found = false;
|
1518
|
+
for (const auto &method : METHODS) {
|
1519
|
+
if (match.method_equals(method.name)) {
|
1520
|
+
(call.*method.action)();
|
1521
|
+
found = true;
|
1522
|
+
break;
|
1523
|
+
}
|
1524
|
+
}
|
1525
|
+
|
1526
|
+
if (!found && !match.method_equals("set")) {
|
1442
1527
|
request->send(404);
|
1443
1528
|
return;
|
1444
1529
|
}
|
@@ -1464,17 +1549,20 @@ std::string WebServer::valve_all_json_generator(WebServer *web_server, void *sou
|
|
1464
1549
|
return web_server->valve_json((valve::Valve *) (source), DETAIL_ALL);
|
1465
1550
|
}
|
1466
1551
|
std::string WebServer::valve_json(valve::Valve *obj, JsonDetail start_config) {
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1552
|
+
json::JsonBuilder builder;
|
1553
|
+
JsonObject root = builder.root();
|
1554
|
+
|
1555
|
+
set_json_icon_state_value(root, obj, "valve", obj->is_fully_closed() ? "CLOSED" : "OPEN", obj->position,
|
1556
|
+
start_config);
|
1557
|
+
root["current_operation"] = valve::valve_operation_to_str(obj->current_operation);
|
1558
|
+
|
1559
|
+
if (obj->get_traits().get_supports_position())
|
1560
|
+
root["position"] = obj->position;
|
1561
|
+
if (start_config == DETAIL_ALL) {
|
1562
|
+
this->add_sorting_info_(root, obj);
|
1563
|
+
}
|
1564
|
+
|
1565
|
+
return builder.serialize();
|
1478
1566
|
}
|
1479
1567
|
#endif
|
1480
1568
|
|
@@ -1499,17 +1587,28 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques
|
|
1499
1587
|
auto call = obj->make_call();
|
1500
1588
|
parse_string_param_(request, "code", call, &decltype(call)::set_code);
|
1501
1589
|
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
}
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
}
|
1590
|
+
// Lookup table for alarm control panel methods
|
1591
|
+
static const struct {
|
1592
|
+
const char *name;
|
1593
|
+
alarm_control_panel::AlarmControlPanelCall &(alarm_control_panel::AlarmControlPanelCall::*action)();
|
1594
|
+
} METHODS[] = {
|
1595
|
+
{"disarm", &alarm_control_panel::AlarmControlPanelCall::disarm},
|
1596
|
+
{"arm_away", &alarm_control_panel::AlarmControlPanelCall::arm_away},
|
1597
|
+
{"arm_home", &alarm_control_panel::AlarmControlPanelCall::arm_home},
|
1598
|
+
{"arm_night", &alarm_control_panel::AlarmControlPanelCall::arm_night},
|
1599
|
+
{"arm_vacation", &alarm_control_panel::AlarmControlPanelCall::arm_vacation},
|
1600
|
+
};
|
1601
|
+
|
1602
|
+
bool found = false;
|
1603
|
+
for (const auto &method : METHODS) {
|
1604
|
+
if (match.method_equals(method.name)) {
|
1605
|
+
(call.*method.action)();
|
1606
|
+
found = true;
|
1607
|
+
break;
|
1608
|
+
}
|
1609
|
+
}
|
1610
|
+
|
1611
|
+
if (!found) {
|
1513
1612
|
request->send(404);
|
1514
1613
|
return;
|
1515
1614
|
}
|
@@ -1533,14 +1632,17 @@ std::string WebServer::alarm_control_panel_all_json_generator(WebServer *web_ser
|
|
1533
1632
|
std::string WebServer::alarm_control_panel_json(alarm_control_panel::AlarmControlPanel *obj,
|
1534
1633
|
alarm_control_panel::AlarmControlPanelState value,
|
1535
1634
|
JsonDetail start_config) {
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1635
|
+
json::JsonBuilder builder;
|
1636
|
+
JsonObject root = builder.root();
|
1637
|
+
|
1638
|
+
char buf[16];
|
1639
|
+
set_json_icon_state_value(root, obj, "alarm-control-panel", PSTR_LOCAL(alarm_control_panel_state_to_string(value)),
|
1640
|
+
value, start_config);
|
1641
|
+
if (start_config == DETAIL_ALL) {
|
1642
|
+
this->add_sorting_info_(root, obj);
|
1643
|
+
}
|
1644
|
+
|
1645
|
+
return builder.serialize();
|
1544
1646
|
}
|
1545
1647
|
#endif
|
1546
1648
|
|
@@ -1577,20 +1679,23 @@ std::string WebServer::event_all_json_generator(WebServer *web_server, void *sou
|
|
1577
1679
|
return web_server->event_json(event, get_event_type(event), DETAIL_ALL);
|
1578
1680
|
}
|
1579
1681
|
std::string WebServer::event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config) {
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
|
-
this->add_sorting_info_(root, obj);
|
1682
|
+
json::JsonBuilder builder;
|
1683
|
+
JsonObject root = builder.root();
|
1684
|
+
|
1685
|
+
set_json_id(root, obj, "event", start_config);
|
1686
|
+
if (!event_type.empty()) {
|
1687
|
+
root["event_type"] = event_type;
|
1688
|
+
}
|
1689
|
+
if (start_config == DETAIL_ALL) {
|
1690
|
+
JsonArray event_types = root["event_types"].to<JsonArray>();
|
1691
|
+
for (auto const &event_type : obj->get_event_types()) {
|
1692
|
+
event_types.add(event_type);
|
1592
1693
|
}
|
1593
|
-
|
1694
|
+
root["device_class"] = obj->get_device_class_ref();
|
1695
|
+
this->add_sorting_info_(root, obj);
|
1696
|
+
}
|
1697
|
+
|
1698
|
+
return builder.serialize();
|
1594
1699
|
}
|
1595
1700
|
#endif
|
1596
1701
|
|
@@ -1637,25 +1742,30 @@ void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlM
|
|
1637
1742
|
request->send(404);
|
1638
1743
|
}
|
1639
1744
|
std::string WebServer::update_state_json_generator(WebServer *web_server, void *source) {
|
1745
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
1640
1746
|
return web_server->update_json((update::UpdateEntity *) (source), DETAIL_STATE);
|
1641
1747
|
}
|
1642
1748
|
std::string WebServer::update_all_json_generator(WebServer *web_server, void *source) {
|
1749
|
+
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
1643
1750
|
return web_server->update_json((update::UpdateEntity *) (source), DETAIL_STATE);
|
1644
1751
|
}
|
1645
1752
|
std::string WebServer::update_json(update::UpdateEntity *obj, JsonDetail start_config) {
|
1646
1753
|
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1656
|
-
|
1657
|
-
|
1658
|
-
|
1754
|
+
json::JsonBuilder builder;
|
1755
|
+
JsonObject root = builder.root();
|
1756
|
+
|
1757
|
+
set_json_id(root, obj, "update", start_config);
|
1758
|
+
root["value"] = obj->update_info.latest_version;
|
1759
|
+
root["state"] = update_state_to_string(obj->state);
|
1760
|
+
if (start_config == DETAIL_ALL) {
|
1761
|
+
root["current_version"] = obj->update_info.current_version;
|
1762
|
+
root["title"] = obj->update_info.title;
|
1763
|
+
root["summary"] = obj->update_info.summary;
|
1764
|
+
root["release_url"] = obj->update_info.release_url;
|
1765
|
+
this->add_sorting_info_(root, obj);
|
1766
|
+
}
|
1767
|
+
|
1768
|
+
return builder.serialize();
|
1659
1769
|
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
1660
1770
|
}
|
1661
1771
|
#endif
|
@@ -1664,24 +1774,24 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) const {
|
|
1664
1774
|
const auto &url = request->url();
|
1665
1775
|
const auto method = request->method();
|
1666
1776
|
|
1667
|
-
//
|
1668
|
-
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
1672
|
-
if (url == "/events")
|
1673
|
-
return true;
|
1777
|
+
// Static URL checks
|
1778
|
+
static const char *const STATIC_URLS[] = {
|
1779
|
+
"/",
|
1780
|
+
#if !defined(USE_ESP32) && defined(USE_ARDUINO)
|
1781
|
+
"/events",
|
1674
1782
|
#endif
|
1675
|
-
|
1676
1783
|
#ifdef USE_WEBSERVER_CSS_INCLUDE
|
1677
|
-
|
1678
|
-
return true;
|
1784
|
+
"/0.css",
|
1679
1785
|
#endif
|
1680
|
-
|
1681
1786
|
#ifdef USE_WEBSERVER_JS_INCLUDE
|
1682
|
-
|
1683
|
-
return true;
|
1787
|
+
"/0.js",
|
1684
1788
|
#endif
|
1789
|
+
};
|
1790
|
+
|
1791
|
+
for (const auto &static_url : STATIC_URLS) {
|
1792
|
+
if (url == static_url)
|
1793
|
+
return true;
|
1794
|
+
}
|
1685
1795
|
|
1686
1796
|
#ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
|
1687
1797
|
if (method == HTTP_OPTIONS && request->hasHeader(HEADER_CORS_REQ_PNA))
|
@@ -1701,92 +1811,87 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) const {
|
|
1701
1811
|
if (!is_get_or_post)
|
1702
1812
|
return false;
|
1703
1813
|
|
1704
|
-
//
|
1705
|
-
|
1814
|
+
// Use lookup tables for domain checks
|
1815
|
+
static const char *const GET_ONLY_DOMAINS[] = {
|
1706
1816
|
#ifdef USE_SENSOR
|
1707
|
-
|
1708
|
-
return true;
|
1817
|
+
"sensor",
|
1709
1818
|
#endif
|
1710
1819
|
#ifdef USE_BINARY_SENSOR
|
1711
|
-
|
1712
|
-
return true;
|
1820
|
+
"binary_sensor",
|
1713
1821
|
#endif
|
1714
1822
|
#ifdef USE_TEXT_SENSOR
|
1715
|
-
|
1716
|
-
return true;
|
1823
|
+
"text_sensor",
|
1717
1824
|
#endif
|
1718
1825
|
#ifdef USE_EVENT
|
1719
|
-
|
1720
|
-
return true;
|
1826
|
+
"event",
|
1721
1827
|
#endif
|
1722
|
-
}
|
1828
|
+
};
|
1723
1829
|
|
1724
|
-
|
1725
|
-
if (is_get_or_post) {
|
1830
|
+
static const char *const GET_POST_DOMAINS[] = {
|
1726
1831
|
#ifdef USE_SWITCH
|
1727
|
-
|
1728
|
-
return true;
|
1832
|
+
"switch",
|
1729
1833
|
#endif
|
1730
1834
|
#ifdef USE_BUTTON
|
1731
|
-
|
1732
|
-
return true;
|
1835
|
+
"button",
|
1733
1836
|
#endif
|
1734
1837
|
#ifdef USE_FAN
|
1735
|
-
|
1736
|
-
return true;
|
1838
|
+
"fan",
|
1737
1839
|
#endif
|
1738
1840
|
#ifdef USE_LIGHT
|
1739
|
-
|
1740
|
-
return true;
|
1841
|
+
"light",
|
1741
1842
|
#endif
|
1742
1843
|
#ifdef USE_COVER
|
1743
|
-
|
1744
|
-
return true;
|
1844
|
+
"cover",
|
1745
1845
|
#endif
|
1746
1846
|
#ifdef USE_NUMBER
|
1747
|
-
|
1748
|
-
return true;
|
1847
|
+
"number",
|
1749
1848
|
#endif
|
1750
1849
|
#ifdef USE_DATETIME_DATE
|
1751
|
-
|
1752
|
-
return true;
|
1850
|
+
"date",
|
1753
1851
|
#endif
|
1754
1852
|
#ifdef USE_DATETIME_TIME
|
1755
|
-
|
1756
|
-
return true;
|
1853
|
+
"time",
|
1757
1854
|
#endif
|
1758
1855
|
#ifdef USE_DATETIME_DATETIME
|
1759
|
-
|
1760
|
-
return true;
|
1856
|
+
"datetime",
|
1761
1857
|
#endif
|
1762
1858
|
#ifdef USE_TEXT
|
1763
|
-
|
1764
|
-
return true;
|
1859
|
+
"text",
|
1765
1860
|
#endif
|
1766
1861
|
#ifdef USE_SELECT
|
1767
|
-
|
1768
|
-
return true;
|
1862
|
+
"select",
|
1769
1863
|
#endif
|
1770
1864
|
#ifdef USE_CLIMATE
|
1771
|
-
|
1772
|
-
return true;
|
1865
|
+
"climate",
|
1773
1866
|
#endif
|
1774
1867
|
#ifdef USE_LOCK
|
1775
|
-
|
1776
|
-
return true;
|
1868
|
+
"lock",
|
1777
1869
|
#endif
|
1778
1870
|
#ifdef USE_VALVE
|
1779
|
-
|
1780
|
-
return true;
|
1871
|
+
"valve",
|
1781
1872
|
#endif
|
1782
1873
|
#ifdef USE_ALARM_CONTROL_PANEL
|
1783
|
-
|
1784
|
-
return true;
|
1874
|
+
"alarm_control_panel",
|
1785
1875
|
#endif
|
1786
1876
|
#ifdef USE_UPDATE
|
1787
|
-
|
1788
|
-
return true;
|
1877
|
+
"update",
|
1789
1878
|
#endif
|
1879
|
+
};
|
1880
|
+
|
1881
|
+
// Check GET-only domains
|
1882
|
+
if (is_get) {
|
1883
|
+
for (const auto &domain : GET_ONLY_DOMAINS) {
|
1884
|
+
if (match.domain_equals(domain))
|
1885
|
+
return true;
|
1886
|
+
}
|
1887
|
+
}
|
1888
|
+
|
1889
|
+
// Check GET+POST domains
|
1890
|
+
if (is_get_or_post) {
|
1891
|
+
for (const auto &domain : GET_POST_DOMAINS) {
|
1892
|
+
if (match.domain_equals(domain))
|
1893
|
+
return true;
|
1894
|
+
}
|
1790
1895
|
}
|
1791
1896
|
|
1792
1897
|
return false;
|
@@ -1800,7 +1905,7 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) {
|
|
1800
1905
|
return;
|
1801
1906
|
}
|
1802
1907
|
|
1803
|
-
#
|
1908
|
+
#if !defined(USE_ESP32) && defined(USE_ARDUINO)
|
1804
1909
|
if (url == "/events") {
|
1805
1910
|
this->events_.add_new_client(this, request);
|
1806
1911
|
return;
|