esphome 2025.6.3__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 +8 -2
- 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.h +1 -0
- 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 +0 -4
- 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 +318 -436
- 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.3.dist-info → esphome-2025.7.0.dist-info}/METADATA +10 -9
- {esphome-2025.6.3.dist-info → esphome-2025.7.0.dist-info}/RECORD +637 -578
- 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.3.dist-info → esphome-2025.7.0.dist-info}/WHEEL +0 -0
- {esphome-2025.6.3.dist-info → esphome-2025.7.0.dist-info}/entry_points.txt +0 -0
- {esphome-2025.6.3.dist-info → esphome-2025.7.0.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.6.3.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;
|
|
@@ -1751,17 +1637,12 @@ std::string WebServer::event_json(event::Event *obj, const std::string &event_ty
|
|
|
1751
1637
|
root["event_type"] = event_type;
|
|
1752
1638
|
}
|
|
1753
1639
|
if (start_config == DETAIL_ALL) {
|
|
1754
|
-
JsonArray event_types = root
|
|
1640
|
+
JsonArray event_types = root["event_types"].to<JsonArray>();
|
|
1755
1641
|
for (auto const &event_type : obj->get_event_types()) {
|
|
1756
1642
|
event_types.add(event_type);
|
|
1757
1643
|
}
|
|
1758
1644
|
root["device_class"] = obj->get_device_class();
|
|
1759
|
-
|
|
1760
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1761
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1762
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1763
|
-
}
|
|
1764
|
-
}
|
|
1645
|
+
this->add_sorting_info_(root, obj);
|
|
1765
1646
|
}
|
|
1766
1647
|
});
|
|
1767
1648
|
}
|
|
@@ -1775,26 +1656,22 @@ void WebServer::on_update(update::UpdateEntity *obj) {
|
|
|
1775
1656
|
}
|
|
1776
1657
|
void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlMatch &match) {
|
|
1777
1658
|
for (update::UpdateEntity *obj : App.get_updates()) {
|
|
1778
|
-
if (obj->get_object_id()
|
|
1659
|
+
if (!match.id_equals(obj->get_object_id()))
|
|
1779
1660
|
continue;
|
|
1780
1661
|
|
|
1781
|
-
if (request->method() == HTTP_GET && match.
|
|
1782
|
-
auto detail =
|
|
1783
|
-
auto *param = request->getParam("detail");
|
|
1784
|
-
if (param && param->value() == "all") {
|
|
1785
|
-
detail = DETAIL_ALL;
|
|
1786
|
-
}
|
|
1662
|
+
if (request->method() == HTTP_GET && match.method_empty()) {
|
|
1663
|
+
auto detail = get_request_detail(request);
|
|
1787
1664
|
std::string data = this->update_json(obj, detail);
|
|
1788
1665
|
request->send(200, "application/json", data.c_str());
|
|
1789
1666
|
return;
|
|
1790
1667
|
}
|
|
1791
1668
|
|
|
1792
|
-
if (match.
|
|
1669
|
+
if (!match.method_equals("install")) {
|
|
1793
1670
|
request->send(404);
|
|
1794
1671
|
return;
|
|
1795
1672
|
}
|
|
1796
1673
|
|
|
1797
|
-
this->
|
|
1674
|
+
this->defer([obj]() mutable { obj->perform(); });
|
|
1798
1675
|
request->send(200);
|
|
1799
1676
|
return;
|
|
1800
1677
|
}
|
|
@@ -1807,6 +1684,7 @@ std::string WebServer::update_all_json_generator(WebServer *web_server, void *so
|
|
|
1807
1684
|
return web_server->update_json((update::UpdateEntity *) (source), DETAIL_STATE);
|
|
1808
1685
|
}
|
|
1809
1686
|
std::string WebServer::update_json(update::UpdateEntity *obj, JsonDetail start_config) {
|
|
1687
|
+
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
|
1810
1688
|
return json::build_json([this, obj, start_config](JsonObject root) {
|
|
1811
1689
|
set_json_id(root, obj, "update-" + obj->get_object_id(), start_config);
|
|
1812
1690
|
root["value"] = obj->update_info.latest_version;
|
|
@@ -1829,18 +1707,14 @@ std::string WebServer::update_json(update::UpdateEntity *obj, JsonDetail start_c
|
|
|
1829
1707
|
root["title"] = obj->update_info.title;
|
|
1830
1708
|
root["summary"] = obj->update_info.summary;
|
|
1831
1709
|
root["release_url"] = obj->update_info.release_url;
|
|
1832
|
-
|
|
1833
|
-
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
|
|
1834
|
-
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
|
|
1835
|
-
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
|
|
1836
|
-
}
|
|
1837
|
-
}
|
|
1710
|
+
this->add_sorting_info_(root, obj);
|
|
1838
1711
|
}
|
|
1839
1712
|
});
|
|
1713
|
+
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
|
1840
1714
|
}
|
|
1841
1715
|
#endif
|
|
1842
1716
|
|
|
1843
|
-
bool WebServer::canHandle(AsyncWebServerRequest *request) {
|
|
1717
|
+
bool WebServer::canHandle(AsyncWebServerRequest *request) const {
|
|
1844
1718
|
if (request->url() == "/")
|
|
1845
1719
|
return true;
|
|
1846
1720
|
|
|
@@ -1862,116 +1736,114 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) {
|
|
|
1862
1736
|
|
|
1863
1737
|
#ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS
|
|
1864
1738
|
if (request->method() == HTTP_OPTIONS && request->hasHeader(HEADER_CORS_REQ_PNA)) {
|
|
1865
|
-
#ifdef USE_ARDUINO
|
|
1866
|
-
// Header needs to be added to interesting header list for it to not be
|
|
1867
|
-
// nuked by the time we handle the request later.
|
|
1868
|
-
// Only required in Arduino framework.
|
|
1869
|
-
request->addInterestingHeader(HEADER_CORS_REQ_PNA);
|
|
1870
|
-
#endif
|
|
1871
1739
|
return true;
|
|
1872
1740
|
}
|
|
1873
1741
|
#endif
|
|
1874
1742
|
|
|
1875
|
-
|
|
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);
|
|
1876
1748
|
if (!match.valid)
|
|
1877
1749
|
return false;
|
|
1878
1750
|
#ifdef USE_SENSOR
|
|
1879
|
-
if (request->method() == HTTP_GET && match.
|
|
1751
|
+
if (request->method() == HTTP_GET && match.domain_equals("sensor"))
|
|
1880
1752
|
return true;
|
|
1881
1753
|
#endif
|
|
1882
1754
|
|
|
1883
1755
|
#ifdef USE_SWITCH
|
|
1884
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1756
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("switch"))
|
|
1885
1757
|
return true;
|
|
1886
1758
|
#endif
|
|
1887
1759
|
|
|
1888
1760
|
#ifdef USE_BUTTON
|
|
1889
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1761
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("button"))
|
|
1890
1762
|
return true;
|
|
1891
1763
|
#endif
|
|
1892
1764
|
|
|
1893
1765
|
#ifdef USE_BINARY_SENSOR
|
|
1894
|
-
if (request->method() == HTTP_GET && match.
|
|
1766
|
+
if (request->method() == HTTP_GET && match.domain_equals("binary_sensor"))
|
|
1895
1767
|
return true;
|
|
1896
1768
|
#endif
|
|
1897
1769
|
|
|
1898
1770
|
#ifdef USE_FAN
|
|
1899
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1771
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("fan"))
|
|
1900
1772
|
return true;
|
|
1901
1773
|
#endif
|
|
1902
1774
|
|
|
1903
1775
|
#ifdef USE_LIGHT
|
|
1904
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1776
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("light"))
|
|
1905
1777
|
return true;
|
|
1906
1778
|
#endif
|
|
1907
1779
|
|
|
1908
1780
|
#ifdef USE_TEXT_SENSOR
|
|
1909
|
-
if (request->method() == HTTP_GET && match.
|
|
1781
|
+
if (request->method() == HTTP_GET && match.domain_equals("text_sensor"))
|
|
1910
1782
|
return true;
|
|
1911
1783
|
#endif
|
|
1912
1784
|
|
|
1913
1785
|
#ifdef USE_COVER
|
|
1914
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1786
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("cover"))
|
|
1915
1787
|
return true;
|
|
1916
1788
|
#endif
|
|
1917
1789
|
|
|
1918
1790
|
#ifdef USE_NUMBER
|
|
1919
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1791
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("number"))
|
|
1920
1792
|
return true;
|
|
1921
1793
|
#endif
|
|
1922
1794
|
|
|
1923
1795
|
#ifdef USE_DATETIME_DATE
|
|
1924
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1796
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("date"))
|
|
1925
1797
|
return true;
|
|
1926
1798
|
#endif
|
|
1927
1799
|
|
|
1928
1800
|
#ifdef USE_DATETIME_TIME
|
|
1929
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1801
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("time"))
|
|
1930
1802
|
return true;
|
|
1931
1803
|
#endif
|
|
1932
1804
|
|
|
1933
1805
|
#ifdef USE_DATETIME_DATETIME
|
|
1934
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1806
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("datetime"))
|
|
1935
1807
|
return true;
|
|
1936
1808
|
#endif
|
|
1937
1809
|
|
|
1938
1810
|
#ifdef USE_TEXT
|
|
1939
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1811
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("text"))
|
|
1940
1812
|
return true;
|
|
1941
1813
|
#endif
|
|
1942
1814
|
|
|
1943
1815
|
#ifdef USE_SELECT
|
|
1944
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1816
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("select"))
|
|
1945
1817
|
return true;
|
|
1946
1818
|
#endif
|
|
1947
1819
|
|
|
1948
1820
|
#ifdef USE_CLIMATE
|
|
1949
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1821
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("climate"))
|
|
1950
1822
|
return true;
|
|
1951
1823
|
#endif
|
|
1952
1824
|
|
|
1953
1825
|
#ifdef USE_LOCK
|
|
1954
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1826
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("lock"))
|
|
1955
1827
|
return true;
|
|
1956
1828
|
#endif
|
|
1957
1829
|
|
|
1958
1830
|
#ifdef USE_VALVE
|
|
1959
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1831
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("valve"))
|
|
1960
1832
|
return true;
|
|
1961
1833
|
#endif
|
|
1962
1834
|
|
|
1963
1835
|
#ifdef USE_ALARM_CONTROL_PANEL
|
|
1964
|
-
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"))
|
|
1965
1837
|
return true;
|
|
1966
1838
|
#endif
|
|
1967
1839
|
|
|
1968
1840
|
#ifdef USE_EVENT
|
|
1969
|
-
if (request->method() == HTTP_GET && match.
|
|
1841
|
+
if (request->method() == HTTP_GET && match.domain_equals("event"))
|
|
1970
1842
|
return true;
|
|
1971
1843
|
#endif
|
|
1972
1844
|
|
|
1973
1845
|
#ifdef USE_UPDATE
|
|
1974
|
-
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.
|
|
1846
|
+
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain_equals("update"))
|
|
1975
1847
|
return true;
|
|
1976
1848
|
#endif
|
|
1977
1849
|
|
|
@@ -2011,114 +1883,117 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) {
|
|
|
2011
1883
|
}
|
|
2012
1884
|
#endif
|
|
2013
1885
|
|
|
2014
|
-
|
|
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
|
+
|
|
2015
1890
|
#ifdef USE_SENSOR
|
|
2016
|
-
if (match.
|
|
1891
|
+
if (match.domain_equals("sensor")) {
|
|
2017
1892
|
this->handle_sensor_request(request, match);
|
|
2018
1893
|
return;
|
|
2019
1894
|
}
|
|
2020
1895
|
#endif
|
|
2021
1896
|
|
|
2022
1897
|
#ifdef USE_SWITCH
|
|
2023
|
-
if (match.
|
|
1898
|
+
if (match.domain_equals("switch")) {
|
|
2024
1899
|
this->handle_switch_request(request, match);
|
|
2025
1900
|
return;
|
|
2026
1901
|
}
|
|
2027
1902
|
#endif
|
|
2028
1903
|
|
|
2029
1904
|
#ifdef USE_BUTTON
|
|
2030
|
-
if (match.
|
|
1905
|
+
if (match.domain_equals("button")) {
|
|
2031
1906
|
this->handle_button_request(request, match);
|
|
2032
1907
|
return;
|
|
2033
1908
|
}
|
|
2034
1909
|
#endif
|
|
2035
1910
|
|
|
2036
1911
|
#ifdef USE_BINARY_SENSOR
|
|
2037
|
-
if (match.
|
|
1912
|
+
if (match.domain_equals("binary_sensor")) {
|
|
2038
1913
|
this->handle_binary_sensor_request(request, match);
|
|
2039
1914
|
return;
|
|
2040
1915
|
}
|
|
2041
1916
|
#endif
|
|
2042
1917
|
|
|
2043
1918
|
#ifdef USE_FAN
|
|
2044
|
-
if (match.
|
|
1919
|
+
if (match.domain_equals("fan")) {
|
|
2045
1920
|
this->handle_fan_request(request, match);
|
|
2046
1921
|
return;
|
|
2047
1922
|
}
|
|
2048
1923
|
#endif
|
|
2049
1924
|
|
|
2050
1925
|
#ifdef USE_LIGHT
|
|
2051
|
-
if (match.
|
|
1926
|
+
if (match.domain_equals("light")) {
|
|
2052
1927
|
this->handle_light_request(request, match);
|
|
2053
1928
|
return;
|
|
2054
1929
|
}
|
|
2055
1930
|
#endif
|
|
2056
1931
|
|
|
2057
1932
|
#ifdef USE_TEXT_SENSOR
|
|
2058
|
-
if (match.
|
|
1933
|
+
if (match.domain_equals("text_sensor")) {
|
|
2059
1934
|
this->handle_text_sensor_request(request, match);
|
|
2060
1935
|
return;
|
|
2061
1936
|
}
|
|
2062
1937
|
#endif
|
|
2063
1938
|
|
|
2064
1939
|
#ifdef USE_COVER
|
|
2065
|
-
if (match.
|
|
1940
|
+
if (match.domain_equals("cover")) {
|
|
2066
1941
|
this->handle_cover_request(request, match);
|
|
2067
1942
|
return;
|
|
2068
1943
|
}
|
|
2069
1944
|
#endif
|
|
2070
1945
|
|
|
2071
1946
|
#ifdef USE_NUMBER
|
|
2072
|
-
if (match.
|
|
1947
|
+
if (match.domain_equals("number")) {
|
|
2073
1948
|
this->handle_number_request(request, match);
|
|
2074
1949
|
return;
|
|
2075
1950
|
}
|
|
2076
1951
|
#endif
|
|
2077
1952
|
|
|
2078
1953
|
#ifdef USE_DATETIME_DATE
|
|
2079
|
-
if (match.
|
|
1954
|
+
if (match.domain_equals("date")) {
|
|
2080
1955
|
this->handle_date_request(request, match);
|
|
2081
1956
|
return;
|
|
2082
1957
|
}
|
|
2083
1958
|
#endif
|
|
2084
1959
|
|
|
2085
1960
|
#ifdef USE_DATETIME_TIME
|
|
2086
|
-
if (match.
|
|
1961
|
+
if (match.domain_equals("time")) {
|
|
2087
1962
|
this->handle_time_request(request, match);
|
|
2088
1963
|
return;
|
|
2089
1964
|
}
|
|
2090
1965
|
#endif
|
|
2091
1966
|
|
|
2092
1967
|
#ifdef USE_DATETIME_DATETIME
|
|
2093
|
-
if (match.
|
|
1968
|
+
if (match.domain_equals("datetime")) {
|
|
2094
1969
|
this->handle_datetime_request(request, match);
|
|
2095
1970
|
return;
|
|
2096
1971
|
}
|
|
2097
1972
|
#endif
|
|
2098
1973
|
|
|
2099
1974
|
#ifdef USE_TEXT
|
|
2100
|
-
if (match.
|
|
1975
|
+
if (match.domain_equals("text")) {
|
|
2101
1976
|
this->handle_text_request(request, match);
|
|
2102
1977
|
return;
|
|
2103
1978
|
}
|
|
2104
1979
|
#endif
|
|
2105
1980
|
|
|
2106
1981
|
#ifdef USE_SELECT
|
|
2107
|
-
if (match.
|
|
1982
|
+
if (match.domain_equals("select")) {
|
|
2108
1983
|
this->handle_select_request(request, match);
|
|
2109
1984
|
return;
|
|
2110
1985
|
}
|
|
2111
1986
|
#endif
|
|
2112
1987
|
|
|
2113
1988
|
#ifdef USE_CLIMATE
|
|
2114
|
-
if (match.
|
|
1989
|
+
if (match.domain_equals("climate")) {
|
|
2115
1990
|
this->handle_climate_request(request, match);
|
|
2116
1991
|
return;
|
|
2117
1992
|
}
|
|
2118
1993
|
#endif
|
|
2119
1994
|
|
|
2120
1995
|
#ifdef USE_LOCK
|
|
2121
|
-
if (match.
|
|
1996
|
+
if (match.domain_equals("lock")) {
|
|
2122
1997
|
this->handle_lock_request(request, match);
|
|
2123
1998
|
|
|
2124
1999
|
return;
|
|
@@ -2126,14 +2001,14 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) {
|
|
|
2126
2001
|
#endif
|
|
2127
2002
|
|
|
2128
2003
|
#ifdef USE_VALVE
|
|
2129
|
-
if (match.
|
|
2004
|
+
if (match.domain_equals("valve")) {
|
|
2130
2005
|
this->handle_valve_request(request, match);
|
|
2131
2006
|
return;
|
|
2132
2007
|
}
|
|
2133
2008
|
#endif
|
|
2134
2009
|
|
|
2135
2010
|
#ifdef USE_ALARM_CONTROL_PANEL
|
|
2136
|
-
if (match.
|
|
2011
|
+
if (match.domain_equals("alarm_control_panel")) {
|
|
2137
2012
|
this->handle_alarm_control_panel_request(request, match);
|
|
2138
2013
|
|
|
2139
2014
|
return;
|
|
@@ -2141,15 +2016,31 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) {
|
|
|
2141
2016
|
#endif
|
|
2142
2017
|
|
|
2143
2018
|
#ifdef USE_UPDATE
|
|
2144
|
-
if (match.
|
|
2019
|
+
if (match.domain_equals("update")) {
|
|
2145
2020
|
this->handle_update_request(request, match);
|
|
2146
2021
|
return;
|
|
2147
2022
|
}
|
|
2148
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");
|
|
2149
2028
|
}
|
|
2150
2029
|
|
|
2151
|
-
bool WebServer::isRequestHandlerTrivial() { return false; }
|
|
2030
|
+
bool WebServer::isRequestHandlerTrivial() const { return false; }
|
|
2152
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
|
|
2153
2044
|
void WebServer::add_entity_config(EntityBase *entity, float weight, uint64_t group) {
|
|
2154
2045
|
this->sorting_entitys_[entity] = SortingComponents{weight, group};
|
|
2155
2046
|
}
|
|
@@ -2157,16 +2048,7 @@ void WebServer::add_entity_config(EntityBase *entity, float weight, uint64_t gro
|
|
|
2157
2048
|
void WebServer::add_sorting_group(uint64_t group_id, const std::string &group_name, float weight) {
|
|
2158
2049
|
this->sorting_groups_[group_id] = SortingGroup{group_name, weight};
|
|
2159
2050
|
}
|
|
2160
|
-
|
|
2161
|
-
void WebServer::schedule_(std::function<void()> &&f) {
|
|
2162
|
-
#ifdef USE_ESP32
|
|
2163
|
-
xSemaphoreTake(this->to_schedule_lock_, portMAX_DELAY);
|
|
2164
|
-
to_schedule_.push_back(std::move(f));
|
|
2165
|
-
xSemaphoreGive(this->to_schedule_lock_);
|
|
2166
|
-
#else
|
|
2167
|
-
this->defer(std::move(f));
|
|
2168
2051
|
#endif
|
|
2169
|
-
}
|
|
2170
2052
|
|
|
2171
2053
|
} // namespace web_server
|
|
2172
2054
|
} // namespace esphome
|