esphome 2025.6.2__py3-none-any.whl → 2025.7.0__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 +1 -3
- esphome/codegen.py +2 -0
- esphome/components/ac_dimmer/ac_dimmer.cpp +6 -6
- esphome/components/adc/__init__.py +25 -1
- esphome/components/adc/adc_sensor.h +11 -11
- esphome/components/adc/adc_sensor_common.cpp +1 -1
- esphome/components/adc/adc_sensor_esp32.cpp +16 -8
- esphome/components/ade7880/ade7880.h +0 -2
- esphome/components/ads1115/ads1115.h +0 -1
- esphome/components/ads1118/ads1118.h +0 -1
- esphome/components/ags10/ags10.h +0 -2
- esphome/components/aic3204/aic3204.h +0 -1
- esphome/components/alarm_control_panel/__init__.py +5 -2
- esphome/components/alpha3/alpha3.h +0 -1
- esphome/components/am43/cover/am43_cover.h +0 -1
- esphome/components/am43/sensor/am43_sensor.h +0 -1
- esphome/components/analog_threshold/analog_threshold_binary_sensor.h +0 -2
- esphome/components/anova/anova.cpp +5 -1
- esphome/components/anova/anova.h +0 -1
- esphome/components/apds9960/apds9960.cpp +1 -1
- esphome/components/api/__init__.py +57 -21
- esphome/components/api/api_connection.cpp +344 -539
- esphome/components/api/api_connection.h +224 -141
- esphome/components/api/api_frame_helper.cpp +91 -127
- esphome/components/api/api_frame_helper.h +64 -54
- esphome/components/api/api_pb2.cpp +1837 -9044
- esphome/components/api/api_pb2.h +532 -685
- esphome/components/api/api_pb2_dump.cpp +4432 -0
- esphome/components/api/api_pb2_service.cpp +184 -425
- esphome/components/api/api_pb2_service.h +13 -6
- esphome/components/api/api_server.cpp +131 -167
- esphome/components/api/api_server.h +38 -10
- esphome/components/api/client.py +10 -4
- esphome/components/api/custom_api_device.h +8 -0
- esphome/components/api/list_entities.cpp +37 -104
- esphome/components/api/list_entities.h +33 -23
- esphome/components/api/proto.h +532 -26
- esphome/components/api/subscribe_state.cpp +23 -29
- esphome/components/api/subscribe_state.h +26 -19
- esphome/components/api/user_services.h +2 -0
- esphome/components/as3935_spi/as3935_spi.h +0 -2
- esphome/components/as5600/as5600.h +0 -1
- esphome/components/async_tcp/__init__.py +14 -5
- esphome/components/atc_mithermometer/atc_mithermometer.h +0 -1
- esphome/components/atm90e32/atm90e32.cpp +2 -1
- esphome/components/audio/audio_decoder.cpp +1 -1
- esphome/components/audio/audio_transfer_buffer.cpp +2 -2
- esphome/components/b_parasite/b_parasite.h +0 -1
- esphome/components/bedjet/bedjet_hub.cpp +5 -1
- esphome/components/bedjet/climate/bedjet_climate.cpp +5 -1
- esphome/components/beken_spi_led_strip/led_strip.cpp +4 -2
- esphome/components/bh1750/bh1750.cpp +5 -5
- esphome/components/binary_sensor/__init__.py +82 -5
- esphome/components/binary_sensor/automation.h +19 -1
- esphome/components/binary_sensor/binary_sensor.cpp +12 -30
- esphome/components/binary_sensor/binary_sensor.h +11 -25
- esphome/components/binary_sensor/filter.cpp +29 -24
- esphome/components/binary_sensor/filter.h +20 -10
- esphome/components/ble_client/output/ble_binary_output.h +0 -1
- esphome/components/ble_client/sensor/ble_rssi_sensor.cpp +5 -1
- esphome/components/ble_client/sensor/ble_rssi_sensor.h +0 -1
- esphome/components/ble_client/sensor/ble_sensor.cpp +5 -1
- esphome/components/ble_client/sensor/ble_sensor.h +0 -1
- esphome/components/ble_client/switch/ble_switch.h +0 -1
- esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +5 -1
- esphome/components/ble_client/text_sensor/ble_text_sensor.h +0 -1
- esphome/components/ble_presence/ble_presence_device.h +0 -1
- esphome/components/ble_rssi/ble_rssi_sensor.h +0 -1
- esphome/components/ble_scanner/ble_scanner.h +0 -1
- esphome/components/bluetooth_proxy/bluetooth_connection.h +9 -2
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +16 -6
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -2
- esphome/components/bme680/sensor.py +1 -1
- esphome/components/bmp581/bmp581.h +0 -2
- esphome/components/button/__init__.py +5 -2
- esphome/components/camera/__init__.py +1 -0
- esphome/components/camera/camera.cpp +22 -0
- esphome/components/camera/camera.h +80 -0
- esphome/components/canbus/__init__.py +1 -0
- esphome/components/cap1188/cap1188.h +0 -1
- esphome/components/captive_portal/__init__.py +12 -2
- esphome/components/captive_portal/captive_portal.cpp +12 -2
- esphome/components/captive_portal/captive_portal.h +5 -2
- esphome/components/ccs811/ccs811.h +0 -2
- esphome/components/climate/__init__.py +5 -2
- esphome/components/cm1106/sensor.py +2 -2
- esphome/components/const/__init__.py +2 -0
- esphome/components/copy/binary_sensor/copy_binary_sensor.h +0 -1
- esphome/components/copy/button/copy_button.h +0 -1
- esphome/components/copy/cover/copy_cover.h +0 -1
- esphome/components/copy/fan/copy_fan.h +0 -1
- esphome/components/copy/lock/copy_lock.h +0 -1
- esphome/components/copy/number/copy_number.h +0 -1
- esphome/components/copy/select/copy_select.h +0 -1
- esphome/components/copy/sensor/copy_sensor.h +0 -1
- esphome/components/copy/switch/copy_switch.h +0 -1
- esphome/components/copy/text/copy_text.h +0 -1
- esphome/components/copy/text_sensor/copy_text_sensor.h +0 -1
- esphome/components/cover/__init__.py +5 -2
- esphome/components/cs5460a/cs5460a.h +0 -1
- esphome/components/datetime/__init__.py +4 -2
- esphome/components/debug/__init__.py +20 -0
- esphome/components/debug/debug_esp32.cpp +2 -0
- esphome/components/deep_sleep/__init__.py +43 -9
- esphome/components/demo/__init__.py +2 -2
- esphome/components/display/display.cpp +4 -3
- esphome/components/display/display.h +0 -2
- esphome/components/display/display_buffer.cpp +1 -1
- esphome/components/ds2484/__init__.py +1 -0
- esphome/components/ds2484/ds2484.cpp +209 -0
- esphome/components/ds2484/ds2484.h +43 -0
- esphome/components/ds2484/one_wire.py +37 -0
- esphome/components/duty_time/duty_time_sensor.h +0 -1
- esphome/components/ens160_base/ens160_base.h +0 -1
- esphome/components/es7210/es7210.h +0 -1
- esphome/components/es7243e/es7243e.h +0 -1
- esphome/components/es8156/es8156.h +0 -1
- esphome/components/es8311/es8311.h +0 -1
- esphome/components/es8388/es8388.h +0 -1
- esphome/components/esp32/__init__.py +103 -135
- esphome/components/esp32/core.cpp +0 -4
- esphome/components/esp32/gpio.h +1 -1
- esphome/components/esp32/helpers.cpp +69 -0
- esphome/components/esp32_ble/ble.cpp +5 -6
- esphome/components/esp32_ble/ble.h +29 -14
- esphome/components/esp32_ble/ble_event.h +6 -6
- esphome/components/esp32_ble_client/ble_client_base.cpp +21 -6
- esphome/components/esp32_ble_client/ble_client_base.h +24 -9
- esphome/components/esp32_ble_tracker/__init__.py +2 -8
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +5 -5
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +11 -7
- esphome/components/esp32_camera/__init__.py +112 -98
- esphome/components/esp32_camera/esp32_camera.cpp +41 -31
- esphome/components/esp32_camera/esp32_camera.h +35 -30
- esphome/components/esp32_camera_web_server/__init__.py +2 -1
- esphome/components/esp32_camera_web_server/camera_web_server.cpp +8 -8
- esphome/components/esp32_camera_web_server/camera_web_server.h +3 -3
- esphome/components/esp32_hall/sensor.py +2 -21
- esphome/components/esp32_hosted/__init__.py +101 -0
- esphome/components/esp32_hosted/esp32_hosted.py.script +12 -0
- esphome/components/esp32_improv/esp32_improv_component.cpp +3 -0
- esphome/components/esp32_rmt/__init__.py +0 -58
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +77 -63
- esphome/components/esp32_rmt_led_strip/led_strip.h +11 -17
- esphome/components/esp32_rmt_led_strip/light.py +14 -76
- esphome/components/esp32_touch/esp32_touch.h +174 -28
- esphome/components/esp32_touch/esp32_touch_common.cpp +162 -0
- esphome/components/esp32_touch/esp32_touch_v1.cpp +240 -0
- esphome/components/esp32_touch/esp32_touch_v2.cpp +397 -0
- esphome/components/esp8266/__init__.py +2 -0
- esphome/components/esp8266/gpio.cpp +10 -10
- esphome/components/esp8266/helpers.cpp +31 -0
- esphome/components/esp_ldo/__init__.py +10 -8
- esphome/components/esp_ldo/esp_ldo.h +3 -0
- esphome/components/esphome/ota/__init__.py +1 -0
- esphome/components/esphome/ota/ota_esphome.cpp +24 -19
- esphome/components/ethernet/__init__.py +42 -23
- esphome/components/ethernet/esp_eth_phy_jl1101.c +0 -16
- esphome/components/ethernet/ethernet_component.cpp +69 -29
- esphome/components/ethernet/ethernet_component.h +18 -10
- esphome/components/event/__init__.py +5 -2
- esphome/components/ezo/ezo.h +0 -1
- esphome/components/ezo_pmp/ezo_pmp.h +0 -1
- esphome/components/fan/__init__.py +5 -2
- esphome/components/fan/fan.cpp +4 -0
- esphome/components/feedback/feedback_cover.h +0 -1
- esphome/components/font/__init__.py +92 -82
- esphome/components/font/font.cpp +9 -2
- esphome/components/font/font.h +20 -5
- esphome/components/fs3000/fs3000.h +0 -1
- esphome/components/gcja5/gcja5.h +0 -1
- esphome/components/gl_r01_i2c/__init__.py +0 -0
- esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +68 -0
- esphome/components/gl_r01_i2c/gl_r01_i2c.h +22 -0
- esphome/components/gl_r01_i2c/sensor.py +36 -0
- esphome/components/gp8403/gp8403.h +0 -1
- esphome/components/gpio/binary_sensor/__init__.py +39 -1
- esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +77 -3
- esphome/components/gpio/binary_sensor/gpio_binary_sensor.h +40 -0
- esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +0 -2
- esphome/components/he60r/he60r.h +0 -1
- esphome/components/heatpumpir/climate.py +2 -1
- esphome/components/heatpumpir/heatpumpir.cpp +1 -0
- esphome/components/heatpumpir/heatpumpir.h +1 -0
- esphome/components/honeywellabp2_i2c/honeywellabp2.h +0 -1
- esphome/components/host/__init__.py +3 -1
- esphome/components/host/helpers.cpp +57 -0
- esphome/components/http_request/__init__.py +19 -1
- esphome/components/http_request/http_request.h +1 -1
- esphome/components/http_request/http_request_arduino.cpp +0 -1
- esphome/components/http_request/http_request_arduino.h +1 -0
- esphome/components/http_request/http_request_idf.cpp +0 -1
- esphome/components/http_request/ota/ota_http_request.cpp +1 -1
- esphome/components/http_request/update/http_request_update.cpp +35 -16
- esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +3 -9
- esphome/components/hydreon_rgxx/sensor.py +1 -1
- esphome/components/i2c/__init__.py +23 -11
- esphome/components/i2c/i2c_bus.h +8 -1
- esphome/components/i2c/i2c_bus_arduino.cpp +4 -3
- esphome/components/i2c/i2c_bus_arduino.h +6 -3
- esphome/components/i2c/i2c_bus_esp_idf.h +5 -3
- esphome/components/i2c_device/i2c_device.h +0 -1
- esphome/components/i2s_audio/__init__.py +2 -10
- esphome/components/i2s_audio/i2s_audio.cpp +1 -5
- esphome/components/i2s_audio/media_player/__init__.py +2 -2
- esphome/components/i2s_audio/speaker/__init__.py +1 -1
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +2 -2
- esphome/components/iaqcore/iaqcore.h +0 -2
- esphome/components/image/__init__.py +123 -24
- esphome/components/improv_serial/improv_serial_component.cpp +0 -4
- esphome/components/ina219/ina219.cpp +7 -0
- esphome/components/ina219/ina219.h +1 -0
- esphome/components/ina260/ina260.h +0 -2
- esphome/components/inkbird_ibsth1_mini/inkbird_ibsth1_mini.h +0 -1
- esphome/components/inkplate6/display.py +15 -0
- esphome/components/inkplate6/inkplate.cpp +2 -2
- esphome/components/integration/integration_sensor.h +0 -1
- esphome/components/internal_temperature/internal_temperature.cpp +8 -27
- esphome/components/internal_temperature/sensor.py +0 -26
- esphome/components/interval/interval.h +0 -2
- esphome/components/json/__init__.py +1 -1
- esphome/components/json/json_util.cpp +56 -63
- esphome/components/ld2410/button/__init__.py +3 -3
- esphome/components/ld2410/button/factory_reset_button.cpp +9 -0
- esphome/components/ld2410/button/{reset_button.h → factory_reset_button.h} +2 -2
- esphome/components/ld2410/ld2410.cpp +421 -268
- esphome/components/ld2410/ld2410.h +44 -146
- esphome/components/ld2410/number/__init__.py +2 -2
- esphome/components/ld2410/sensor.py +1 -1
- esphome/components/ld2410/switch/__init__.py +1 -1
- esphome/components/ld2420/binary_sensor/ld2420_binary_sensor.cpp +2 -2
- esphome/components/ld2420/button/reconfig_buttons.cpp +1 -1
- esphome/components/ld2420/ld2420.cpp +252 -147
- esphome/components/ld2420/ld2420.h +52 -126
- esphome/components/ld2420/number/__init__.py +2 -2
- esphome/components/ld2420/number/gate_config_number.cpp +1 -1
- esphome/components/ld2420/select/operating_mode_select.cpp +1 -1
- esphome/components/ld2420/sensor/__init__.py +6 -2
- esphome/components/ld2420/sensor/ld2420_sensor.cpp +2 -2
- esphome/components/ld2420/sensor/ld2420_sensor.h +1 -1
- esphome/components/ld2420/text_sensor/text_sensor.cpp +2 -2
- esphome/components/ld2450/button/__init__.py +3 -3
- esphome/components/ld2450/button/factory_reset_button.cpp +9 -0
- esphome/components/ld2450/button/{reset_button.h → factory_reset_button.h} +2 -2
- esphome/components/ld2450/ld2450.cpp +384 -232
- esphome/components/ld2450/ld2450.h +60 -69
- esphome/components/ld2450/switch/__init__.py +1 -1
- esphome/components/ledc/ledc_output.cpp +1 -63
- esphome/components/libretiny/__init__.py +5 -3
- esphome/components/libretiny/const.py +5 -0
- esphome/components/libretiny/generate_components.py +1 -0
- esphome/components/libretiny/helpers.cpp +35 -0
- esphome/components/libretiny/lt_component.cpp +5 -3
- esphome/components/light/__init__.py +4 -2
- esphome/components/light/addressable_light.h +3 -3
- esphome/components/light/light_call.cpp +180 -243
- esphome/components/light/light_call.h +72 -20
- esphome/components/light/light_color_values.h +14 -14
- esphome/components/light/light_json_schema.cpp +17 -16
- esphome/components/light/light_state.h +15 -13
- esphome/components/light/transformers.h +2 -2
- esphome/components/ln882x/__init__.py +52 -0
- esphome/components/ln882x/boards.py +285 -0
- esphome/components/lock/__init__.py +5 -2
- esphome/components/logger/__init__.py +40 -3
- esphome/components/logger/logger.cpp +47 -12
- esphome/components/logger/logger.h +80 -49
- esphome/components/logger/logger_esp32.cpp +3 -3
- esphome/components/lps22/__init__.py +0 -0
- esphome/components/lps22/lps22.cpp +75 -0
- esphome/components/lps22/lps22.h +27 -0
- esphome/components/lps22/sensor.py +58 -0
- esphome/components/ltr390/ltr390.h +0 -1
- esphome/components/ltr501/ltr501.h +0 -1
- esphome/components/ltr_als_ps/ltr_als_ps.h +0 -1
- esphome/components/lvgl/__init__.py +1 -1
- esphome/components/lvgl/schemas.py +66 -6
- esphome/components/lvgl/styles.py +24 -16
- esphome/components/lvgl/widgets/__init__.py +12 -2
- esphome/components/lvgl/widgets/lv_bar.py +40 -19
- esphome/components/lvgl/widgets/meter.py +20 -13
- esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +1 -1
- esphome/components/max9611/max9611.h +0 -1
- esphome/components/mcp23016/__init__.py +1 -1
- esphome/components/mcp23xxx_base/__init__.py +1 -1
- esphome/components/mcp4461/__init__.py +1 -1
- esphome/components/mcp4461/output/__init__.py +3 -2
- esphome/components/mcp9600/mcp9600.h +0 -2
- esphome/components/md5/md5.cpp +3 -3
- esphome/components/md5/md5.h +1 -6
- esphome/components/mdns/__init__.py +22 -11
- esphome/components/media_player/__init__.py +4 -3
- esphome/components/micro_wake_word/__init__.py +1 -5
- esphome/components/micro_wake_word/streaming_model.cpp +2 -2
- esphome/components/microphone/microphone.cpp +7 -9
- esphome/components/microphone/microphone.h +0 -2
- esphome/components/mipi_spi/display.py +1 -0
- esphome/components/mmc5603/mmc5603.cpp +1 -1
- esphome/components/modbus/modbus.cpp +33 -15
- esphome/components/modbus/modbus.h +9 -0
- esphome/components/modbus_controller/__init__.py +42 -10
- esphome/components/modbus_controller/modbus_controller.cpp +92 -11
- esphome/components/modbus_controller/modbus_controller.h +61 -7
- esphome/components/mopeka_pro_check/mopeka_pro_check.h +0 -1
- esphome/components/mopeka_std_check/mopeka_std_check.h +0 -1
- esphome/components/mpl3115a2/mpl3115a2.h +0 -2
- esphome/components/mqtt/__init__.py +16 -0
- esphome/components/mqtt/mqtt_alarm_control_panel.cpp +2 -1
- esphome/components/mqtt/mqtt_backend.h +2 -1
- esphome/components/mqtt/mqtt_backend_esp32.cpp +132 -47
- esphome/components/mqtt/mqtt_backend_esp32.h +106 -4
- esphome/components/mqtt/mqtt_binary_sensor.cpp +1 -0
- esphome/components/mqtt/mqtt_button.cpp +4 -1
- esphome/components/mqtt/mqtt_client.cpp +17 -9
- esphome/components/mqtt/mqtt_client.h +8 -3
- esphome/components/mqtt/mqtt_climate.cpp +6 -4
- esphome/components/mqtt/mqtt_component.cpp +3 -1
- esphome/components/mqtt/mqtt_cover.cpp +1 -0
- esphome/components/mqtt/mqtt_date.cpp +4 -3
- esphome/components/mqtt/mqtt_datetime.cpp +7 -6
- esphome/components/mqtt/mqtt_event.cpp +6 -3
- esphome/components/mqtt/mqtt_fan.cpp +1 -0
- esphome/components/mqtt/mqtt_light.cpp +8 -4
- esphome/components/mqtt/mqtt_lock.cpp +3 -1
- esphome/components/mqtt/mqtt_number.cpp +1 -0
- esphome/components/mqtt/mqtt_select.cpp +2 -1
- esphome/components/mqtt/mqtt_sensor.cpp +3 -1
- esphome/components/mqtt/mqtt_switch.cpp +3 -1
- esphome/components/mqtt/mqtt_text.cpp +1 -0
- esphome/components/mqtt/mqtt_text_sensor.cpp +3 -1
- esphome/components/mqtt/mqtt_time.cpp +4 -3
- esphome/components/mqtt/mqtt_update.cpp +1 -0
- esphome/components/mqtt/mqtt_valve.cpp +3 -1
- esphome/components/ms8607/ms8607.cpp +1 -1
- esphome/components/ms8607/ms8607.h +0 -1
- esphome/components/neopixelbus/light.py +4 -1
- esphome/components/neopixelbus/neopixelbus_light.h +1 -1
- esphome/components/network/__init__.py +4 -1
- esphome/components/network/ip_address.h +1 -0
- esphome/components/nextion/__init__.py +16 -0
- esphome/components/nextion/base_component.py +1 -0
- esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +1 -1
- esphome/components/nextion/display.py +14 -4
- esphome/components/nextion/nextion.cpp +166 -101
- esphome/components/nextion/nextion.h +84 -53
- esphome/components/nextion/nextion_commands.cpp +11 -10
- esphome/components/nextion/nextion_component.cpp +28 -28
- esphome/components/nextion/nextion_component.h +53 -18
- esphome/components/nextion/nextion_component_base.h +3 -0
- esphome/components/nextion/nextion_upload.cpp +36 -0
- esphome/components/nextion/nextion_upload_arduino.cpp +10 -35
- esphome/components/nextion/nextion_upload_idf.cpp +9 -33
- esphome/components/nextion/sensor/nextion_sensor.cpp +1 -1
- esphome/components/nextion/switch/nextion_switch.cpp +1 -1
- esphome/components/nextion/text_sensor/nextion_textsensor.cpp +1 -1
- esphome/components/nfc/nfc.cpp +3 -22
- esphome/components/nfc/nfc.h +3 -3
- esphome/components/number/__init__.py +5 -2
- esphome/components/online_image/__init__.py +9 -1
- esphome/components/online_image/online_image.cpp +17 -7
- esphome/components/online_image/online_image.h +10 -2
- esphome/components/opentherm/opentherm.cpp +7 -12
- esphome/components/opentherm/output/output.cpp +1 -1
- esphome/components/openthread/__init__.py +47 -40
- esphome/components/openthread/const.py +1 -0
- esphome/components/openthread/openthread_esp.cpp +27 -5
- esphome/components/opt3001/__init__.py +0 -0
- esphome/components/opt3001/opt3001.cpp +122 -0
- esphome/components/opt3001/opt3001.h +27 -0
- esphome/components/opt3001/sensor.py +35 -0
- esphome/components/ota/__init__.py +17 -0
- esphome/components/ota/ota_backend.h +27 -1
- esphome/components/ota/ota_backend_arduino_esp32.cpp +12 -2
- esphome/components/ota/ota_backend_arduino_esp32.h +3 -0
- esphome/components/ota/ota_backend_arduino_esp8266.cpp +18 -4
- esphome/components/ota/ota_backend_arduino_esp8266.h +3 -0
- esphome/components/ota/ota_backend_arduino_libretiny.cpp +12 -2
- esphome/components/ota/ota_backend_arduino_libretiny.h +3 -0
- esphome/components/ota/ota_backend_arduino_rp2040.cpp +9 -2
- esphome/components/ota/ota_backend_arduino_rp2040.h +3 -0
- esphome/components/ota/ota_backend_esp_idf.cpp +10 -16
- esphome/components/ota/ota_backend_esp_idf.h +1 -0
- esphome/components/packages/__init__.py +5 -2
- esphome/components/packet_transport/binary_sensor.py +61 -4
- esphome/components/packet_transport/packet_transport.cpp +34 -1
- esphome/components/packet_transport/packet_transport.h +11 -5
- esphome/components/pcf8574/__init__.py +1 -1
- esphome/components/pi4ioe5v6408/__init__.py +84 -0
- esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +171 -0
- esphome/components/pi4ioe5v6408/pi4ioe5v6408.h +70 -0
- esphome/components/pmsa003i/pmsa003i.h +0 -1
- esphome/components/pmsx003/pmsx003.h +0 -1
- esphome/components/pn7150/pn7150.cpp +7 -7
- esphome/components/pn7150/pn7150.h +0 -1
- esphome/components/pn7160/pn7160.cpp +7 -7
- esphome/components/pn7160/pn7160.h +0 -1
- esphome/components/preferences/syncer.h +2 -0
- esphome/components/prometheus/prometheus_handler.h +1 -1
- esphome/components/psram/psram.cpp +0 -20
- esphome/components/pulse_counter/pulse_counter_sensor.h +0 -1
- esphome/components/pulse_meter/pulse_meter_sensor.cpp +8 -4
- esphome/components/pulse_width/pulse_width.h +0 -1
- esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +0 -4
- esphome/components/pvvx_mithermometer/display/pvvx_display.h +0 -2
- esphome/components/pvvx_mithermometer/pvvx_mithermometer.h +0 -1
- esphome/components/qr_code/__init__.py +13 -10
- esphome/components/qwiic_pir/qwiic_pir.h +0 -1
- esphome/components/radon_eye_ble/radon_eye_listener.cpp +1 -1
- esphome/components/rc522/rc522.h +0 -1
- esphome/components/rdm6300/rdm6300.h +0 -2
- esphome/components/remote_base/__init__.py +7 -5
- esphome/components/remote_base/remote_base.cpp +24 -21
- esphome/components/remote_base/remote_base.h +3 -26
- esphome/components/remote_receiver/__init__.py +40 -46
- esphome/components/remote_receiver/remote_receiver.h +4 -18
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -87
- esphome/components/remote_receiver/remote_receiver_esp8266.cpp +1 -1
- esphome/components/remote_transmitter/__init__.py +42 -43
- esphome/components/remote_transmitter/remote_transmitter.h +2 -14
- esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -77
- esphome/components/resistance/resistance_sensor.h +0 -1
- esphome/components/rp2040/__init__.py +2 -0
- esphome/components/rp2040/helpers.cpp +55 -0
- esphome/components/rp2040_pio_led_strip/led_strip.cpp +2 -2
- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -4
- esphome/components/rtttl/__init__.py +4 -4
- esphome/components/rtttl/rtttl.cpp +10 -1
- esphome/components/ruuvitag/ruuvitag.h +0 -1
- esphome/components/safe_mode/safe_mode.cpp +2 -0
- esphome/components/safe_mode/safe_mode.h +4 -1
- esphome/components/scd30/scd30.h +0 -1
- esphome/components/scd30/sensor.py +2 -2
- esphome/components/scd4x/scd4x.cpp +61 -54
- esphome/components/scd4x/scd4x.h +17 -15
- esphome/components/scd4x/sensor.py +4 -4
- esphome/components/script/script.h +0 -2
- esphome/components/sdp3x/sensor.py +1 -1
- esphome/components/select/__init__.py +5 -2
- esphome/components/sen5x/sen5x.h +0 -1
- esphome/components/senseair/senseair.h +0 -1
- esphome/components/sensor/__init__.py +4 -2
- esphome/components/sensor/filter.cpp +1 -1
- esphome/components/sensor/sensor.cpp +12 -6
- esphome/components/sensor/sensor.h +13 -5
- esphome/components/servo/servo.cpp +2 -2
- esphome/components/servo/servo.h +0 -1
- esphome/components/sfa30/sfa30.h +0 -1
- esphome/components/sgp30/sgp30.h +0 -1
- esphome/components/sgp4x/sgp4x.h +0 -1
- esphome/components/shelly_dimmer/stm32flash.cpp +1 -2
- esphome/components/sht4x/sht4x.h +0 -1
- esphome/components/sm300d2/sm300d2.h +0 -2
- esphome/components/smt100/sensor.py +8 -4
- esphome/components/smt100/smt100.cpp +5 -5
- esphome/components/smt100/smt100.h +3 -3
- esphome/components/sn74hc595/__init__.py +1 -1
- esphome/components/sn74hc595/sn74hc595.cpp +5 -4
- esphome/components/sntp/sntp_component.cpp +9 -3
- esphome/components/sntp/time.py +2 -0
- esphome/components/socket/__init__.py +17 -0
- esphome/components/spi/__init__.py +27 -6
- esphome/components/spi/spi.cpp +3 -2
- esphome/components/spi/spi.h +9 -3
- esphome/components/spi/spi_arduino.cpp +3 -5
- esphome/components/spi/spi_esp_idf.cpp +40 -21
- esphome/components/spi_led_strip/spi_led_strip.cpp +1 -1
- esphome/components/sps30/sps30.h +0 -1
- esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
- esphome/components/st7701s/st7701s.cpp +0 -4
- esphome/components/status/status_binary_sensor.h +0 -2
- esphome/components/substitutions/__init__.py +81 -21
- esphome/components/substitutions/jinja.py +99 -0
- esphome/components/sun/sun.cpp +3 -4
- esphome/components/switch/__init__.py +5 -2
- esphome/components/switch/binary_sensor/switch_binary_sensor.h +0 -1
- esphome/components/sx126x/__init__.py +317 -0
- esphome/components/sx126x/automation.h +62 -0
- esphome/components/sx126x/packet_transport/__init__.py +26 -0
- esphome/components/sx126x/packet_transport/sx126x_transport.cpp +26 -0
- esphome/components/sx126x/packet_transport/sx126x_transport.h +25 -0
- esphome/components/sx126x/sx126x.cpp +523 -0
- esphome/components/sx126x/sx126x.h +140 -0
- esphome/components/sx126x/sx126x_reg.h +163 -0
- esphome/components/sx127x/__init__.py +325 -0
- esphome/components/sx127x/automation.h +62 -0
- esphome/components/sx127x/packet_transport/__init__.py +26 -0
- esphome/components/sx127x/packet_transport/sx127x_transport.cpp +26 -0
- esphome/components/sx127x/packet_transport/sx127x_transport.h +25 -0
- esphome/components/sx127x/sx127x.cpp +498 -0
- esphome/components/sx127x/sx127x.h +128 -0
- esphome/components/sx127x/sx127x_reg.h +295 -0
- esphome/components/syslog/esphome_syslog.cpp +5 -3
- esphome/components/syslog/esphome_syslog.h +1 -1
- esphome/components/tca9555/__init__.py +1 -1
- esphome/components/template/binary_sensor/template_binary_sensor.cpp +1 -9
- esphome/components/text/__init__.py +5 -2
- esphome/components/text_sensor/__init__.py +5 -2
- esphome/components/thermostat/thermostat_climate.cpp +34 -31
- esphome/components/thermostat/thermostat_climate.h +43 -39
- esphome/components/time/__init__.py +16 -2
- esphome/components/time/real_time_clock.cpp +4 -0
- esphome/components/time/real_time_clock.h +5 -1
- esphome/components/tlc5971/tlc5971.cpp +4 -1
- esphome/components/tmp1075/tmp1075.h +0 -2
- esphome/components/tof10120/tof10120_sensor.h +0 -1
- esphome/components/tormatic/tormatic_cover.h +0 -1
- esphome/components/total_daily_energy/total_daily_energy.h +0 -1
- esphome/components/tsl2591/tsl2591.cpp +1 -1
- esphome/components/ttp229_bsf/ttp229_bsf.h +0 -1
- esphome/components/ttp229_lsf/ttp229_lsf.h +0 -1
- esphome/components/tx20/tx20.cpp +2 -2
- esphome/components/uart/__init__.py +18 -0
- esphome/components/uart/uart_component_esp_idf.cpp +1 -5
- esphome/components/update/__init__.py +5 -2
- esphome/components/update/update_entity.h +8 -0
- esphome/components/usb_host/__init__.py +5 -2
- esphome/components/usb_host/usb_host_client.cpp +10 -10
- esphome/components/usb_uart/cp210x.cpp +1 -1
- esphome/components/usb_uart/usb_uart.cpp +41 -44
- esphome/components/usb_uart/usb_uart.h +4 -3
- esphome/components/valve/__init__.py +5 -2
- esphome/components/vbus/vbus.h +0 -1
- esphome/components/veml3235/veml3235.h +0 -1
- esphome/components/veml7700/veml7700.h +0 -1
- esphome/components/vl53l0x/vl53l0x_sensor.h +0 -1
- esphome/components/voice_assistant/voice_assistant.cpp +4 -4
- esphome/components/watchdog/watchdog.cpp +0 -4
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +6 -6
- esphome/components/web_server/__init__.py +34 -19
- esphome/components/web_server/ota/__init__.py +32 -0
- esphome/components/web_server/ota/ota_web_server.cpp +210 -0
- esphome/components/web_server/ota/ota_web_server.h +26 -0
- esphome/components/web_server/web_server.cpp +324 -439
- esphome/components/web_server/web_server.h +33 -23
- esphome/components/web_server/web_server_v1.cpp +4 -5
- esphome/components/web_server_base/__init__.py +5 -2
- esphome/components/web_server_base/web_server_base.cpp +2 -94
- esphome/components/web_server_base/web_server_base.h +5 -25
- esphome/components/web_server_idf/multipart.cpp +254 -0
- esphome/components/web_server_idf/multipart.h +86 -0
- esphome/components/web_server_idf/utils.cpp +32 -0
- esphome/components/web_server_idf/utils.h +10 -0
- esphome/components/web_server_idf/web_server_idf.cpp +164 -16
- esphome/components/web_server_idf/web_server_idf.h +11 -10
- esphome/components/wiegand/wiegand.cpp +2 -2
- esphome/components/wifi/__init__.py +18 -0
- esphome/components/wifi/wifi_component.cpp +17 -22
- esphome/components/wifi/wifi_component.h +27 -23
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +52 -59
- esphome/components/wifi/wifi_component_esp8266.cpp +46 -46
- esphome/components/wifi/wifi_component_esp_idf.cpp +35 -36
- esphome/components/wifi/wifi_component_libretiny.cpp +26 -27
- esphome/components/wifi/wifi_component_pico_w.cpp +3 -3
- esphome/components/wifi_info/wifi_info_text_sensor.cpp +6 -6
- esphome/components/wireguard/__init__.py +2 -11
- esphome/components/xiaomi_ble/xiaomi_ble.cpp +13 -1
- esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
- esphome/components/xiaomi_cgd1/xiaomi_cgd1.h +0 -1
- esphome/components/xiaomi_cgdk2/xiaomi_cgdk2.h +0 -1
- esphome/components/xiaomi_cgg1/xiaomi_cgg1.h +0 -1
- esphome/components/xiaomi_cgpr1/xiaomi_cgpr1.h +0 -1
- esphome/components/xiaomi_gcls002/xiaomi_gcls002.h +0 -1
- esphome/components/xiaomi_hhccjcy01/xiaomi_hhccjcy01.h +0 -1
- esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h +0 -1
- esphome/components/xiaomi_hhccpot002/xiaomi_hhccpot002.h +0 -1
- esphome/components/xiaomi_jqjcy01ym/xiaomi_jqjcy01ym.h +0 -1
- esphome/components/xiaomi_lywsd02/xiaomi_lywsd02.h +0 -1
- esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +0 -1
- esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.h +0 -1
- esphome/components/xiaomi_lywsdcgq/xiaomi_lywsdcgq.h +0 -1
- esphome/components/xiaomi_mhoc303/xiaomi_mhoc303.h +0 -1
- esphome/components/xiaomi_mhoc401/xiaomi_mhoc401.h +0 -1
- esphome/components/xiaomi_miscale/xiaomi_miscale.h +0 -1
- esphome/components/xiaomi_mjyd02yla/xiaomi_mjyd02yla.h +0 -1
- esphome/components/xiaomi_mue4094rt/xiaomi_mue4094rt.h +0 -1
- esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.h +0 -1
- esphome/components/xiaomi_wx08zm/xiaomi_wx08zm.h +0 -1
- esphome/components/xiaomi_xmwsdj04mmc/__init__.py +0 -0
- esphome/components/xiaomi_xmwsdj04mmc/sensor.py +77 -0
- esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp +77 -0
- esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.h +36 -0
- esphome/components/zio_ultrasonic/zio_ultrasonic.h +0 -2
- esphome/components/zyaura/zyaura.h +0 -1
- esphome/config.py +88 -22
- esphome/config_helpers.py +74 -1
- esphome/config_validation.py +12 -1
- esphome/const.py +65 -10
- esphome/core/__init__.py +18 -2
- esphome/core/application.cpp +169 -10
- esphome/core/application.h +145 -165
- esphome/core/area.h +19 -0
- esphome/core/automation.h +58 -9
- esphome/core/color.cpp +3 -5
- esphome/core/color.h +16 -16
- esphome/core/component.cpp +156 -22
- esphome/core/component.h +98 -4
- esphome/core/component_iterator.cpp +11 -9
- esphome/core/component_iterator.h +12 -10
- esphome/core/config.py +155 -6
- esphome/core/controller.cpp +4 -2
- esphome/core/controller.h +1 -1
- esphome/core/datatypes.h +2 -2
- esphome/core/defines.h +17 -2
- esphome/core/device.h +20 -0
- esphome/core/entity_base.cpp +20 -15
- esphome/core/entity_base.h +76 -0
- esphome/core/entity_helpers.py +168 -1
- esphome/core/event_pool.h +81 -0
- esphome/core/helpers.cpp +75 -230
- esphome/core/helpers.h +165 -105
- esphome/core/lock_free_queue.h +151 -0
- esphome/core/log.cpp +2 -2
- esphome/core/log.h +2 -0
- esphome/core/optional.h +5 -0
- esphome/core/ring_buffer.cpp +2 -2
- esphome/core/scheduler.cpp +275 -103
- esphome/core/scheduler.h +154 -17
- esphome/core/time.cpp +5 -5
- esphome/core/time.h +5 -5
- esphome/cpp_generator.py +17 -0
- esphome/cpp_helpers.py +0 -22
- esphome/cpp_types.py +3 -1
- esphome/dashboard/entries.py +1 -1
- esphome/dashboard/util/text.py +5 -21
- esphome/dashboard/web_server.py +9 -1
- esphome/helpers.py +47 -0
- esphome/loader.py +15 -1
- esphome/pins.py +14 -8
- esphome/platformio_api.py +2 -0
- esphome/wizard.py +17 -4
- esphome/writer.py +44 -3
- esphome/yaml_util.py +0 -2
- {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/METADATA +10 -9
- {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/RECORD +639 -580
- esphome/components/api/api_pb2_size.h +0 -361
- esphome/components/esp32_ble/ble_event_pool.h +0 -72
- esphome/components/esp32_ble/queue.h +0 -85
- esphome/components/esp32_hall/esp32_hall.cpp +0 -25
- esphome/components/esp32_hall/esp32_hall.h +0 -23
- esphome/components/esp32_touch/esp32_touch.cpp +0 -355
- esphome/components/ld2410/button/reset_button.cpp +0 -9
- esphome/components/ld2450/button/reset_button.cpp +0 -9
- esphome/components/openthread/tlv.py +0 -65
- /esphome/{dashboard/enum.py → enum.py} +0 -0
- {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/WHEEL +0 -0
- {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/entry_points.txt +0 -0
- {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.6.2.dist-info → esphome-2025.7.0.dist-info}/top_level.txt +0 -0
|
@@ -46,29 +46,60 @@ static const char *const HEADER_CORS_REQ_PNA = "Access-Control-Request-Private-N
|
|
|
46
46
|
static const char *const HEADER_CORS_ALLOW_PNA = "Access-Control-Allow-Private-Network";
|
|
47
47
|
#endif
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
match
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
match.domain = url.substr(1, domain_end - 1);
|
|
56
|
-
if (only_domain) {
|
|
57
|
-
match.valid = true;
|
|
49
|
+
// Parse URL and return match info
|
|
50
|
+
static UrlMatch match_url(const char *url_ptr, size_t url_len, bool only_domain) {
|
|
51
|
+
UrlMatch match{};
|
|
52
|
+
|
|
53
|
+
// URL must start with '/'
|
|
54
|
+
if (url_len < 2 || url_ptr[0] != '/') {
|
|
58
55
|
return match;
|
|
59
56
|
}
|
|
60
|
-
|
|
57
|
+
|
|
58
|
+
// Skip leading '/'
|
|
59
|
+
const char *start = url_ptr + 1;
|
|
60
|
+
const char *end = url_ptr + url_len;
|
|
61
|
+
|
|
62
|
+
// Find domain (everything up to next '/' or end)
|
|
63
|
+
const char *domain_end = (const char *) memchr(start, '/', end - start);
|
|
64
|
+
if (!domain_end) {
|
|
65
|
+
// No second slash found - original behavior returns invalid
|
|
61
66
|
return match;
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Set domain
|
|
70
|
+
match.domain = start;
|
|
71
|
+
match.domain_len = domain_end - start;
|
|
64
72
|
match.valid = true;
|
|
65
|
-
|
|
66
|
-
|
|
73
|
+
|
|
74
|
+
if (only_domain) {
|
|
75
|
+
return match;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Parse ID if present
|
|
79
|
+
if (domain_end + 1 >= end) {
|
|
80
|
+
return match; // Nothing after domain slash
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const char *id_start = domain_end + 1;
|
|
84
|
+
const char *id_end = (const char *) memchr(id_start, '/', end - id_start);
|
|
85
|
+
|
|
86
|
+
if (!id_end) {
|
|
87
|
+
// No more slashes, entire remaining string is ID
|
|
88
|
+
match.id = id_start;
|
|
89
|
+
match.id_len = end - id_start;
|
|
67
90
|
return match;
|
|
68
91
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
match.
|
|
92
|
+
|
|
93
|
+
// Set ID
|
|
94
|
+
match.id = id_start;
|
|
95
|
+
match.id_len = id_end - id_start;
|
|
96
|
+
|
|
97
|
+
// Parse method if present
|
|
98
|
+
if (id_end + 1 < end) {
|
|
99
|
+
match.method = id_end + 1;
|
|
100
|
+
match.method_len = end - (id_end + 1);
|
|
101
|
+
}
|
|
102
|
+
|
|
72
103
|
return match;
|
|
73
104
|
}
|
|
74
105
|
|
|
@@ -91,10 +122,19 @@ void DeferredUpdateEventSource::process_deferred_queue_() {
|
|
|
91
122
|
while (!deferred_queue_.empty()) {
|
|
92
123
|
DeferredEvent &de = deferred_queue_.front();
|
|
93
124
|
std::string message = de.message_generator_(web_server_, de.source_);
|
|
94
|
-
if (this->
|
|
125
|
+
if (this->send(message.c_str(), "state") != DISCARDED) {
|
|
95
126
|
// O(n) but memory efficiency is more important than speed here which is why std::vector was chosen
|
|
96
127
|
deferred_queue_.erase(deferred_queue_.begin());
|
|
128
|
+
this->consecutive_send_failures_ = 0; // Reset failure count on successful send
|
|
97
129
|
} else {
|
|
130
|
+
this->consecutive_send_failures_++;
|
|
131
|
+
if (this->consecutive_send_failures_ >= MAX_CONSECUTIVE_SEND_FAILURES) {
|
|
132
|
+
// Too many failures, connection is likely dead
|
|
133
|
+
ESP_LOGW(TAG, "Closing stuck EventSource connection after %" PRIu16 " failed sends",
|
|
134
|
+
this->consecutive_send_failures_);
|
|
135
|
+
this->close();
|
|
136
|
+
this->deferred_queue_.clear();
|
|
137
|
+
}
|
|
98
138
|
break;
|
|
99
139
|
}
|
|
100
140
|
}
|
|
@@ -131,8 +171,10 @@ void DeferredUpdateEventSource::deferrable_send_state(void *source, const char *
|
|
|
131
171
|
deq_push_back_with_dedup_(source, message_generator);
|
|
132
172
|
} else {
|
|
133
173
|
std::string message = message_generator(web_server_, source);
|
|
134
|
-
if (
|
|
174
|
+
if (this->send(message.c_str(), "state") == DISCARDED) {
|
|
135
175
|
deq_push_back_with_dedup_(source, message_generator);
|
|
176
|
+
} else {
|
|
177
|
+
this->consecutive_send_failures_ = 0; // Reset failure count on successful send
|
|
136
178
|
}
|
|
137
179
|
}
|
|
138
180
|
}
|
|
@@ -171,8 +213,8 @@ void DeferredUpdateEventSourceList::add_new_client(WebServer *ws, AsyncWebServer
|
|
|
171
213
|
ws->defer([this, ws, es]() { this->on_client_connect_(ws, es); });
|
|
172
214
|
});
|
|
173
215
|
|
|
174
|
-
es->onDisconnect([this, ws](
|
|
175
|
-
ws->defer([this,
|
|
216
|
+
es->onDisconnect([this, ws, es](AsyncEventSourceClient *client) {
|
|
217
|
+
ws->defer([this, es]() { this->on_client_disconnect_((DeferredUpdateEventSource *) es); });
|
|
176
218
|
});
|
|
177
219
|
|
|
178
220
|
es->handleRequest(request);
|
|
@@ -184,6 +226,7 @@ void DeferredUpdateEventSourceList::on_client_connect_(WebServer *ws, DeferredUp
|
|
|
184
226
|
std::string message = ws->get_config_json();
|
|
185
227
|
source->try_send_nodefer(message.c_str(), "ping", millis(), 30000);
|
|
186
228
|
|
|
229
|
+
#ifdef USE_WEBSERVER_SORTING
|
|
187
230
|
for (auto &group : ws->sorting_groups_) {
|
|
188
231
|
message = json::build_json([group](JsonObject root) {
|
|
189
232
|
root["name"] = group.second.name;
|
|
@@ -193,6 +236,7 @@ void DeferredUpdateEventSourceList::on_client_connect_(WebServer *ws, DeferredUp
|
|
|
193
236
|
// up to 31 groups should be able to be queued initially without defer
|
|
194
237
|
source->try_send_nodefer(message.c_str(), "sorting_group");
|
|
195
238
|
}
|
|
239
|
+
#endif
|
|
196
240
|
|
|
197
241
|
source->entities_iterator_.begin(ws->include_internal_);
|
|
198
242
|
|
|
@@ -211,11 +255,7 @@ void DeferredUpdateEventSourceList::on_client_disconnect_(DeferredUpdateEventSou
|
|
|
211
255
|
}
|
|
212
256
|
#endif
|
|
213
257
|
|
|
214
|
-
WebServer::WebServer(web_server_base::WebServerBase *base) : base_(base) {
|
|
215
|
-
#ifdef USE_ESP32
|
|
216
|
-
to_schedule_lock_ = xSemaphoreCreateMutex();
|
|
217
|
-
#endif
|
|
218
|
-
}
|
|
258
|
+
WebServer::WebServer(web_server_base::WebServerBase *base) : base_(base) {}
|
|
219
259
|
|
|
220
260
|
#ifdef USE_WEBSERVER_CSS_INCLUDE
|
|
221
261
|
void WebServer::set_css_include(const char *css_include) { this->css_include_ = css_include; }
|
|
@@ -228,7 +268,11 @@ std::string WebServer::get_config_json() {
|
|
|
228
268
|
return json::build_json([this](JsonObject root) {
|
|
229
269
|
root["title"] = App.get_friendly_name().empty() ? App.get_name() : App.get_friendly_name();
|
|
230
270
|
root["comment"] = App.get_comment();
|
|
231
|
-
|
|
271
|
+
#ifdef USE_WEBSERVER_OTA
|
|
272
|
+
root["ota"] = true; // web_server OTA platform is configured
|
|
273
|
+
#else
|
|
274
|
+
root["ota"] = false;
|
|
275
|
+
#endif
|
|
232
276
|
root["log"] = this->expose_log_;
|
|
233
277
|
root["lang"] = "en";
|
|
234
278
|
});
|
|
@@ -243,7 +287,8 @@ void WebServer::setup() {
|
|
|
243
287
|
if (logger::global_logger != nullptr && this->expose_log_) {
|
|
244
288
|
logger::global_logger->add_on_log_callback(
|
|
245
289
|
// logs are not deferred, the memory overhead would be too large
|
|
246
|
-
[this](int level, const char *tag, const char *message) {
|
|
290
|
+
[this](int level, const char *tag, const char *message, size_t message_len) {
|
|
291
|
+
(void) message_len;
|
|
247
292
|
this->events_.try_send_nodefer(message, "log", millis());
|
|
248
293
|
});
|
|
249
294
|
}
|
|
@@ -254,33 +299,13 @@ void WebServer::setup() {
|
|
|
254
299
|
#endif
|
|
255
300
|
this->base_->add_handler(this);
|
|
256
301
|
|
|
257
|
-
|
|
258
|
-
this->base_->add_ota_handler();
|
|
302
|
+
// OTA is now handled by the web_server OTA platform
|
|
259
303
|
|
|
260
304
|
// doesn't need defer functionality - if the queue is full, the client JS knows it's alive because it's clearly
|
|
261
305
|
// getting a lot of events
|
|
262
306
|
this->set_interval(10000, [this]() { this->events_.try_send_nodefer("", "ping", millis(), 30000); });
|
|
263
307
|
}
|
|
264
|
-
void WebServer::loop() {
|
|
265
|
-
#ifdef USE_ESP32
|
|
266
|
-
if (xSemaphoreTake(this->to_schedule_lock_, 0L)) {
|
|
267
|
-
std::function<void()> fn;
|
|
268
|
-
if (!to_schedule_.empty()) {
|
|
269
|
-
// scheduler execute things out of order which may lead to incorrect state
|
|
270
|
-
// this->defer(std::move(to_schedule_.front()));
|
|
271
|
-
// let's execute it directly from the loop
|
|
272
|
-
fn = std::move(to_schedule_.front());
|
|
273
|
-
to_schedule_.pop_front();
|
|
274
|
-
}
|
|
275
|
-
xSemaphoreGive(this->to_schedule_lock_);
|
|
276
|
-
if (fn) {
|
|
277
|
-
fn();
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
#endif
|
|
281
|
-
|
|
282
|
-
this->events_.loop();
|
|
283
|
-
}
|
|
308
|
+
void WebServer::loop() { this->events_.loop(); }
|
|
284
309
|
void WebServer::dump_config() {
|
|
285
310
|
ESP_LOGCONFIG(TAG,
|
|
286
311
|
"Web Server:\n"
|
|
@@ -291,14 +316,23 @@ float WebServer::get_setup_priority() const { return setup_priority::WIFI - 1.0f
|
|
|
291
316
|
|
|
292
317
|
#ifdef USE_WEBSERVER_LOCAL
|
|
293
318
|
void WebServer::handle_index_request(AsyncWebServerRequest *request) {
|
|
319
|
+
#ifndef USE_ESP8266
|
|
320
|
+
AsyncWebServerResponse *response = request->beginResponse(200, "text/html", INDEX_GZ, sizeof(INDEX_GZ));
|
|
321
|
+
#else
|
|
294
322
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", INDEX_GZ, sizeof(INDEX_GZ));
|
|
323
|
+
#endif
|
|
295
324
|
response->addHeader("Content-Encoding", "gzip");
|
|
296
325
|
request->send(response);
|
|
297
326
|
}
|
|
298
327
|
#elif USE_WEBSERVER_VERSION >= 2
|
|
299
328
|
void WebServer::handle_index_request(AsyncWebServerRequest *request) {
|
|
329
|
+
#ifndef USE_ESP8266
|
|
330
|
+
AsyncWebServerResponse *response =
|
|
331
|
+
request->beginResponse(200, "text/html", ESPHOME_WEBSERVER_INDEX_HTML, ESPHOME_WEBSERVER_INDEX_HTML_SIZE);
|
|
332
|
+
#else
|
|
300
333
|
AsyncWebServerResponse *response =
|
|
301
334
|
request->beginResponse_P(200, "text/html", ESPHOME_WEBSERVER_INDEX_HTML, ESPHOME_WEBSERVER_INDEX_HTML_SIZE);
|
|
335
|
+
#endif
|
|
302
336
|
// No gzip header here because the HTML file is so small
|
|
303
337
|
request->send(response);
|
|
304
338
|
}
|
|
@@ -317,8 +351,13 @@ void WebServer::handle_pna_cors_request(AsyncWebServerRequest *request) {
|
|
|
317
351
|
|
|
318
352
|
#ifdef USE_WEBSERVER_CSS_INCLUDE
|
|
319
353
|
void WebServer::handle_css_request(AsyncWebServerRequest *request) {
|
|
354
|
+
#ifndef USE_ESP8266
|
|
355
|
+
AsyncWebServerResponse *response =
|
|
356
|
+
request->beginResponse(200, "text/css", ESPHOME_WEBSERVER_CSS_INCLUDE, ESPHOME_WEBSERVER_CSS_INCLUDE_SIZE);
|
|
357
|
+
#else
|
|
320
358
|
AsyncWebServerResponse *response =
|
|
321
359
|
request->beginResponse_P(200, "text/css", ESPHOME_WEBSERVER_CSS_INCLUDE, ESPHOME_WEBSERVER_CSS_INCLUDE_SIZE);
|
|
360
|
+
#endif
|
|
322
361
|
response->addHeader("Content-Encoding", "gzip");
|
|
323
362
|
request->send(response);
|
|
324
363
|
}
|
|
@@ -326,8 +365,13 @@ void WebServer::handle_css_request(AsyncWebServerRequest *request) {
|
|
|
326
365
|
|
|
327
366
|
#ifdef USE_WEBSERVER_JS_INCLUDE
|
|
328
367
|
void WebServer::handle_js_request(AsyncWebServerRequest *request) {
|
|
368
|
+
#ifndef USE_ESP8266
|
|
369
|
+
AsyncWebServerResponse *response =
|
|
370
|
+
request->beginResponse(200, "text/javascript", ESPHOME_WEBSERVER_JS_INCLUDE, ESPHOME_WEBSERVER_JS_INCLUDE_SIZE);
|
|
371
|
+
#else
|
|
329
372
|
AsyncWebServerResponse *response =
|
|
330
373
|
request->beginResponse_P(200, "text/javascript", ESPHOME_WEBSERVER_JS_INCLUDE, ESPHOME_WEBSERVER_JS_INCLUDE_SIZE);
|
|
374
|
+
#endif
|
|
331
375
|
response->addHeader("Content-Encoding", "gzip");
|
|
332
376
|
request->send(response);
|
|
333
377
|
}
|
|
@@ -351,6 +395,12 @@ void WebServer::handle_js_request(AsyncWebServerRequest *request) {
|
|
|
351
395
|
set_json_value(root, obj, sensor, value, start_config); \
|
|
352
396
|
(root)["state"] = state;
|
|
353
397
|
|
|
398
|
+
// Helper to get request detail parameter
|
|
399
|
+
static JsonDetail get_request_detail(AsyncWebServerRequest *request) {
|
|
400
|
+
auto *param = request->getParam("detail");
|
|
401
|
+
return (param && param->value() == "all") ? DETAIL_ALL : DETAIL_STATE;
|
|
402
|
+
}
|
|
403
|
+
|
|
354
404
|
#ifdef USE_SENSOR
|
|
355
405
|
void WebServer::on_sensor_update(sensor::Sensor *obj, float state) {
|
|
356
406
|
if (this->events_.empty())
|
|
@@ -359,14 +409,10 @@ void WebServer::on_sensor_update(sensor::Sensor *obj, float state) {
|
|
|
359
409
|
}
|
|
360
410
|
void WebServer::handle_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
361
411
|
for (sensor::Sensor *obj : App.get_sensors()) {
|
|
362
|
-
if (obj->get_object_id()
|
|
412
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
363
413
|
continue;
|
|
364
|
-
if (request->method() == HTTP_GET && match.
|
|
365
|
-
auto detail =
|
|
366
|
-
auto *param = request->getParam("detail");
|
|
367
|
-
if (param && param->value() == "all") {
|
|
368
|
-
detail = DETAIL_ALL;
|
|
369
|
-
}
|
|
414
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
415
|
+
auto detail = get_request_detail(request);
|
|
370
416
|
std::string data = this->sensor_json(obj, obj->state, detail);
|
|
371
417
|
request->send(200, "application/json", data.c_str());
|
|
372
418
|
return;
|
|
@@ -392,12 +438,7 @@ std::string WebServer::sensor_json(sensor::Sensor *obj, float value, JsonDetail
|
|
|
392
438
|
}
|
|
393
439
|
set_json_icon_state_value(root, obj, "sensor-" + obj->get_object_id(), state, value, start_config);
|
|
394
440
|
if (start_config == DETAIL_ALL) {
|
|
395
|
-
|
|
396
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
397
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
398
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
441
|
+
this->add_sorting_info_(root, obj);
|
|
401
442
|
if (!obj->get_unit_of_measurement().empty())
|
|
402
443
|
root["uom"] = obj->get_unit_of_measurement();
|
|
403
444
|
}
|
|
@@ -413,14 +454,10 @@ void WebServer::on_text_sensor_update(text_sensor::TextSensor *obj, const std::s
|
|
|
413
454
|
}
|
|
414
455
|
void WebServer::handle_text_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
415
456
|
for (text_sensor::TextSensor *obj : App.get_text_sensors()) {
|
|
416
|
-
if (obj->get_object_id()
|
|
457
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
417
458
|
continue;
|
|
418
|
-
if (request->method() == HTTP_GET && match.
|
|
419
|
-
auto detail =
|
|
420
|
-
auto *param = request->getParam("detail");
|
|
421
|
-
if (param && param->value() == "all") {
|
|
422
|
-
detail = DETAIL_ALL;
|
|
423
|
-
}
|
|
459
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
460
|
+
auto detail = get_request_detail(request);
|
|
424
461
|
std::string data = this->text_sensor_json(obj, obj->state, detail);
|
|
425
462
|
request->send(200, "application/json", data.c_str());
|
|
426
463
|
return;
|
|
@@ -441,12 +478,7 @@ std::string WebServer::text_sensor_json(text_sensor::TextSensor *obj, const std:
|
|
|
441
478
|
return json::build_json([this, obj, value, start_config](JsonObject root) {
|
|
442
479
|
set_json_icon_state_value(root, obj, "text_sensor-" + obj->get_object_id(), value, value, start_config);
|
|
443
480
|
if (start_config == DETAIL_ALL) {
|
|
444
|
-
|
|
445
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
446
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
447
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
481
|
+
this->add_sorting_info_(root, obj);
|
|
450
482
|
}
|
|
451
483
|
});
|
|
452
484
|
}
|
|
@@ -460,25 +492,21 @@ void WebServer::on_switch_update(switch_::Switch *obj, bool state) {
|
|
|
460
492
|
}
|
|
461
493
|
void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
462
494
|
for (switch_::Switch *obj : App.get_switches()) {
|
|
463
|
-
if (obj->get_object_id()
|
|
495
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
464
496
|
continue;
|
|
465
497
|
|
|
466
|
-
if (request->method() == HTTP_GET && match.
|
|
467
|
-
auto detail =
|
|
468
|
-
auto *param = request->getParam("detail");
|
|
469
|
-
if (param && param->value() == "all") {
|
|
470
|
-
detail = DETAIL_ALL;
|
|
471
|
-
}
|
|
498
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
499
|
+
auto detail = get_request_detail(request);
|
|
472
500
|
std::string data = this->switch_json(obj, obj->state, detail);
|
|
473
501
|
request->send(200, "application/json", data.c_str());
|
|
474
|
-
} else if (match.
|
|
475
|
-
this->
|
|
502
|
+
} else if (match.method_equals("toggle")) {
|
|
503
|
+
this->defer([obj]() { obj->toggle(); });
|
|
476
504
|
request->send(200);
|
|
477
|
-
} else if (match.
|
|
478
|
-
this->
|
|
505
|
+
} else if (match.method_equals("turn_on")) {
|
|
506
|
+
this->defer([obj]() { obj->turn_on(); });
|
|
479
507
|
request->send(200);
|
|
480
|
-
} else if (match.
|
|
481
|
-
this->
|
|
508
|
+
} else if (match.method_equals("turn_off")) {
|
|
509
|
+
this->defer([obj]() { obj->turn_off(); });
|
|
482
510
|
request->send(200);
|
|
483
511
|
} else {
|
|
484
512
|
request->send(404);
|
|
@@ -498,12 +526,7 @@ std::string WebServer::switch_json(switch_::Switch *obj, bool value, JsonDetail
|
|
|
498
526
|
set_json_icon_state_value(root, obj, "switch-" + obj->get_object_id(), value ? "ON" : "OFF", value, start_config);
|
|
499
527
|
if (start_config == DETAIL_ALL) {
|
|
500
528
|
root["assumed_state"] = obj->assumed_state();
|
|
501
|
-
|
|
502
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
503
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
504
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
529
|
+
this->add_sorting_info_(root, obj);
|
|
507
530
|
}
|
|
508
531
|
});
|
|
509
532
|
}
|
|
@@ -512,18 +535,14 @@ std::string WebServer::switch_json(switch_::Switch *obj, bool value, JsonDetail
|
|
|
512
535
|
#ifdef USE_BUTTON
|
|
513
536
|
void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
514
537
|
for (button::Button *obj : App.get_buttons()) {
|
|
515
|
-
if (obj->get_object_id()
|
|
538
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
516
539
|
continue;
|
|
517
|
-
if (request->method() == HTTP_GET && match.
|
|
518
|
-
auto detail =
|
|
519
|
-
auto *param = request->getParam("detail");
|
|
520
|
-
if (param && param->value() == "all") {
|
|
521
|
-
detail = DETAIL_ALL;
|
|
522
|
-
}
|
|
540
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
541
|
+
auto detail = get_request_detail(request);
|
|
523
542
|
std::string data = this->button_json(obj, detail);
|
|
524
543
|
request->send(200, "application/json", data.c_str());
|
|
525
|
-
} else if (match.
|
|
526
|
-
this->
|
|
544
|
+
} else if (match.method_equals("press")) {
|
|
545
|
+
this->defer([obj]() { obj->press(); });
|
|
527
546
|
request->send(200);
|
|
528
547
|
return;
|
|
529
548
|
} else {
|
|
@@ -543,33 +562,24 @@ std::string WebServer::button_json(button::Button *obj, JsonDetail start_config)
|
|
|
543
562
|
return json::build_json([this, obj, start_config](JsonObject root) {
|
|
544
563
|
set_json_id(root, obj, "button-" + obj->get_object_id(), start_config);
|
|
545
564
|
if (start_config == DETAIL_ALL) {
|
|
546
|
-
|
|
547
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
548
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
549
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
550
|
-
}
|
|
551
|
-
}
|
|
565
|
+
this->add_sorting_info_(root, obj);
|
|
552
566
|
}
|
|
553
567
|
});
|
|
554
568
|
}
|
|
555
569
|
#endif
|
|
556
570
|
|
|
557
571
|
#ifdef USE_BINARY_SENSOR
|
|
558
|
-
void WebServer::on_binary_sensor_update(binary_sensor::BinarySensor *obj
|
|
572
|
+
void WebServer::on_binary_sensor_update(binary_sensor::BinarySensor *obj) {
|
|
559
573
|
if (this->events_.empty())
|
|
560
574
|
return;
|
|
561
575
|
this->events_.deferrable_send_state(obj, "state", binary_sensor_state_json_generator);
|
|
562
576
|
}
|
|
563
577
|
void WebServer::handle_binary_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
564
578
|
for (binary_sensor::BinarySensor *obj : App.get_binary_sensors()) {
|
|
565
|
-
if (obj->get_object_id()
|
|
579
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
566
580
|
continue;
|
|
567
|
-
if (request->method() == HTTP_GET && match.
|
|
568
|
-
auto detail =
|
|
569
|
-
auto *param = request->getParam("detail");
|
|
570
|
-
if (param && param->value() == "all") {
|
|
571
|
-
detail = DETAIL_ALL;
|
|
572
|
-
}
|
|
581
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
582
|
+
auto detail = get_request_detail(request);
|
|
573
583
|
std::string data = this->binary_sensor_json(obj, obj->state, detail);
|
|
574
584
|
request->send(200, "application/json", data.c_str());
|
|
575
585
|
return;
|
|
@@ -590,12 +600,7 @@ std::string WebServer::binary_sensor_json(binary_sensor::BinarySensor *obj, bool
|
|
|
590
600
|
set_json_icon_state_value(root, obj, "binary_sensor-" + obj->get_object_id(), value ? "ON" : "OFF", value,
|
|
591
601
|
start_config);
|
|
592
602
|
if (start_config == DETAIL_ALL) {
|
|
593
|
-
|
|
594
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
595
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
596
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
603
|
+
this->add_sorting_info_(root, obj);
|
|
599
604
|
}
|
|
600
605
|
});
|
|
601
606
|
}
|
|
@@ -609,22 +614,18 @@ void WebServer::on_fan_update(fan::Fan *obj) {
|
|
|
609
614
|
}
|
|
610
615
|
void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
611
616
|
for (fan::Fan *obj : App.get_fans()) {
|
|
612
|
-
if (obj->get_object_id()
|
|
617
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
613
618
|
continue;
|
|
614
619
|
|
|
615
|
-
if (request->method() == HTTP_GET && match.
|
|
616
|
-
auto detail =
|
|
617
|
-
auto *param = request->getParam("detail");
|
|
618
|
-
if (param && param->value() == "all") {
|
|
619
|
-
detail = DETAIL_ALL;
|
|
620
|
-
}
|
|
620
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
621
|
+
auto detail = get_request_detail(request);
|
|
621
622
|
std::string data = this->fan_json(obj, detail);
|
|
622
623
|
request->send(200, "application/json", data.c_str());
|
|
623
|
-
} else if (match.
|
|
624
|
-
this->
|
|
624
|
+
} else if (match.method_equals("toggle")) {
|
|
625
|
+
this->defer([obj]() { obj->toggle().perform(); });
|
|
625
626
|
request->send(200);
|
|
626
|
-
} else if (match.
|
|
627
|
-
auto call = match.
|
|
627
|
+
} else if (match.method_equals("turn_on") || match.method_equals("turn_off")) {
|
|
628
|
+
auto call = match.method_equals("turn_on") ? obj->turn_on() : obj->turn_off();
|
|
628
629
|
|
|
629
630
|
if (request->hasParam("speed_level")) {
|
|
630
631
|
auto speed_level = request->getParam("speed_level")->value();
|
|
@@ -653,7 +654,7 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc
|
|
|
653
654
|
return;
|
|
654
655
|
}
|
|
655
656
|
}
|
|
656
|
-
this->
|
|
657
|
+
this->defer([call]() mutable { call.perform(); });
|
|
657
658
|
request->send(200);
|
|
658
659
|
} else {
|
|
659
660
|
request->send(404);
|
|
@@ -680,12 +681,7 @@ std::string WebServer::fan_json(fan::Fan *obj, JsonDetail start_config) {
|
|
|
680
681
|
if (obj->get_traits().supports_oscillation())
|
|
681
682
|
root["oscillation"] = obj->oscillating;
|
|
682
683
|
if (start_config == DETAIL_ALL) {
|
|
683
|
-
|
|
684
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
685
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
686
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
687
|
-
}
|
|
688
|
-
}
|
|
684
|
+
this->add_sorting_info_(root, obj);
|
|
689
685
|
}
|
|
690
686
|
});
|
|
691
687
|
}
|
|
@@ -699,21 +695,17 @@ void WebServer::on_light_update(light::LightState *obj) {
|
|
|
699
695
|
}
|
|
700
696
|
void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
701
697
|
for (light::LightState *obj : App.get_lights()) {
|
|
702
|
-
if (obj->get_object_id()
|
|
698
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
703
699
|
continue;
|
|
704
700
|
|
|
705
|
-
if (request->method() == HTTP_GET && match.
|
|
706
|
-
auto detail =
|
|
707
|
-
auto *param = request->getParam("detail");
|
|
708
|
-
if (param && param->value() == "all") {
|
|
709
|
-
detail = DETAIL_ALL;
|
|
710
|
-
}
|
|
701
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
702
|
+
auto detail = get_request_detail(request);
|
|
711
703
|
std::string data = this->light_json(obj, detail);
|
|
712
704
|
request->send(200, "application/json", data.c_str());
|
|
713
|
-
} else if (match.
|
|
714
|
-
this->
|
|
705
|
+
} else if (match.method_equals("toggle")) {
|
|
706
|
+
this->defer([obj]() { obj->toggle().perform(); });
|
|
715
707
|
request->send(200);
|
|
716
|
-
} else if (match.
|
|
708
|
+
} else if (match.method_equals("turn_on")) {
|
|
717
709
|
auto call = obj->turn_on();
|
|
718
710
|
if (request->hasParam("brightness")) {
|
|
719
711
|
auto brightness = parse_number<float>(request->getParam("brightness")->value().c_str());
|
|
@@ -768,9 +760,9 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa
|
|
|
768
760
|
call.set_effect(effect);
|
|
769
761
|
}
|
|
770
762
|
|
|
771
|
-
this->
|
|
763
|
+
this->defer([call]() mutable { call.perform(); });
|
|
772
764
|
request->send(200);
|
|
773
|
-
} else if (match.
|
|
765
|
+
} else if (match.method_equals("turn_off")) {
|
|
774
766
|
auto call = obj->turn_off();
|
|
775
767
|
if (request->hasParam("transition")) {
|
|
776
768
|
auto transition = parse_number<uint32_t>(request->getParam("transition")->value().c_str());
|
|
@@ -778,7 +770,7 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa
|
|
|
778
770
|
call.set_transition_length(*transition * 1000);
|
|
779
771
|
}
|
|
780
772
|
}
|
|
781
|
-
this->
|
|
773
|
+
this->defer([call]() mutable { call.perform(); });
|
|
782
774
|
request->send(200);
|
|
783
775
|
} else {
|
|
784
776
|
request->send(404);
|
|
@@ -800,17 +792,12 @@ std::string WebServer::light_json(light::LightState *obj, JsonDetail start_confi
|
|
|
800
792
|
|
|
801
793
|
light::LightJSONSchema::dump_json(*obj, root);
|
|
802
794
|
if (start_config == DETAIL_ALL) {
|
|
803
|
-
JsonArray opt = root
|
|
795
|
+
JsonArray opt = root["effects"].to<JsonArray>();
|
|
804
796
|
opt.add("None");
|
|
805
797
|
for (auto const &option : obj->get_effects()) {
|
|
806
798
|
opt.add(option->get_name());
|
|
807
799
|
}
|
|
808
|
-
|
|
809
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
810
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
811
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
812
|
-
}
|
|
813
|
-
}
|
|
800
|
+
this->add_sorting_info_(root, obj);
|
|
814
801
|
}
|
|
815
802
|
});
|
|
816
803
|
}
|
|
@@ -824,30 +811,26 @@ void WebServer::on_cover_update(cover::Cover *obj) {
|
|
|
824
811
|
}
|
|
825
812
|
void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
826
813
|
for (cover::Cover *obj : App.get_covers()) {
|
|
827
|
-
if (obj->get_object_id()
|
|
814
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
828
815
|
continue;
|
|
829
816
|
|
|
830
|
-
if (request->method() == HTTP_GET && match.
|
|
831
|
-
auto detail =
|
|
832
|
-
auto *param = request->getParam("detail");
|
|
833
|
-
if (param && param->value() == "all") {
|
|
834
|
-
detail = DETAIL_ALL;
|
|
835
|
-
}
|
|
817
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
818
|
+
auto detail = get_request_detail(request);
|
|
836
819
|
std::string data = this->cover_json(obj, detail);
|
|
837
820
|
request->send(200, "application/json", data.c_str());
|
|
838
821
|
return;
|
|
839
822
|
}
|
|
840
823
|
|
|
841
824
|
auto call = obj->make_call();
|
|
842
|
-
if (match.
|
|
825
|
+
if (match.method_equals("open")) {
|
|
843
826
|
call.set_command_open();
|
|
844
|
-
} else if (match.
|
|
827
|
+
} else if (match.method_equals("close")) {
|
|
845
828
|
call.set_command_close();
|
|
846
|
-
} else if (match.
|
|
829
|
+
} else if (match.method_equals("stop")) {
|
|
847
830
|
call.set_command_stop();
|
|
848
|
-
} else if (match.
|
|
831
|
+
} else if (match.method_equals("toggle")) {
|
|
849
832
|
call.set_command_toggle();
|
|
850
|
-
} else if (match.
|
|
833
|
+
} else if (!match.method_equals("set")) {
|
|
851
834
|
request->send(404);
|
|
852
835
|
return;
|
|
853
836
|
}
|
|
@@ -872,7 +855,7 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa
|
|
|
872
855
|
}
|
|
873
856
|
}
|
|
874
857
|
|
|
875
|
-
this->
|
|
858
|
+
this->defer([call]() mutable { call.perform(); });
|
|
876
859
|
request->send(200);
|
|
877
860
|
return;
|
|
878
861
|
}
|
|
@@ -895,12 +878,7 @@ std::string WebServer::cover_json(cover::Cover *obj, JsonDetail start_config) {
|
|
|
895
878
|
if (obj->get_traits().get_supports_tilt())
|
|
896
879
|
root["tilt"] = obj->tilt;
|
|
897
880
|
if (start_config == DETAIL_ALL) {
|
|
898
|
-
|
|
899
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
900
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
901
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
902
|
-
}
|
|
903
|
-
}
|
|
881
|
+
this->add_sorting_info_(root, obj);
|
|
904
882
|
}
|
|
905
883
|
});
|
|
906
884
|
}
|
|
@@ -914,20 +892,16 @@ void WebServer::on_number_update(number::Number *obj, float state) {
|
|
|
914
892
|
}
|
|
915
893
|
void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
916
894
|
for (auto *obj : App.get_numbers()) {
|
|
917
|
-
if (obj->get_object_id()
|
|
895
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
918
896
|
continue;
|
|
919
897
|
|
|
920
|
-
if (request->method() == HTTP_GET && match.
|
|
921
|
-
auto detail =
|
|
922
|
-
auto *param = request->getParam("detail");
|
|
923
|
-
if (param && param->value() == "all") {
|
|
924
|
-
detail = DETAIL_ALL;
|
|
925
|
-
}
|
|
898
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
899
|
+
auto detail = get_request_detail(request);
|
|
926
900
|
std::string data = this->number_json(obj, obj->state, detail);
|
|
927
901
|
request->send(200, "application/json", data.c_str());
|
|
928
902
|
return;
|
|
929
903
|
}
|
|
930
|
-
if (match.
|
|
904
|
+
if (!match.method_equals("set")) {
|
|
931
905
|
request->send(404);
|
|
932
906
|
return;
|
|
933
907
|
}
|
|
@@ -939,7 +913,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM
|
|
|
939
913
|
call.set_value(*value);
|
|
940
914
|
}
|
|
941
915
|
|
|
942
|
-
this->
|
|
916
|
+
this->defer([call]() mutable { call.perform(); });
|
|
943
917
|
request->send(200);
|
|
944
918
|
return;
|
|
945
919
|
}
|
|
@@ -965,12 +939,7 @@ std::string WebServer::number_json(number::Number *obj, float value, JsonDetail
|
|
|
965
939
|
root["mode"] = (int) obj->traits.get_mode();
|
|
966
940
|
if (!obj->traits.get_unit_of_measurement().empty())
|
|
967
941
|
root["uom"] = obj->traits.get_unit_of_measurement();
|
|
968
|
-
|
|
969
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
970
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
971
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
942
|
+
this->add_sorting_info_(root, obj);
|
|
974
943
|
}
|
|
975
944
|
if (std::isnan(value)) {
|
|
976
945
|
root["value"] = "\"NaN\"";
|
|
@@ -994,19 +963,15 @@ void WebServer::on_date_update(datetime::DateEntity *obj) {
|
|
|
994
963
|
}
|
|
995
964
|
void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
996
965
|
for (auto *obj : App.get_dates()) {
|
|
997
|
-
if (obj->get_object_id()
|
|
966
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
998
967
|
continue;
|
|
999
|
-
if (request->method() == HTTP_GET && match.
|
|
1000
|
-
auto detail =
|
|
1001
|
-
auto *param = request->getParam("detail");
|
|
1002
|
-
if (param && param->value() == "all") {
|
|
1003
|
-
detail = DETAIL_ALL;
|
|
1004
|
-
}
|
|
968
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
969
|
+
auto detail = get_request_detail(request);
|
|
1005
970
|
std::string data = this->date_json(obj, detail);
|
|
1006
971
|
request->send(200, "application/json", data.c_str());
|
|
1007
972
|
return;
|
|
1008
973
|
}
|
|
1009
|
-
if (match.
|
|
974
|
+
if (!match.method_equals("set")) {
|
|
1010
975
|
request->send(404);
|
|
1011
976
|
return;
|
|
1012
977
|
}
|
|
@@ -1023,7 +988,7 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat
|
|
|
1023
988
|
call.set_date(value);
|
|
1024
989
|
}
|
|
1025
990
|
|
|
1026
|
-
this->
|
|
991
|
+
this->defer([call]() mutable { call.perform(); });
|
|
1027
992
|
request->send(200);
|
|
1028
993
|
return;
|
|
1029
994
|
}
|
|
@@ -1043,12 +1008,7 @@ std::string WebServer::date_json(datetime::DateEntity *obj, JsonDetail start_con
|
|
|
1043
1008
|
root["value"] = value;
|
|
1044
1009
|
root["state"] = value;
|
|
1045
1010
|
if (start_config == DETAIL_ALL) {
|
|
1046
|
-
|
|
1047
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1048
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1049
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1011
|
+
this->add_sorting_info_(root, obj);
|
|
1052
1012
|
}
|
|
1053
1013
|
});
|
|
1054
1014
|
}
|
|
@@ -1062,19 +1022,15 @@ void WebServer::on_time_update(datetime::TimeEntity *obj) {
|
|
|
1062
1022
|
}
|
|
1063
1023
|
void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1064
1024
|
for (auto *obj : App.get_times()) {
|
|
1065
|
-
if (obj->get_object_id()
|
|
1025
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1066
1026
|
continue;
|
|
1067
|
-
if (request->method() == HTTP_GET && match.
|
|
1068
|
-
auto detail =
|
|
1069
|
-
auto *param = request->getParam("detail");
|
|
1070
|
-
if (param && param->value() == "all") {
|
|
1071
|
-
detail = DETAIL_ALL;
|
|
1072
|
-
}
|
|
1027
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1028
|
+
auto detail = get_request_detail(request);
|
|
1073
1029
|
std::string data = this->time_json(obj, detail);
|
|
1074
1030
|
request->send(200, "application/json", data.c_str());
|
|
1075
1031
|
return;
|
|
1076
1032
|
}
|
|
1077
|
-
if (match.
|
|
1033
|
+
if (!match.method_equals("set")) {
|
|
1078
1034
|
request->send(404);
|
|
1079
1035
|
return;
|
|
1080
1036
|
}
|
|
@@ -1091,7 +1047,7 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat
|
|
|
1091
1047
|
call.set_time(value);
|
|
1092
1048
|
}
|
|
1093
1049
|
|
|
1094
|
-
this->
|
|
1050
|
+
this->defer([call]() mutable { call.perform(); });
|
|
1095
1051
|
request->send(200);
|
|
1096
1052
|
return;
|
|
1097
1053
|
}
|
|
@@ -1110,12 +1066,7 @@ std::string WebServer::time_json(datetime::TimeEntity *obj, JsonDetail start_con
|
|
|
1110
1066
|
root["value"] = value;
|
|
1111
1067
|
root["state"] = value;
|
|
1112
1068
|
if (start_config == DETAIL_ALL) {
|
|
1113
|
-
|
|
1114
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1115
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1116
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1069
|
+
this->add_sorting_info_(root, obj);
|
|
1119
1070
|
}
|
|
1120
1071
|
});
|
|
1121
1072
|
}
|
|
@@ -1129,19 +1080,15 @@ void WebServer::on_datetime_update(datetime::DateTimeEntity *obj) {
|
|
|
1129
1080
|
}
|
|
1130
1081
|
void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1131
1082
|
for (auto *obj : App.get_datetimes()) {
|
|
1132
|
-
if (obj->get_object_id()
|
|
1083
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1133
1084
|
continue;
|
|
1134
|
-
if (request->method() == HTTP_GET && match.
|
|
1135
|
-
auto detail =
|
|
1136
|
-
auto *param = request->getParam("detail");
|
|
1137
|
-
if (param && param->value() == "all") {
|
|
1138
|
-
detail = DETAIL_ALL;
|
|
1139
|
-
}
|
|
1085
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1086
|
+
auto detail = get_request_detail(request);
|
|
1140
1087
|
std::string data = this->datetime_json(obj, detail);
|
|
1141
1088
|
request->send(200, "application/json", data.c_str());
|
|
1142
1089
|
return;
|
|
1143
1090
|
}
|
|
1144
|
-
if (match.
|
|
1091
|
+
if (!match.method_equals("set")) {
|
|
1145
1092
|
request->send(404);
|
|
1146
1093
|
return;
|
|
1147
1094
|
}
|
|
@@ -1158,7 +1105,7 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur
|
|
|
1158
1105
|
call.set_datetime(value);
|
|
1159
1106
|
}
|
|
1160
1107
|
|
|
1161
|
-
this->
|
|
1108
|
+
this->defer([call]() mutable { call.perform(); });
|
|
1162
1109
|
request->send(200);
|
|
1163
1110
|
return;
|
|
1164
1111
|
}
|
|
@@ -1178,12 +1125,7 @@ std::string WebServer::datetime_json(datetime::DateTimeEntity *obj, JsonDetail s
|
|
|
1178
1125
|
root["value"] = value;
|
|
1179
1126
|
root["state"] = value;
|
|
1180
1127
|
if (start_config == DETAIL_ALL) {
|
|
1181
|
-
|
|
1182
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1183
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1184
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1128
|
+
this->add_sorting_info_(root, obj);
|
|
1187
1129
|
}
|
|
1188
1130
|
});
|
|
1189
1131
|
}
|
|
@@ -1197,20 +1139,16 @@ void WebServer::on_text_update(text::Text *obj, const std::string &state) {
|
|
|
1197
1139
|
}
|
|
1198
1140
|
void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1199
1141
|
for (auto *obj : App.get_texts()) {
|
|
1200
|
-
if (obj->get_object_id()
|
|
1142
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1201
1143
|
continue;
|
|
1202
1144
|
|
|
1203
|
-
if (request->method() == HTTP_GET && match.
|
|
1204
|
-
auto detail =
|
|
1205
|
-
auto *param = request->getParam("detail");
|
|
1206
|
-
if (param && param->value() == "all") {
|
|
1207
|
-
detail = DETAIL_ALL;
|
|
1208
|
-
}
|
|
1145
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1146
|
+
auto detail = get_request_detail(request);
|
|
1209
1147
|
std::string data = this->text_json(obj, obj->state, detail);
|
|
1210
1148
|
request->send(200, "application/json", data.c_str());
|
|
1211
1149
|
return;
|
|
1212
1150
|
}
|
|
1213
|
-
if (match.
|
|
1151
|
+
if (!match.method_equals("set")) {
|
|
1214
1152
|
request->send(404);
|
|
1215
1153
|
return;
|
|
1216
1154
|
}
|
|
@@ -1248,12 +1186,7 @@ std::string WebServer::text_json(text::Text *obj, const std::string &value, Json
|
|
|
1248
1186
|
root["value"] = value;
|
|
1249
1187
|
if (start_config == DETAIL_ALL) {
|
|
1250
1188
|
root["mode"] = (int) obj->traits.get_mode();
|
|
1251
|
-
|
|
1252
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1253
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1254
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1189
|
+
this->add_sorting_info_(root, obj);
|
|
1257
1190
|
}
|
|
1258
1191
|
});
|
|
1259
1192
|
}
|
|
@@ -1267,21 +1200,17 @@ void WebServer::on_select_update(select::Select *obj, const std::string &state,
|
|
|
1267
1200
|
}
|
|
1268
1201
|
void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1269
1202
|
for (auto *obj : App.get_selects()) {
|
|
1270
|
-
if (obj->get_object_id()
|
|
1203
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1271
1204
|
continue;
|
|
1272
1205
|
|
|
1273
|
-
if (request->method() == HTTP_GET && match.
|
|
1274
|
-
auto detail =
|
|
1275
|
-
auto *param = request->getParam("detail");
|
|
1276
|
-
if (param && param->value() == "all") {
|
|
1277
|
-
detail = DETAIL_ALL;
|
|
1278
|
-
}
|
|
1206
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1207
|
+
auto detail = get_request_detail(request);
|
|
1279
1208
|
std::string data = this->select_json(obj, obj->state, detail);
|
|
1280
1209
|
request->send(200, "application/json", data.c_str());
|
|
1281
1210
|
return;
|
|
1282
1211
|
}
|
|
1283
1212
|
|
|
1284
|
-
if (match.
|
|
1213
|
+
if (!match.method_equals("set")) {
|
|
1285
1214
|
request->send(404);
|
|
1286
1215
|
return;
|
|
1287
1216
|
}
|
|
@@ -1293,7 +1222,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM
|
|
|
1293
1222
|
call.set_option(option.c_str()); // NOLINT
|
|
1294
1223
|
}
|
|
1295
1224
|
|
|
1296
|
-
this->
|
|
1225
|
+
this->defer([call]() mutable { call.perform(); });
|
|
1297
1226
|
request->send(200);
|
|
1298
1227
|
return;
|
|
1299
1228
|
}
|
|
@@ -1309,16 +1238,11 @@ std::string WebServer::select_json(select::Select *obj, const std::string &value
|
|
|
1309
1238
|
return json::build_json([this, obj, value, start_config](JsonObject root) {
|
|
1310
1239
|
set_json_icon_state_value(root, obj, "select-" + obj->get_object_id(), value, value, start_config);
|
|
1311
1240
|
if (start_config == DETAIL_ALL) {
|
|
1312
|
-
JsonArray opt = root
|
|
1241
|
+
JsonArray opt = root["option"].to<JsonArray>();
|
|
1313
1242
|
for (auto &option : obj->traits.get_options()) {
|
|
1314
1243
|
opt.add(option);
|
|
1315
1244
|
}
|
|
1316
|
-
|
|
1317
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1318
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1319
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1245
|
+
this->add_sorting_info_(root, obj);
|
|
1322
1246
|
}
|
|
1323
1247
|
});
|
|
1324
1248
|
}
|
|
@@ -1335,21 +1259,17 @@ void WebServer::on_climate_update(climate::Climate *obj) {
|
|
|
1335
1259
|
}
|
|
1336
1260
|
void WebServer::handle_climate_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1337
1261
|
for (auto *obj : App.get_climates()) {
|
|
1338
|
-
if (obj->get_object_id()
|
|
1262
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1339
1263
|
continue;
|
|
1340
1264
|
|
|
1341
|
-
if (request->method() == HTTP_GET && match.
|
|
1342
|
-
auto detail =
|
|
1343
|
-
auto *param = request->getParam("detail");
|
|
1344
|
-
if (param && param->value() == "all") {
|
|
1345
|
-
detail = DETAIL_ALL;
|
|
1346
|
-
}
|
|
1265
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1266
|
+
auto detail = get_request_detail(request);
|
|
1347
1267
|
std::string data = this->climate_json(obj, detail);
|
|
1348
1268
|
request->send(200, "application/json", data.c_str());
|
|
1349
1269
|
return;
|
|
1350
1270
|
}
|
|
1351
1271
|
|
|
1352
|
-
if (match.
|
|
1272
|
+
if (!match.method_equals("set")) {
|
|
1353
1273
|
request->send(404);
|
|
1354
1274
|
return;
|
|
1355
1275
|
}
|
|
@@ -1389,7 +1309,7 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url
|
|
|
1389
1309
|
call.set_target_temperature(*target_temperature);
|
|
1390
1310
|
}
|
|
1391
1311
|
|
|
1392
|
-
this->
|
|
1312
|
+
this->defer([call]() mutable { call.perform(); });
|
|
1393
1313
|
request->send(200);
|
|
1394
1314
|
return;
|
|
1395
1315
|
}
|
|
@@ -1402,6 +1322,7 @@ std::string WebServer::climate_all_json_generator(WebServer *web_server, void *s
|
|
|
1402
1322
|
return web_server->climate_json((climate::Climate *) (source), DETAIL_ALL);
|
|
1403
1323
|
}
|
|
1404
1324
|
std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_config) {
|
|
1325
|
+
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
1405
1326
|
return json::build_json([this, obj, start_config](JsonObject root) {
|
|
1406
1327
|
set_json_id(root, obj, "climate-" + obj->get_object_id(), start_config);
|
|
1407
1328
|
const auto traits = obj->get_traits();
|
|
@@ -1410,41 +1331,36 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf
|
|
|
1410
1331
|
char buf[16];
|
|
1411
1332
|
|
|
1412
1333
|
if (start_config == DETAIL_ALL) {
|
|
1413
|
-
JsonArray opt = root
|
|
1334
|
+
JsonArray opt = root["modes"].to<JsonArray>();
|
|
1414
1335
|
for (climate::ClimateMode m : traits.get_supported_modes())
|
|
1415
1336
|
opt.add(PSTR_LOCAL(climate::climate_mode_to_string(m)));
|
|
1416
1337
|
if (!traits.get_supported_custom_fan_modes().empty()) {
|
|
1417
|
-
JsonArray opt = root
|
|
1338
|
+
JsonArray opt = root["fan_modes"].to<JsonArray>();
|
|
1418
1339
|
for (climate::ClimateFanMode m : traits.get_supported_fan_modes())
|
|
1419
1340
|
opt.add(PSTR_LOCAL(climate::climate_fan_mode_to_string(m)));
|
|
1420
1341
|
}
|
|
1421
1342
|
|
|
1422
1343
|
if (!traits.get_supported_custom_fan_modes().empty()) {
|
|
1423
|
-
JsonArray opt = root
|
|
1344
|
+
JsonArray opt = root["custom_fan_modes"].to<JsonArray>();
|
|
1424
1345
|
for (auto const &custom_fan_mode : traits.get_supported_custom_fan_modes())
|
|
1425
1346
|
opt.add(custom_fan_mode);
|
|
1426
1347
|
}
|
|
1427
1348
|
if (traits.get_supports_swing_modes()) {
|
|
1428
|
-
JsonArray opt = root
|
|
1349
|
+
JsonArray opt = root["swing_modes"].to<JsonArray>();
|
|
1429
1350
|
for (auto swing_mode : traits.get_supported_swing_modes())
|
|
1430
1351
|
opt.add(PSTR_LOCAL(climate::climate_swing_mode_to_string(swing_mode)));
|
|
1431
1352
|
}
|
|
1432
1353
|
if (traits.get_supports_presets() && obj->preset.has_value()) {
|
|
1433
|
-
JsonArray opt = root
|
|
1354
|
+
JsonArray opt = root["presets"].to<JsonArray>();
|
|
1434
1355
|
for (climate::ClimatePreset m : traits.get_supported_presets())
|
|
1435
1356
|
opt.add(PSTR_LOCAL(climate::climate_preset_to_string(m)));
|
|
1436
1357
|
}
|
|
1437
1358
|
if (!traits.get_supported_custom_presets().empty() && obj->custom_preset.has_value()) {
|
|
1438
|
-
JsonArray opt = root
|
|
1359
|
+
JsonArray opt = root["custom_presets"].to<JsonArray>();
|
|
1439
1360
|
for (auto const &custom_preset : traits.get_supported_custom_presets())
|
|
1440
1361
|
opt.add(custom_preset);
|
|
1441
1362
|
}
|
|
1442
|
-
|
|
1443
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1444
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1445
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1446
|
-
}
|
|
1447
|
-
}
|
|
1363
|
+
this->add_sorting_info_(root, obj);
|
|
1448
1364
|
}
|
|
1449
1365
|
|
|
1450
1366
|
bool has_state = false;
|
|
@@ -1492,6 +1408,7 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf
|
|
|
1492
1408
|
root["state"] = root["target_temperature"];
|
|
1493
1409
|
}
|
|
1494
1410
|
});
|
|
1411
|
+
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
|
1495
1412
|
}
|
|
1496
1413
|
#endif
|
|
1497
1414
|
|
|
@@ -1503,25 +1420,21 @@ void WebServer::on_lock_update(lock::Lock *obj) {
|
|
|
1503
1420
|
}
|
|
1504
1421
|
void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1505
1422
|
for (lock::Lock *obj : App.get_locks()) {
|
|
1506
|
-
if (obj->get_object_id()
|
|
1423
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1507
1424
|
continue;
|
|
1508
1425
|
|
|
1509
|
-
if (request->method() == HTTP_GET && match.
|
|
1510
|
-
auto detail =
|
|
1511
|
-
auto *param = request->getParam("detail");
|
|
1512
|
-
if (param && param->value() == "all") {
|
|
1513
|
-
detail = DETAIL_ALL;
|
|
1514
|
-
}
|
|
1426
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1427
|
+
auto detail = get_request_detail(request);
|
|
1515
1428
|
std::string data = this->lock_json(obj, obj->state, detail);
|
|
1516
1429
|
request->send(200, "application/json", data.c_str());
|
|
1517
|
-
} else if (match.
|
|
1518
|
-
this->
|
|
1430
|
+
} else if (match.method_equals("lock")) {
|
|
1431
|
+
this->defer([obj]() { obj->lock(); });
|
|
1519
1432
|
request->send(200);
|
|
1520
|
-
} else if (match.
|
|
1521
|
-
this->
|
|
1433
|
+
} else if (match.method_equals("unlock")) {
|
|
1434
|
+
this->defer([obj]() { obj->unlock(); });
|
|
1522
1435
|
request->send(200);
|
|
1523
|
-
} else if (match.
|
|
1524
|
-
this->
|
|
1436
|
+
} else if (match.method_equals("open")) {
|
|
1437
|
+
this->defer([obj]() { obj->open(); });
|
|
1525
1438
|
request->send(200);
|
|
1526
1439
|
} else {
|
|
1527
1440
|
request->send(404);
|
|
@@ -1541,12 +1454,7 @@ std::string WebServer::lock_json(lock::Lock *obj, lock::LockState value, JsonDet
|
|
|
1541
1454
|
set_json_icon_state_value(root, obj, "lock-" + obj->get_object_id(), lock::lock_state_to_string(value), value,
|
|
1542
1455
|
start_config);
|
|
1543
1456
|
if (start_config == DETAIL_ALL) {
|
|
1544
|
-
|
|
1545
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1546
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1547
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1457
|
+
this->add_sorting_info_(root, obj);
|
|
1550
1458
|
}
|
|
1551
1459
|
});
|
|
1552
1460
|
}
|
|
@@ -1560,30 +1468,26 @@ void WebServer::on_valve_update(valve::Valve *obj) {
|
|
|
1560
1468
|
}
|
|
1561
1469
|
void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1562
1470
|
for (valve::Valve *obj : App.get_valves()) {
|
|
1563
|
-
if (obj->get_object_id()
|
|
1471
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1564
1472
|
continue;
|
|
1565
1473
|
|
|
1566
|
-
if (request->method() == HTTP_GET && match.
|
|
1567
|
-
auto detail =
|
|
1568
|
-
auto *param = request->getParam("detail");
|
|
1569
|
-
if (param && param->value() == "all") {
|
|
1570
|
-
detail = DETAIL_ALL;
|
|
1571
|
-
}
|
|
1474
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1475
|
+
auto detail = get_request_detail(request);
|
|
1572
1476
|
std::string data = this->valve_json(obj, detail);
|
|
1573
1477
|
request->send(200, "application/json", data.c_str());
|
|
1574
1478
|
return;
|
|
1575
1479
|
}
|
|
1576
1480
|
|
|
1577
1481
|
auto call = obj->make_call();
|
|
1578
|
-
if (match.
|
|
1482
|
+
if (match.method_equals("open")) {
|
|
1579
1483
|
call.set_command_open();
|
|
1580
|
-
} else if (match.
|
|
1484
|
+
} else if (match.method_equals("close")) {
|
|
1581
1485
|
call.set_command_close();
|
|
1582
|
-
} else if (match.
|
|
1486
|
+
} else if (match.method_equals("stop")) {
|
|
1583
1487
|
call.set_command_stop();
|
|
1584
|
-
} else if (match.
|
|
1488
|
+
} else if (match.method_equals("toggle")) {
|
|
1585
1489
|
call.set_command_toggle();
|
|
1586
|
-
} else if (match.
|
|
1490
|
+
} else if (!match.method_equals("set")) {
|
|
1587
1491
|
request->send(404);
|
|
1588
1492
|
return;
|
|
1589
1493
|
}
|
|
@@ -1601,7 +1505,7 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa
|
|
|
1601
1505
|
}
|
|
1602
1506
|
}
|
|
1603
1507
|
|
|
1604
|
-
this->
|
|
1508
|
+
this->defer([call]() mutable { call.perform(); });
|
|
1605
1509
|
request->send(200);
|
|
1606
1510
|
return;
|
|
1607
1511
|
}
|
|
@@ -1622,12 +1526,7 @@ std::string WebServer::valve_json(valve::Valve *obj, JsonDetail start_config) {
|
|
|
1622
1526
|
if (obj->get_traits().get_supports_position())
|
|
1623
1527
|
root["position"] = obj->position;
|
|
1624
1528
|
if (start_config == DETAIL_ALL) {
|
|
1625
|
-
|
|
1626
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1627
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1628
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1529
|
+
this->add_sorting_info_(root, obj);
|
|
1631
1530
|
}
|
|
1632
1531
|
});
|
|
1633
1532
|
}
|
|
@@ -1641,15 +1540,11 @@ void WebServer::on_alarm_control_panel_update(alarm_control_panel::AlarmControlP
|
|
|
1641
1540
|
}
|
|
1642
1541
|
void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1643
1542
|
for (alarm_control_panel::AlarmControlPanel *obj : App.get_alarm_control_panels()) {
|
|
1644
|
-
if (obj->get_object_id()
|
|
1543
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1645
1544
|
continue;
|
|
1646
1545
|
|
|
1647
|
-
if (request->method() == HTTP_GET && match.
|
|
1648
|
-
auto detail =
|
|
1649
|
-
auto *param = request->getParam("detail");
|
|
1650
|
-
if (param && param->value() == "all") {
|
|
1651
|
-
detail = DETAIL_ALL;
|
|
1652
|
-
}
|
|
1546
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1547
|
+
auto detail = get_request_detail(request);
|
|
1653
1548
|
std::string data = this->alarm_control_panel_json(obj, obj->get_state(), detail);
|
|
1654
1549
|
request->send(200, "application/json", data.c_str());
|
|
1655
1550
|
return;
|
|
@@ -1660,22 +1555,22 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques
|
|
|
1660
1555
|
call.set_code(request->getParam("code")->value().c_str()); // NOLINT
|
|
1661
1556
|
}
|
|
1662
1557
|
|
|
1663
|
-
if (match.
|
|
1558
|
+
if (match.method_equals("disarm")) {
|
|
1664
1559
|
call.disarm();
|
|
1665
|
-
} else if (match.
|
|
1560
|
+
} else if (match.method_equals("arm_away")) {
|
|
1666
1561
|
call.arm_away();
|
|
1667
|
-
} else if (match.
|
|
1562
|
+
} else if (match.method_equals("arm_home")) {
|
|
1668
1563
|
call.arm_home();
|
|
1669
|
-
} else if (match.
|
|
1564
|
+
} else if (match.method_equals("arm_night")) {
|
|
1670
1565
|
call.arm_night();
|
|
1671
|
-
} else if (match.
|
|
1566
|
+
} else if (match.method_equals("arm_vacation")) {
|
|
1672
1567
|
call.arm_vacation();
|
|
1673
1568
|
} else {
|
|
1674
1569
|
request->send(404);
|
|
1675
1570
|
return;
|
|
1676
1571
|
}
|
|
1677
1572
|
|
|
1678
|
-
this->
|
|
1573
|
+
this->defer([call]() mutable { call.perform(); });
|
|
1679
1574
|
request->send(200);
|
|
1680
1575
|
return;
|
|
1681
1576
|
}
|
|
@@ -1699,12 +1594,7 @@ std::string WebServer::alarm_control_panel_json(alarm_control_panel::AlarmContro
|
|
|
1699
1594
|
set_json_icon_state_value(root, obj, "alarm-control-panel-" + obj->get_object_id(),
|
|
1700
1595
|
PSTR_LOCAL(alarm_control_panel_state_to_string(value)), value, start_config);
|
|
1701
1596
|
if (start_config == DETAIL_ALL) {
|
|
1702
|
-
|
|
1703
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1704
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1705
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1706
|
-
}
|
|
1707
|
-
}
|
|
1597
|
+
this->add_sorting_info_(root, obj);
|
|
1708
1598
|
}
|
|
1709
1599
|
});
|
|
1710
1600
|
}
|
|
@@ -1717,15 +1607,11 @@ void WebServer::on_event(event::Event *obj, const std::string &event_type) {
|
|
|
1717
1607
|
|
|
1718
1608
|
void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1719
1609
|
for (event::Event *obj : App.get_events()) {
|
|
1720
|
-
if (obj->get_object_id()
|
|
1610
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1721
1611
|
continue;
|
|
1722
1612
|
|
|
1723
|
-
if (request->method() == HTTP_GET && match.
|
|
1724
|
-
auto detail =
|
|
1725
|
-
auto *param = request->getParam("detail");
|
|
1726
|
-
if (param && param->value() == "all") {
|
|
1727
|
-
detail = DETAIL_ALL;
|
|
1728
|
-
}
|
|
1613
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1614
|
+
auto detail = get_request_detail(request);
|
|
1729
1615
|
std::string data = this->event_json(obj, "", detail);
|
|
1730
1616
|
request->send(200, "application/json", data.c_str());
|
|
1731
1617
|
return;
|
|
@@ -1734,12 +1620,15 @@ void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMa
|
|
|
1734
1620
|
request->send(404);
|
|
1735
1621
|
}
|
|
1736
1622
|
|
|
1623
|
+
static std::string get_event_type(event::Event *event) { return event->last_event_type ? *event->last_event_type : ""; }
|
|
1624
|
+
|
|
1737
1625
|
std::string WebServer::event_state_json_generator(WebServer *web_server, void *source) {
|
|
1738
|
-
|
|
1739
|
-
|
|
1626
|
+
auto *event = static_cast<event::Event *>(source);
|
|
1627
|
+
return web_server->event_json(event, get_event_type(event), DETAIL_STATE);
|
|
1740
1628
|
}
|
|
1741
1629
|
std::string WebServer::event_all_json_generator(WebServer *web_server, void *source) {
|
|
1742
|
-
|
|
1630
|
+
auto *event = static_cast<event::Event *>(source);
|
|
1631
|
+
return web_server->event_json(event, get_event_type(event), DETAIL_ALL);
|
|
1743
1632
|
}
|
|
1744
1633
|
std::string WebServer::event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config) {
|
|
1745
1634
|
return json::build_json([this, obj, event_type, start_config](JsonObject root) {
|
|
@@ -1748,17 +1637,12 @@ std::string WebServer::event_json(event::Event *obj, const std::string &event_ty
|
|
|
1748
1637
|
root["event_type"] = event_type;
|
|
1749
1638
|
}
|
|
1750
1639
|
if (start_config == DETAIL_ALL) {
|
|
1751
|
-
JsonArray event_types = root
|
|
1640
|
+
JsonArray event_types = root["event_types"].to<JsonArray>();
|
|
1752
1641
|
for (auto const &event_type : obj->get_event_types()) {
|
|
1753
1642
|
event_types.add(event_type);
|
|
1754
1643
|
}
|
|
1755
1644
|
root["device_class"] = obj->get_device_class();
|
|
1756
|
-
|
|
1757
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1758
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1759
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1645
|
+
this->add_sorting_info_(root, obj);
|
|
1762
1646
|
}
|
|
1763
1647
|
});
|
|
1764
1648
|
}
|
|
@@ -1772,26 +1656,22 @@ void WebServer::on_update(update::UpdateEntity *obj) {
|
|
|
1772
1656
|
}
|
|
1773
1657
|
void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1774
1658
|
for (update::UpdateEntity *obj : App.get_updates()) {
|
|
1775
|
-
if (obj->get_object_id()
|
|
1659
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1776
1660
|
continue;
|
|
1777
1661
|
|
|
1778
|
-
if (request->method() == HTTP_GET && match.
|
|
1779
|
-
auto detail =
|
|
1780
|
-
auto *param = request->getParam("detail");
|
|
1781
|
-
if (param && param->value() == "all") {
|
|
1782
|
-
detail = DETAIL_ALL;
|
|
1783
|
-
}
|
|
1662
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1663
|
+
auto detail = get_request_detail(request);
|
|
1784
1664
|
std::string data = this->update_json(obj, detail);
|
|
1785
1665
|
request->send(200, "application/json", data.c_str());
|
|
1786
1666
|
return;
|
|
1787
1667
|
}
|
|
1788
1668
|
|
|
1789
|
-
if (match.
|
|
1669
|
+
if (!match.method_equals("install")) {
|
|
1790
1670
|
request->send(404);
|
|
1791
1671
|
return;
|
|
1792
1672
|
}
|
|
1793
1673
|
|
|
1794
|
-
this->
|
|
1674
|
+
this->defer([obj]() mutable { obj->perform(); });
|
|
1795
1675
|
request->send(200);
|
|
1796
1676
|
return;
|
|
1797
1677
|
}
|
|
@@ -1804,6 +1684,7 @@ std::string WebServer::update_all_json_generator(WebServer *web_server, void *so
|
|
|
1804
1684
|
return web_server->update_json((update::UpdateEntity *) (source), DETAIL_STATE);
|
|
1805
1685
|
}
|
|
1806
1686
|
std::string WebServer::update_json(update::UpdateEntity *obj, JsonDetail start_config) {
|
|
1687
|
+
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
1807
1688
|
return json::build_json([this, obj, start_config](JsonObject root) {
|
|
1808
1689
|
set_json_id(root, obj, "update-" + obj->get_object_id(), start_config);
|
|
1809
1690
|
root["value"] = obj->update_info.latest_version;
|
|
@@ -1826,18 +1707,14 @@ std::string WebServer::update_json(update::UpdateEntity *obj, JsonDetail start_c
|
|
|
1826
1707
|
root["title"] = obj->update_info.title;
|
|
1827
1708
|
root["summary"] = obj->update_info.summary;
|
|
1828
1709
|
root["release_url"] = obj->update_info.release_url;
|
|
1829
|
-
|
|
1830
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1831
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1832
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
1710
|
+
this->add_sorting_info_(root, obj);
|
|
1835
1711
|
}
|
|
1836
1712
|
});
|
|
1713
|
+
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
|
1837
1714
|
}
|
|
1838
1715
|
#endif
|
|
1839
1716
|
|
|
1840
|
-
bool WebServer::canHandle(AsyncWebServerRequest *request) {
|
|
1717
|
+
bool WebServer::canHandle(AsyncWebServerRequest *request) const {
|
|
1841
1718
|
if (request->url() == "/")
|
|
1842
1719
|
return true;
|
|
1843
1720
|
|
|
@@ -1859,116 +1736,114 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) {
|
|
|
1859
1736
|
|
|
1860
1737
|
#ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
|
|
1861
1738
|
if (request->method() == HTTP_OPTIONS && request->hasHeader(HEADER_CORS_REQ_PNA)) {
|
|
1862
|
-
#ifdef USE_ARDUINO
|
|
1863
|
-
// Header needs to be added to interesting header list for it to not be
|
|
1864
|
-
// nuked by the time we handle the request later.
|
|
1865
|
-
// Only required in Arduino framework.
|
|
1866
|
-
request->addInterestingHeader(HEADER_CORS_REQ_PNA);
|
|
1867
|
-
#endif
|
|
1868
1739
|
return true;
|
|
1869
1740
|
}
|
|
1870
1741
|
#endif
|
|
1871
1742
|
|
|
1872
|
-
|
|
1743
|
+
// Store the URL to prevent temporary string destruction
|
|
1744
|
+
// request->url() returns a reference to a String (on Arduino) or std::string (on ESP-IDF)
|
|
1745
|
+
// UrlMatch stores pointers to the string's data, so we must ensure the string outlives match_url()
|
|
1746
|
+
const auto &url = request->url();
|
|
1747
|
+
UrlMatch match = match_url(url.c_str(), url.length(), true);
|
|
1873
1748
|
if (!match.valid)
|
|
1874
1749
|
return false;
|
|
1875
1750
|
#ifdef USE_SENSOR
|
|
1876
|
-
if (request->method() == HTTP_GET && match.
|
|
1751
|
+
if (request->method() == HTTP_GET && match.domain_equals("sensor"))
|
|
1877
1752
|
return true;
|
|
1878
1753
|
#endif
|
|
1879
1754
|
|
|
1880
1755
|
#ifdef USE_SWITCH
|
|
1881
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1756
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("switch"))
|
|
1882
1757
|
return true;
|
|
1883
1758
|
#endif
|
|
1884
1759
|
|
|
1885
1760
|
#ifdef USE_BUTTON
|
|
1886
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1761
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("button"))
|
|
1887
1762
|
return true;
|
|
1888
1763
|
#endif
|
|
1889
1764
|
|
|
1890
1765
|
#ifdef USE_BINARY_SENSOR
|
|
1891
|
-
if (request->method() == HTTP_GET && match.
|
|
1766
|
+
if (request->method() == HTTP_GET && match.domain_equals("binary_sensor"))
|
|
1892
1767
|
return true;
|
|
1893
1768
|
#endif
|
|
1894
1769
|
|
|
1895
1770
|
#ifdef USE_FAN
|
|
1896
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1771
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("fan"))
|
|
1897
1772
|
return true;
|
|
1898
1773
|
#endif
|
|
1899
1774
|
|
|
1900
1775
|
#ifdef USE_LIGHT
|
|
1901
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1776
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("light"))
|
|
1902
1777
|
return true;
|
|
1903
1778
|
#endif
|
|
1904
1779
|
|
|
1905
1780
|
#ifdef USE_TEXT_SENSOR
|
|
1906
|
-
if (request->method() == HTTP_GET && match.
|
|
1781
|
+
if (request->method() == HTTP_GET && match.domain_equals("text_sensor"))
|
|
1907
1782
|
return true;
|
|
1908
1783
|
#endif
|
|
1909
1784
|
|
|
1910
1785
|
#ifdef USE_COVER
|
|
1911
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1786
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("cover"))
|
|
1912
1787
|
return true;
|
|
1913
1788
|
#endif
|
|
1914
1789
|
|
|
1915
1790
|
#ifdef USE_NUMBER
|
|
1916
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1791
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("number"))
|
|
1917
1792
|
return true;
|
|
1918
1793
|
#endif
|
|
1919
1794
|
|
|
1920
1795
|
#ifdef USE_DATETIME_DATE
|
|
1921
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1796
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("date"))
|
|
1922
1797
|
return true;
|
|
1923
1798
|
#endif
|
|
1924
1799
|
|
|
1925
1800
|
#ifdef USE_DATETIME_TIME
|
|
1926
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1801
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("time"))
|
|
1927
1802
|
return true;
|
|
1928
1803
|
#endif
|
|
1929
1804
|
|
|
1930
1805
|
#ifdef USE_DATETIME_DATETIME
|
|
1931
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1806
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("datetime"))
|
|
1932
1807
|
return true;
|
|
1933
1808
|
#endif
|
|
1934
1809
|
|
|
1935
1810
|
#ifdef USE_TEXT
|
|
1936
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1811
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("text"))
|
|
1937
1812
|
return true;
|
|
1938
1813
|
#endif
|
|
1939
1814
|
|
|
1940
1815
|
#ifdef USE_SELECT
|
|
1941
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1816
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("select"))
|
|
1942
1817
|
return true;
|
|
1943
1818
|
#endif
|
|
1944
1819
|
|
|
1945
1820
|
#ifdef USE_CLIMATE
|
|
1946
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1821
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("climate"))
|
|
1947
1822
|
return true;
|
|
1948
1823
|
#endif
|
|
1949
1824
|
|
|
1950
1825
|
#ifdef USE_LOCK
|
|
1951
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1826
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("lock"))
|
|
1952
1827
|
return true;
|
|
1953
1828
|
#endif
|
|
1954
1829
|
|
|
1955
1830
|
#ifdef USE_VALVE
|
|
1956
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1831
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("valve"))
|
|
1957
1832
|
return true;
|
|
1958
1833
|
#endif
|
|
1959
1834
|
|
|
1960
1835
|
#ifdef USE_ALARM_CONTROL_PANEL
|
|
1961
|
-
if ((request->method() == HTTP_GET || request->method() == HTTP_POST) && match.
|
|
1836
|
+
if ((request->method() == HTTP_GET || request->method() == HTTP_POST) && match.domain_equals("alarm_control_panel"))
|
|
1962
1837
|
return true;
|
|
1963
1838
|
#endif
|
|
1964
1839
|
|
|
1965
1840
|
#ifdef USE_EVENT
|
|
1966
|
-
if (request->method() == HTTP_GET && match.
|
|
1841
|
+
if (request->method() == HTTP_GET && match.domain_equals("event"))
|
|
1967
1842
|
return true;
|
|
1968
1843
|
#endif
|
|
1969
1844
|
|
|
1970
1845
|
#ifdef USE_UPDATE
|
|
1971
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1846
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("update"))
|
|
1972
1847
|
return true;
|
|
1973
1848
|
#endif
|
|
1974
1849
|
|
|
@@ -2008,114 +1883,117 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) {
|
|
|
2008
1883
|
}
|
|
2009
1884
|
#endif
|
|
2010
1885
|
|
|
2011
|
-
|
|
1886
|
+
// See comment in canHandle() for why we store the URL reference
|
|
1887
|
+
const auto &url = request->url();
|
|
1888
|
+
UrlMatch match = match_url(url.c_str(), url.length(), false);
|
|
1889
|
+
|
|
2012
1890
|
#ifdef USE_SENSOR
|
|
2013
|
-
if (match.
|
|
1891
|
+
if (match.domain_equals("sensor")) {
|
|
2014
1892
|
this->handle_sensor_request(request, match);
|
|
2015
1893
|
return;
|
|
2016
1894
|
}
|
|
2017
1895
|
#endif
|
|
2018
1896
|
|
|
2019
1897
|
#ifdef USE_SWITCH
|
|
2020
|
-
if (match.
|
|
1898
|
+
if (match.domain_equals("switch")) {
|
|
2021
1899
|
this->handle_switch_request(request, match);
|
|
2022
1900
|
return;
|
|
2023
1901
|
}
|
|
2024
1902
|
#endif
|
|
2025
1903
|
|
|
2026
1904
|
#ifdef USE_BUTTON
|
|
2027
|
-
if (match.
|
|
1905
|
+
if (match.domain_equals("button")) {
|
|
2028
1906
|
this->handle_button_request(request, match);
|
|
2029
1907
|
return;
|
|
2030
1908
|
}
|
|
2031
1909
|
#endif
|
|
2032
1910
|
|
|
2033
1911
|
#ifdef USE_BINARY_SENSOR
|
|
2034
|
-
if (match.
|
|
1912
|
+
if (match.domain_equals("binary_sensor")) {
|
|
2035
1913
|
this->handle_binary_sensor_request(request, match);
|
|
2036
1914
|
return;
|
|
2037
1915
|
}
|
|
2038
1916
|
#endif
|
|
2039
1917
|
|
|
2040
1918
|
#ifdef USE_FAN
|
|
2041
|
-
if (match.
|
|
1919
|
+
if (match.domain_equals("fan")) {
|
|
2042
1920
|
this->handle_fan_request(request, match);
|
|
2043
1921
|
return;
|
|
2044
1922
|
}
|
|
2045
1923
|
#endif
|
|
2046
1924
|
|
|
2047
1925
|
#ifdef USE_LIGHT
|
|
2048
|
-
if (match.
|
|
1926
|
+
if (match.domain_equals("light")) {
|
|
2049
1927
|
this->handle_light_request(request, match);
|
|
2050
1928
|
return;
|
|
2051
1929
|
}
|
|
2052
1930
|
#endif
|
|
2053
1931
|
|
|
2054
1932
|
#ifdef USE_TEXT_SENSOR
|
|
2055
|
-
if (match.
|
|
1933
|
+
if (match.domain_equals("text_sensor")) {
|
|
2056
1934
|
this->handle_text_sensor_request(request, match);
|
|
2057
1935
|
return;
|
|
2058
1936
|
}
|
|
2059
1937
|
#endif
|
|
2060
1938
|
|
|
2061
1939
|
#ifdef USE_COVER
|
|
2062
|
-
if (match.
|
|
1940
|
+
if (match.domain_equals("cover")) {
|
|
2063
1941
|
this->handle_cover_request(request, match);
|
|
2064
1942
|
return;
|
|
2065
1943
|
}
|
|
2066
1944
|
#endif
|
|
2067
1945
|
|
|
2068
1946
|
#ifdef USE_NUMBER
|
|
2069
|
-
if (match.
|
|
1947
|
+
if (match.domain_equals("number")) {
|
|
2070
1948
|
this->handle_number_request(request, match);
|
|
2071
1949
|
return;
|
|
2072
1950
|
}
|
|
2073
1951
|
#endif
|
|
2074
1952
|
|
|
2075
1953
|
#ifdef USE_DATETIME_DATE
|
|
2076
|
-
if (match.
|
|
1954
|
+
if (match.domain_equals("date")) {
|
|
2077
1955
|
this->handle_date_request(request, match);
|
|
2078
1956
|
return;
|
|
2079
1957
|
}
|
|
2080
1958
|
#endif
|
|
2081
1959
|
|
|
2082
1960
|
#ifdef USE_DATETIME_TIME
|
|
2083
|
-
if (match.
|
|
1961
|
+
if (match.domain_equals("time")) {
|
|
2084
1962
|
this->handle_time_request(request, match);
|
|
2085
1963
|
return;
|
|
2086
1964
|
}
|
|
2087
1965
|
#endif
|
|
2088
1966
|
|
|
2089
1967
|
#ifdef USE_DATETIME_DATETIME
|
|
2090
|
-
if (match.
|
|
1968
|
+
if (match.domain_equals("datetime")) {
|
|
2091
1969
|
this->handle_datetime_request(request, match);
|
|
2092
1970
|
return;
|
|
2093
1971
|
}
|
|
2094
1972
|
#endif
|
|
2095
1973
|
|
|
2096
1974
|
#ifdef USE_TEXT
|
|
2097
|
-
if (match.
|
|
1975
|
+
if (match.domain_equals("text")) {
|
|
2098
1976
|
this->handle_text_request(request, match);
|
|
2099
1977
|
return;
|
|
2100
1978
|
}
|
|
2101
1979
|
#endif
|
|
2102
1980
|
|
|
2103
1981
|
#ifdef USE_SELECT
|
|
2104
|
-
if (match.
|
|
1982
|
+
if (match.domain_equals("select")) {
|
|
2105
1983
|
this->handle_select_request(request, match);
|
|
2106
1984
|
return;
|
|
2107
1985
|
}
|
|
2108
1986
|
#endif
|
|
2109
1987
|
|
|
2110
1988
|
#ifdef USE_CLIMATE
|
|
2111
|
-
if (match.
|
|
1989
|
+
if (match.domain_equals("climate")) {
|
|
2112
1990
|
this->handle_climate_request(request, match);
|
|
2113
1991
|
return;
|
|
2114
1992
|
}
|
|
2115
1993
|
#endif
|
|
2116
1994
|
|
|
2117
1995
|
#ifdef USE_LOCK
|
|
2118
|
-
if (match.
|
|
1996
|
+
if (match.domain_equals("lock")) {
|
|
2119
1997
|
this->handle_lock_request(request, match);
|
|
2120
1998
|
|
|
2121
1999
|
return;
|
|
@@ -2123,14 +2001,14 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) {
|
|
|
2123
2001
|
#endif
|
|
2124
2002
|
|
|
2125
2003
|
#ifdef USE_VALVE
|
|
2126
|
-
if (match.
|
|
2004
|
+
if (match.domain_equals("valve")) {
|
|
2127
2005
|
this->handle_valve_request(request, match);
|
|
2128
2006
|
return;
|
|
2129
2007
|
}
|
|
2130
2008
|
#endif
|
|
2131
2009
|
|
|
2132
2010
|
#ifdef USE_ALARM_CONTROL_PANEL
|
|
2133
|
-
if (match.
|
|
2011
|
+
if (match.domain_equals("alarm_control_panel")) {
|
|
2134
2012
|
this->handle_alarm_control_panel_request(request, match);
|
|
2135
2013
|
|
|
2136
2014
|
return;
|
|
@@ -2138,15 +2016,31 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) {
|
|
|
2138
2016
|
#endif
|
|
2139
2017
|
|
|
2140
2018
|
#ifdef USE_UPDATE
|
|
2141
|
-
if (match.
|
|
2019
|
+
if (match.domain_equals("update")) {
|
|
2142
2020
|
this->handle_update_request(request, match);
|
|
2143
2021
|
return;
|
|
2144
2022
|
}
|
|
2145
2023
|
#endif
|
|
2024
|
+
|
|
2025
|
+
// No matching handler found - send 404
|
|
2026
|
+
ESP_LOGV(TAG, "Request for unknown URL: %s", request->url().c_str());
|
|
2027
|
+
request->send(404, "text/plain", "Not Found");
|
|
2146
2028
|
}
|
|
2147
2029
|
|
|
2148
|
-
bool WebServer::isRequestHandlerTrivial() { return false; }
|
|
2030
|
+
bool WebServer::isRequestHandlerTrivial() const { return false; }
|
|
2149
2031
|
|
|
2032
|
+
void WebServer::add_sorting_info_(JsonObject &root, EntityBase *entity) {
|
|
2033
|
+
#ifdef USE_WEBSERVER_SORTING
|
|
2034
|
+
if (this->sorting_entitys_.find(entity) != this->sorting_entitys_.end()) {
|
|
2035
|
+
root["sorting_weight"] = this->sorting_entitys_[entity].weight;
|
|
2036
|
+
if (this->sorting_groups_.find(this->sorting_entitys_[entity].group_id) != this->sorting_groups_.end()) {
|
|
2037
|
+
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[entity].group_id].name;
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
#endif
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
#ifdef USE_WEBSERVER_SORTING
|
|
2150
2044
|
void WebServer::add_entity_config(EntityBase *entity, float weight, uint64_t group) {
|
|
2151
2045
|
this->sorting_entitys_[entity] = SortingComponents{weight, group};
|
|
2152
2046
|
}
|
|
@@ -2154,16 +2048,7 @@ void WebServer::add_entity_config(EntityBase *entity, float weight, uint64_t gro
|
|
|
2154
2048
|
void WebServer::add_sorting_group(uint64_t group_id, const std::string &group_name, float weight) {
|
|
2155
2049
|
this->sorting_groups_[group_id] = SortingGroup{group_name, weight};
|
|
2156
2050
|
}
|
|
2157
|
-
|
|
2158
|
-
void WebServer::schedule_(std::function<void()> &&f) {
|
|
2159
|
-
#ifdef USE_ESP32
|
|
2160
|
-
xSemaphoreTake(this->to_schedule_lock_, portMAX_DELAY);
|
|
2161
|
-
to_schedule_.push_back(std::move(f));
|
|
2162
|
-
xSemaphoreGive(this->to_schedule_lock_);
|
|
2163
|
-
#else
|
|
2164
|
-
this->defer(std::move(f));
|
|
2165
2051
|
#endif
|
|
2166
|
-
}
|
|
2167
2052
|
|
|
2168
2053
|
} // namespace web_server
|
|
2169
2054
|
} // namespace esphome
|