esphome 2025.9.3__py3-none-any.whl → 2025.10.0b1__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 +87 -31
- esphome/address_cache.py +142 -0
- esphome/automation.py +130 -32
- esphome/build_gen/platformio.py +1 -3
- esphome/codegen.py +1 -0
- esphome/components/animation/animation.cpp +2 -2
- esphome/components/api/__init__.py +166 -3
- esphome/components/api/api_connection.cpp +84 -41
- esphome/components/api/api_connection.h +22 -16
- esphome/components/api/api_frame_helper.cpp +33 -19
- esphome/components/api/api_frame_helper.h +19 -4
- esphome/components/api/api_frame_helper_noise.cpp +41 -53
- esphome/components/api/api_frame_helper_noise.h +1 -1
- esphome/components/api/api_frame_helper_plaintext.cpp +22 -31
- esphome/components/api/api_frame_helper_plaintext.h +1 -1
- esphome/components/api/api_pb2.cpp +189 -15
- esphome/components/api/api_pb2.h +132 -20
- esphome/components/api/api_pb2_dump.cpp +97 -9
- esphome/components/api/api_pb2_service.cpp +118 -160
- esphome/components/api/api_pb2_service.h +31 -3
- esphome/components/api/api_server.cpp +68 -10
- esphome/components/api/api_server.h +32 -4
- esphome/components/api/custom_api_device.h +8 -8
- esphome/components/api/homeassistant_service.h +123 -6
- esphome/components/api/proto.h +6 -2
- esphome/components/api/user_services.h +2 -2
- esphome/components/as7341/sensor.py +1 -1
- esphome/components/audio/__init__.py +1 -1
- esphome/components/audio/audio.cpp +1 -1
- esphome/components/audio/audio_decoder.cpp +9 -9
- esphome/components/bl0906/bl0906.cpp +2 -2
- esphome/components/bl0942/bl0942.cpp +2 -2
- esphome/components/ble_client/__init__.py +1 -1
- esphome/components/bluetooth_proxy/__init__.py +4 -30
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +11 -4
- esphome/components/bluetooth_proxy/bluetooth_connection.h +2 -2
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +2 -2
- esphome/components/camera_encoder/__init__.py +2 -4
- esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +4 -2
- esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +3 -1
- esphome/components/canbus/canbus.cpp +7 -5
- esphome/components/canbus/canbus.h +4 -4
- esphome/components/captive_portal/__init__.py +18 -1
- esphome/components/captive_portal/captive_portal.cpp +40 -46
- esphome/components/captive_portal/captive_portal.h +20 -22
- esphome/components/captive_portal/dns_server_esp32_idf.cpp +205 -0
- esphome/components/captive_portal/dns_server_esp32_idf.h +27 -0
- esphome/components/ccs811/ccs811.cpp +1 -1
- esphome/components/climate/climate.cpp +10 -7
- esphome/components/cm1106/cm1106.cpp +1 -1
- esphome/components/copy/lock/copy_lock.cpp +1 -1
- esphome/components/cover/cover.cpp +1 -0
- esphome/components/daikin_arc/daikin_arc.cpp +19 -12
- esphome/components/deep_sleep/__init__.py +9 -2
- esphome/components/deep_sleep/deep_sleep_component.h +11 -9
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +51 -27
- esphome/components/ektf2232/touchscreen/__init__.py +8 -5
- esphome/components/ektf2232/touchscreen/ektf2232.cpp +4 -4
- esphome/components/ektf2232/touchscreen/ektf2232.h +2 -2
- esphome/components/epaper_spi/__init__.py +1 -0
- esphome/components/epaper_spi/display.py +80 -0
- esphome/components/epaper_spi/epaper_spi.cpp +227 -0
- esphome/components/epaper_spi/epaper_spi.h +93 -0
- esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.cpp +42 -0
- esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.h +45 -0
- esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +135 -0
- esphome/components/epaper_spi/epaper_spi_spectra_e6.h +23 -0
- esphome/components/es7210/es7210.cpp +3 -3
- esphome/components/esp32/__init__.py +254 -339
- esphome/components/esp32/boards.py +81 -0
- esphome/components/esp32/preferences.cpp +23 -17
- esphome/components/esp32_ble/__init__.py +159 -44
- esphome/components/esp32_ble/ble.cpp +47 -3
- esphome/components/esp32_ble/ble.h +18 -0
- esphome/components/esp32_ble/ble_advertising.cpp +7 -3
- esphome/components/esp32_ble/ble_advertising.h +4 -0
- esphome/components/esp32_ble/ble_uuid.cpp +16 -42
- esphome/components/esp32_ble_beacon/__init__.py +3 -4
- esphome/components/esp32_ble_client/ble_client_base.cpp +14 -12
- esphome/components/esp32_ble_server/__init__.py +28 -14
- esphome/components/esp32_ble_server/ble_characteristic.cpp +67 -57
- esphome/components/esp32_ble_server/ble_characteristic.h +27 -16
- esphome/components/esp32_ble_server/ble_descriptor.cpp +4 -3
- esphome/components/esp32_ble_server/ble_descriptor.h +13 -9
- esphome/components/esp32_ble_server/ble_server.cpp +59 -24
- esphome/components/esp32_ble_server/ble_server.h +38 -20
- esphome/components/esp32_ble_server/ble_server_automations.cpp +49 -33
- esphome/components/esp32_ble_server/ble_server_automations.h +39 -24
- esphome/components/esp32_ble_tracker/__init__.py +25 -80
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -4
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +0 -3
- esphome/components/esp32_camera/__init__.py +1 -3
- esphome/components/esp32_can/esp32_can.cpp +22 -4
- esphome/components/esp32_can/esp32_can.h +3 -0
- esphome/components/esp32_hosted/__init__.py +2 -1
- esphome/components/esp32_improv/esp32_improv_component.cpp +102 -44
- esphome/components/esp32_improv/esp32_improv_component.h +6 -1
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
- esphome/components/esp8266/__init__.py +3 -3
- esphome/components/esphome/ota/__init__.py +21 -2
- esphome/components/esphome/ota/ota_esphome.cpp +455 -145
- esphome/components/esphome/ota/ota_esphome.h +49 -2
- esphome/components/ethernet/__init__.py +39 -22
- esphome/components/ethernet/ethernet_component.cpp +28 -5
- esphome/components/ethernet/ethernet_component.h +5 -1
- esphome/components/external_components/__init__.py +8 -6
- esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
- esphome/components/fingerprint_grow/fingerprint_grow.h +2 -1
- esphome/components/font/__init__.py +5 -5
- esphome/components/graph/graph.cpp +1 -1
- esphome/components/graphical_display_menu/graphical_display_menu.cpp +3 -2
- esphome/components/haier/hon_climate.cpp +2 -2
- esphome/components/haier/hon_climate.h +1 -1
- esphome/components/hdc1080/hdc1080.cpp +42 -34
- esphome/components/hdc1080/hdc1080.h +1 -3
- esphome/components/homeassistant/number/homeassistant_number.cpp +2 -2
- esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
- esphome/components/http_request/__init__.py +3 -3
- esphome/components/htu21d/htu21d.cpp +13 -18
- esphome/components/htu21d/htu21d.h +1 -1
- esphome/components/i2s_audio/__init__.py +1 -2
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
- esphome/components/ili9xxx/ili9xxx_display.cpp +2 -2
- esphome/components/improv_serial/improv_serial_component.cpp +12 -15
- esphome/components/improv_serial/improv_serial_component.h +6 -8
- esphome/components/json/json_util.cpp +35 -43
- esphome/components/json/json_util.h +57 -0
- esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +2 -2
- esphome/components/key_collector/key_collector.h +4 -4
- esphome/components/libretiny/__init__.py +6 -6
- esphome/components/libretiny/preferences.cpp +23 -16
- esphome/components/light/light_call.cpp +98 -120
- esphome/components/light/light_call.h +17 -7
- esphome/components/lm75b/__init__.py +0 -0
- esphome/components/lm75b/lm75b.cpp +39 -0
- esphome/components/lm75b/lm75b.h +19 -0
- esphome/components/lm75b/sensor.py +34 -0
- esphome/components/lock/lock.h +12 -6
- esphome/components/logger/__init__.py +15 -27
- esphome/components/logger/logger.cpp +10 -20
- esphome/components/logger/logger.h +105 -62
- esphome/components/logger/logger_esp32.cpp +0 -48
- esphome/components/logger/logger_zephyr.cpp +2 -3
- esphome/components/logger/select/logger_level_select.cpp +6 -7
- esphome/components/logger/select/logger_level_select.h +7 -0
- esphome/components/ltr501/ltr501.cpp +7 -6
- esphome/components/ltr_als_ps/ltr_als_ps.cpp +7 -6
- esphome/components/matrix_keypad/matrix_keypad.h +4 -4
- esphome/components/max7219digit/max7219digit.cpp +1 -1
- esphome/components/mcp2515/mcp2515.cpp +31 -3
- esphome/components/mcp2515/mcp2515_defs.h +3 -1
- esphome/components/md5/md5.cpp +0 -26
- esphome/components/md5/md5.h +10 -20
- esphome/components/mdns/__init__.py +19 -6
- esphome/components/mdns/mdns_component.cpp +27 -59
- esphome/components/mdns/mdns_component.h +23 -10
- esphome/components/mdns/mdns_esp32.cpp +7 -7
- esphome/components/mdns/mdns_esp8266.cpp +6 -6
- esphome/components/mdns/mdns_libretiny.cpp +3 -3
- esphome/components/mdns/mdns_rp2040.cpp +3 -3
- esphome/components/mipi/__init__.py +1 -5
- esphome/components/mipi_spi/display.py +24 -8
- esphome/components/mipi_spi/mipi_spi.h +3 -3
- esphome/components/mixer/speaker/mixer_speaker.cpp +3 -3
- esphome/components/mmc5603/mmc5603.cpp +3 -3
- esphome/components/modbus/modbus.cpp +27 -13
- esphome/components/modbus/modbus.h +5 -3
- esphome/components/modbus/modbus_definitions.h +86 -0
- esphome/components/modbus_controller/__init__.py +29 -1
- esphome/components/modbus_controller/const.py +4 -0
- esphome/components/modbus_controller/modbus_controller.cpp +38 -13
- esphome/components/modbus_controller/modbus_controller.h +18 -29
- esphome/components/mpr121/mpr121.cpp +41 -42
- esphome/components/mpr121/mpr121.h +0 -1
- esphome/components/nau7802/nau7802.cpp +2 -2
- esphome/components/network/__init__.py +7 -3
- esphome/components/nextion/display.py +4 -4
- esphome/components/nextion/nextion.cpp +8 -8
- esphome/components/number/__init__.py +2 -0
- esphome/components/number/number_call.cpp +23 -12
- esphome/components/number/number_call.h +5 -0
- esphome/components/online_image/bmp_image.cpp +2 -1
- esphome/components/online_image/jpeg_image.cpp +4 -2
- esphome/components/openthread/openthread.cpp +6 -7
- esphome/components/openthread/openthread.h +0 -1
- esphome/components/ota/ota_backend.h +1 -0
- esphome/components/packages/__init__.py +10 -8
- esphome/components/packet_transport/packet_transport.cpp +2 -0
- esphome/components/pid/pid_controller.cpp +1 -1
- esphome/components/prometheus/prometheus_handler.cpp +239 -239
- esphome/components/psram/__init__.py +30 -28
- esphome/components/qmc5883l/qmc5883l.cpp +15 -0
- esphome/components/qmc5883l/qmc5883l.h +3 -0
- esphome/components/qmc5883l/sensor.py +31 -12
- esphome/components/remote_base/gobox_protocol.cpp +3 -3
- esphome/components/remote_receiver/__init__.py +14 -2
- esphome/components/remote_receiver/{remote_receiver_esp8266.cpp → remote_receiver.cpp} +2 -2
- esphome/components/remote_receiver/remote_receiver.h +4 -0
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +18 -1
- esphome/components/remote_transmitter/__init__.py +2 -2
- esphome/components/remote_transmitter/remote_transmitter.cpp +103 -0
- esphome/components/rp2040/__init__.py +11 -11
- esphome/components/rtttl/rtttl.cpp +2 -2
- esphome/components/scd30/sensor.py +1 -1
- esphome/components/script/__init__.py +1 -1
- esphome/components/script/script.h +7 -7
- esphome/components/select/select.cpp +5 -4
- esphome/components/select/select_call.cpp +1 -1
- esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
- esphome/components/sensor/__init__.py +2 -0
- esphome/components/sha256/__init__.py +22 -0
- esphome/components/sha256/sha256.cpp +116 -0
- esphome/components/sha256/sha256.h +60 -0
- esphome/components/socket/lwip_raw_tcp_impl.cpp +34 -6
- esphome/components/sonoff_d1/sonoff_d1.cpp +1 -1
- esphome/components/spi/__init__.py +0 -3
- esphome/components/split_buffer/__init__.py +5 -0
- esphome/components/split_buffer/split_buffer.cpp +133 -0
- esphome/components/split_buffer/split_buffer.h +40 -0
- esphome/components/sps30/sps30.cpp +14 -10
- esphome/components/sps30/sps30.h +2 -0
- esphome/components/st7567_i2c/st7567_i2c.cpp +3 -1
- esphome/components/st7789v/st7789v.cpp +3 -2
- esphome/components/statsd/statsd.cpp +1 -1
- esphome/components/substitutions/__init__.py +3 -1
- esphome/components/substitutions/jinja.py +13 -3
- esphome/components/sx126x/__init__.py +16 -0
- esphome/components/sx126x/sx126x.cpp +15 -1
- esphome/components/sx126x/sx126x.h +9 -1
- esphome/components/sx126x/sx126x_reg.h +2 -0
- esphome/components/text_sensor/text_sensor.cpp +16 -0
- esphome/components/text_sensor/text_sensor.h +3 -10
- esphome/components/tormatic/tormatic_cover.cpp +1 -1
- esphome/components/tuya/select/tuya_select.cpp +1 -1
- esphome/components/tuya/tuya.cpp +29 -4
- esphome/components/uart/__init__.py +36 -26
- esphome/components/uart/uart.h +6 -0
- esphome/components/uart/uart_component.cpp +8 -0
- esphome/components/uart/uart_component.h +28 -0
- esphome/components/uart/uart_component_esp_idf.cpp +64 -10
- esphome/components/uart/uart_component_esp_idf.h +5 -2
- esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
- esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +1 -1
- esphome/components/uponor_smatrix/uponor_smatrix.cpp +3 -3
- esphome/components/usb_host/__init__.py +2 -1
- esphome/components/usb_host/usb_host.h +82 -13
- esphome/components/usb_host/usb_host_client.cpp +180 -24
- esphome/components/usb_host/usb_host_component.cpp +1 -1
- esphome/components/usb_uart/__init__.py +0 -1
- esphome/components/usb_uart/ch34x.cpp +4 -4
- esphome/components/usb_uart/cp210x.cpp +3 -3
- esphome/components/usb_uart/usb_uart.cpp +88 -32
- esphome/components/usb_uart/usb_uart.h +30 -6
- esphome/components/valve/valve.cpp +1 -0
- esphome/components/veml7700/veml7700.cpp +7 -6
- esphome/components/version/version_text_sensor.cpp +2 -1
- esphome/components/voice_assistant/voice_assistant.cpp +3 -2
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +4 -4
- esphome/components/web_server/list_entities.cpp +3 -4
- esphome/components/web_server/list_entities.h +8 -10
- esphome/components/web_server/ota/__init__.py +1 -1
- esphome/components/web_server/ota/ota_web_server.cpp +9 -3
- esphome/components/web_server/web_server.cpp +509 -404
- esphome/components/web_server/web_server.h +5 -6
- esphome/components/web_server/web_server_v1.cpp +21 -19
- esphome/components/web_server_base/__init__.py +5 -2
- esphome/components/web_server_base/web_server_base.h +27 -7
- esphome/components/web_server_idf/__init__.py +1 -1
- esphome/components/web_server_idf/multipart.cpp +2 -2
- esphome/components/web_server_idf/multipart.h +2 -2
- esphome/components/web_server_idf/utils.cpp +2 -2
- esphome/components/web_server_idf/utils.h +2 -2
- esphome/components/web_server_idf/web_server_idf.cpp +118 -26
- esphome/components/web_server_idf/web_server_idf.h +12 -10
- esphome/components/wifi/__init__.py +13 -11
- esphome/components/wifi/wifi_component.cpp +73 -56
- esphome/components/wifi/wifi_component.h +4 -4
- esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
- esphome/components/wifi/wifi_component_esp_idf.cpp +24 -4
- esphome/components/wireguard/__init__.py +1 -1
- esphome/components/wts01/__init__.py +0 -0
- esphome/components/wts01/sensor.py +41 -0
- esphome/components/wts01/wts01.cpp +91 -0
- esphome/components/wts01/wts01.h +27 -0
- esphome/components/zephyr/__init__.py +5 -5
- esphome/components/zwave_proxy/__init__.py +43 -0
- esphome/components/zwave_proxy/zwave_proxy.cpp +346 -0
- esphome/components/zwave_proxy/zwave_proxy.h +93 -0
- esphome/config.py +79 -24
- esphome/config_validation.py +13 -15
- esphome/const.py +9 -2
- esphome/core/__init__.py +31 -22
- esphome/core/component.cpp +28 -18
- esphome/core/component_iterator.h +2 -1
- esphome/core/config.py +15 -15
- esphome/core/defines.h +19 -0
- esphome/core/hash_base.h +56 -0
- esphome/core/helpers.cpp +19 -3
- esphome/core/helpers.h +26 -0
- esphome/core/scheduler.cpp +5 -21
- esphome/core/scheduler.h +19 -8
- esphome/core/string_ref.h +1 -1
- esphome/core/time.cpp +5 -5
- esphome/cpp_generator.py +4 -29
- esphome/dashboard/const.py +21 -4
- esphome/dashboard/core.py +10 -8
- esphome/dashboard/dns.py +15 -0
- esphome/dashboard/entries.py +15 -21
- esphome/dashboard/models.py +76 -0
- esphome/dashboard/settings.py +7 -7
- esphome/dashboard/status/mdns.py +46 -2
- esphome/dashboard/web_server.py +367 -93
- esphome/espota2.py +111 -31
- esphome/external_files.py +6 -7
- esphome/git.py +8 -0
- esphome/helpers.py +124 -77
- esphome/loader.py +8 -9
- esphome/platformio_api.py +25 -18
- esphome/storage_json.py +26 -21
- esphome/types.py +30 -2
- esphome/util.py +32 -16
- esphome/vscode.py +8 -8
- esphome/wizard.py +10 -10
- esphome/writer.py +50 -15
- esphome/yaml_util.py +37 -31
- esphome/zeroconf.py +12 -3
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/METADATA +11 -11
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/RECORD +332 -312
- esphome/components/event_emitter/__init__.py +0 -5
- esphome/components/event_emitter/event_emitter.cpp +0 -14
- esphome/components/event_emitter/event_emitter.h +0 -63
- esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -125
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +0 -107
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +0 -110
- esphome/components/uart/uart_component_esp32_arduino.cpp +0 -214
- esphome/components/uart/uart_component_esp32_arduino.h +0 -60
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +0 -860
- esphome/core/string_ref.cpp +0 -12
- esphome/dashboard/util/file.py +0 -63
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/WHEEL +0 -0
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/entry_points.txt +0 -0
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,7 @@
|
|
1
1
|
#pragma once
|
2
2
|
|
3
|
+
#include "esphome/core/defines.h"
|
4
|
+
|
3
5
|
#ifdef USE_ESP32_CAMERA_JPEG_ENCODER
|
4
6
|
|
5
7
|
#include <esp_camera.h>
|
@@ -24,7 +26,7 @@ class ESP32CameraJPEGEncoder : public camera::Encoder {
|
|
24
26
|
void dump_config() override;
|
25
27
|
// -------------------------
|
26
28
|
protected:
|
27
|
-
static size_t
|
29
|
+
static size_t callback(void *arg, size_t index, const void *data, size_t len);
|
28
30
|
pixformat_t to_internal_(camera::PixelFormat format);
|
29
31
|
|
30
32
|
camera::EncoderBuffer *output_{};
|
@@ -21,8 +21,8 @@ void Canbus::dump_config() {
|
|
21
21
|
}
|
22
22
|
}
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
canbus::Error Canbus::send_data(uint32_t can_id, bool use_extended_id, bool remote_transmission_request,
|
25
|
+
const std::vector<uint8_t> &data) {
|
26
26
|
struct CanFrame can_message;
|
27
27
|
|
28
28
|
uint8_t size = static_cast<uint8_t>(data.size());
|
@@ -45,13 +45,15 @@ void Canbus::send_data(uint32_t can_id, bool use_extended_id, bool remote_transm
|
|
45
45
|
ESP_LOGVV(TAG, " data[%d]=%02x", i, can_message.data[i]);
|
46
46
|
}
|
47
47
|
|
48
|
-
|
48
|
+
canbus::Error error = this->send_message(&can_message);
|
49
|
+
if (error != canbus::ERROR_OK) {
|
49
50
|
if (use_extended_id) {
|
50
|
-
ESP_LOGW(TAG, "send to extended id=0x%08" PRIx32 " failed!", can_id);
|
51
|
+
ESP_LOGW(TAG, "send to extended id=0x%08" PRIx32 " failed with error %d!", can_id, error);
|
51
52
|
} else {
|
52
|
-
ESP_LOGW(TAG, "send to standard id=0x%03" PRIx32 " failed!", can_id);
|
53
|
+
ESP_LOGW(TAG, "send to standard id=0x%03" PRIx32 " failed with error %d!", can_id, error);
|
53
54
|
}
|
54
55
|
}
|
56
|
+
return error;
|
55
57
|
}
|
56
58
|
|
57
59
|
void Canbus::add_trigger(CanbusTrigger *trigger) {
|
@@ -70,11 +70,11 @@ class Canbus : public Component {
|
|
70
70
|
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
71
71
|
void loop() override;
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
canbus::Error send_data(uint32_t can_id, bool use_extended_id, bool remote_transmission_request,
|
74
|
+
const std::vector<uint8_t> &data);
|
75
|
+
canbus::Error send_data(uint32_t can_id, bool use_extended_id, const std::vector<uint8_t> &data) {
|
76
76
|
// for backwards compatibility only
|
77
|
-
this->send_data(can_id, use_extended_id, false, data);
|
77
|
+
return this->send_data(can_id, use_extended_id, false, data);
|
78
78
|
}
|
79
79
|
void set_can_id(uint32_t can_id) { this->can_id_ = can_id; }
|
80
80
|
void set_use_extended_id(bool use_extended_id) { this->use_extended_id_ = use_extended_id; }
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import esphome.codegen as cg
|
2
2
|
from esphome.components import web_server_base
|
3
3
|
from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID
|
4
|
+
from esphome.config_helpers import filter_source_files_from_platform
|
4
5
|
import esphome.config_validation as cv
|
5
6
|
from esphome.const import (
|
6
7
|
CONF_ID,
|
@@ -9,11 +10,19 @@ from esphome.const import (
|
|
9
10
|
PLATFORM_ESP8266,
|
10
11
|
PLATFORM_LN882X,
|
11
12
|
PLATFORM_RTL87XX,
|
13
|
+
PlatformFramework,
|
12
14
|
)
|
13
15
|
from esphome.core import CORE, coroutine_with_priority
|
14
16
|
from esphome.coroutine import CoroPriority
|
15
17
|
|
16
|
-
|
18
|
+
|
19
|
+
def AUTO_LOAD() -> list[str]:
|
20
|
+
auto_load = ["web_server_base", "ota.web_server"]
|
21
|
+
if CORE.using_esp_idf:
|
22
|
+
auto_load.append("socket")
|
23
|
+
return auto_load
|
24
|
+
|
25
|
+
|
17
26
|
DEPENDENCIES = ["wifi"]
|
18
27
|
CODEOWNERS = ["@esphome/core"]
|
19
28
|
|
@@ -58,3 +67,11 @@ async def to_code(config):
|
|
58
67
|
cg.add_library("DNSServer", None)
|
59
68
|
if CORE.is_libretiny:
|
60
69
|
cg.add_library("DNSServer", None)
|
70
|
+
|
71
|
+
|
72
|
+
# Only compile the ESP-IDF DNS server when using ESP-IDF framework
|
73
|
+
FILTER_SOURCE_FILES = filter_source_files_from_platform(
|
74
|
+
{
|
75
|
+
"dns_server_esp32_idf.cpp": {PlatformFramework.ESP32_IDF},
|
76
|
+
}
|
77
|
+
)
|
@@ -11,14 +11,14 @@ namespace captive_portal {
|
|
11
11
|
static const char *const TAG = "captive_portal";
|
12
12
|
|
13
13
|
void CaptivePortal::handle_config(AsyncWebServerRequest *request) {
|
14
|
-
AsyncResponseStream *stream = request->beginResponseStream(
|
15
|
-
stream->addHeader(
|
14
|
+
AsyncResponseStream *stream = request->beginResponseStream(ESPHOME_F("application/json"));
|
15
|
+
stream->addHeader(ESPHOME_F("cache-control"), ESPHOME_F("public, max-age=0, must-revalidate"));
|
16
16
|
#ifdef USE_ESP8266
|
17
|
-
stream->print(
|
17
|
+
stream->print(ESPHOME_F("{\"mac\":\""));
|
18
18
|
stream->print(get_mac_address_pretty().c_str());
|
19
|
-
stream->print(
|
19
|
+
stream->print(ESPHOME_F("\",\"name\":\""));
|
20
20
|
stream->print(App.get_name().c_str());
|
21
|
-
stream->print(
|
21
|
+
stream->print(ESPHOME_F("\",\"aps\":[{}"));
|
22
22
|
#else
|
23
23
|
stream->printf(R"({"mac":"%s","name":"%s","aps":[{})", get_mac_address_pretty().c_str(), App.get_name().c_str());
|
24
24
|
#endif
|
@@ -29,37 +29,35 @@ void CaptivePortal::handle_config(AsyncWebServerRequest *request) {
|
|
29
29
|
|
30
30
|
// Assumes no " in ssid, possible unicode isses?
|
31
31
|
#ifdef USE_ESP8266
|
32
|
-
stream->print(
|
32
|
+
stream->print(ESPHOME_F(",{\"ssid\":\""));
|
33
33
|
stream->print(scan.get_ssid().c_str());
|
34
|
-
stream->print(
|
34
|
+
stream->print(ESPHOME_F("\",\"rssi\":"));
|
35
35
|
stream->print(scan.get_rssi());
|
36
|
-
stream->print(
|
36
|
+
stream->print(ESPHOME_F(",\"lock\":"));
|
37
37
|
stream->print(scan.get_with_auth());
|
38
|
-
stream->print(
|
38
|
+
stream->print(ESPHOME_F("}"));
|
39
39
|
#else
|
40
40
|
stream->printf(R"(,{"ssid":"%s","rssi":%d,"lock":%d})", scan.get_ssid().c_str(), scan.get_rssi(),
|
41
41
|
scan.get_with_auth());
|
42
42
|
#endif
|
43
43
|
}
|
44
|
-
stream->print(
|
44
|
+
stream->print(ESPHOME_F("]}"));
|
45
45
|
request->send(stream);
|
46
46
|
}
|
47
47
|
void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) {
|
48
|
-
std::string ssid = request->arg("ssid").c_str();
|
49
|
-
std::string psk = request->arg("psk").c_str();
|
48
|
+
std::string ssid = request->arg("ssid").c_str(); // NOLINT(readability-redundant-string-cstr)
|
49
|
+
std::string psk = request->arg("psk").c_str(); // NOLINT(readability-redundant-string-cstr)
|
50
50
|
ESP_LOGI(TAG, "Requested WiFi Settings Change:");
|
51
51
|
ESP_LOGI(TAG, " SSID='%s'", ssid.c_str());
|
52
52
|
ESP_LOGI(TAG, " Password=" LOG_SECRET("'%s'"), psk.c_str());
|
53
53
|
wifi::global_wifi_component->save_wifi_sta(ssid, psk);
|
54
54
|
wifi::global_wifi_component->start_scanning();
|
55
|
-
request->redirect(
|
55
|
+
request->redirect(ESPHOME_F("/?save"));
|
56
56
|
}
|
57
57
|
|
58
58
|
void CaptivePortal::setup() {
|
59
|
-
|
60
|
-
// No DNS server needed for non-Arduino frameworks
|
59
|
+
// Disable loop by default - will be enabled when captive portal starts
|
61
60
|
this->disable_loop();
|
62
|
-
#endif
|
63
61
|
}
|
64
62
|
void CaptivePortal::start() {
|
65
63
|
this->base_->init();
|
@@ -67,51 +65,47 @@ void CaptivePortal::start() {
|
|
67
65
|
this->base_->add_handler(this);
|
68
66
|
}
|
69
67
|
|
68
|
+
network::IPAddress ip = wifi::global_wifi_component->wifi_soft_ap_ip();
|
69
|
+
|
70
|
+
#ifdef USE_ESP_IDF
|
71
|
+
// Create DNS server instance for ESP-IDF
|
72
|
+
this->dns_server_ = make_unique<DNSServer>();
|
73
|
+
this->dns_server_->start(ip);
|
74
|
+
#endif
|
70
75
|
#ifdef USE_ARDUINO
|
71
76
|
this->dns_server_ = make_unique<DNSServer>();
|
72
77
|
this->dns_server_->setErrorReplyCode(DNSReplyCode::NoError);
|
73
|
-
|
74
|
-
this->dns_server_->start(53, F("*"), ip);
|
75
|
-
// Re-enable loop() when DNS server is started
|
76
|
-
this->enable_loop();
|
77
|
-
#endif
|
78
|
-
|
79
|
-
this->base_->get_server()->onNotFound([this](AsyncWebServerRequest *req) {
|
80
|
-
if (!this->active_ || req->host().c_str() == wifi::global_wifi_component->wifi_soft_ap_ip().str()) {
|
81
|
-
req->send(404, F("text/html"), F("File not found"));
|
82
|
-
return;
|
83
|
-
}
|
84
|
-
|
85
|
-
#ifdef USE_ESP8266
|
86
|
-
String url = F("http://");
|
87
|
-
url += wifi::global_wifi_component->wifi_soft_ap_ip().str().c_str();
|
88
|
-
#else
|
89
|
-
auto url = "http://" + wifi::global_wifi_component->wifi_soft_ap_ip().str();
|
78
|
+
this->dns_server_->start(53, ESPHOME_F("*"), ip);
|
90
79
|
#endif
|
91
|
-
req->redirect(url.c_str());
|
92
|
-
});
|
93
80
|
|
94
81
|
this->initialized_ = true;
|
95
82
|
this->active_ = true;
|
83
|
+
|
84
|
+
// Enable loop() now that captive portal is active
|
85
|
+
this->enable_loop();
|
86
|
+
|
87
|
+
ESP_LOGV(TAG, "Captive portal started");
|
96
88
|
}
|
97
89
|
|
98
90
|
void CaptivePortal::handleRequest(AsyncWebServerRequest *req) {
|
99
|
-
if (req->url() ==
|
100
|
-
#ifndef USE_ESP8266
|
101
|
-
auto *response = req->beginResponse(200, F("text/html"), INDEX_GZ, sizeof(INDEX_GZ));
|
102
|
-
#else
|
103
|
-
auto *response = req->beginResponse_P(200, F("text/html"), INDEX_GZ, sizeof(INDEX_GZ));
|
104
|
-
#endif
|
105
|
-
response->addHeader(F("Content-Encoding"), F("gzip"));
|
106
|
-
req->send(response);
|
107
|
-
return;
|
108
|
-
} else if (req->url() == F("/config.json")) {
|
91
|
+
if (req->url() == ESPHOME_F("/config.json")) {
|
109
92
|
this->handle_config(req);
|
110
93
|
return;
|
111
|
-
} else if (req->url() ==
|
94
|
+
} else if (req->url() == ESPHOME_F("/wifisave")) {
|
112
95
|
this->handle_wifisave(req);
|
113
96
|
return;
|
114
97
|
}
|
98
|
+
|
99
|
+
// All other requests get the captive portal page
|
100
|
+
// This includes OS captive portal detection endpoints which will trigger
|
101
|
+
// the captive portal when they don't receive their expected responses
|
102
|
+
#ifndef USE_ESP8266
|
103
|
+
auto *response = req->beginResponse(200, ESPHOME_F("text/html"), INDEX_GZ, sizeof(INDEX_GZ));
|
104
|
+
#else
|
105
|
+
auto *response = req->beginResponse_P(200, ESPHOME_F("text/html"), INDEX_GZ, sizeof(INDEX_GZ));
|
106
|
+
#endif
|
107
|
+
response->addHeader(ESPHOME_F("Content-Encoding"), ESPHOME_F("gzip"));
|
108
|
+
req->send(response);
|
115
109
|
}
|
116
110
|
|
117
111
|
CaptivePortal::CaptivePortal(web_server_base::WebServerBase *base) : base_(base) { global_captive_portal = this; }
|
@@ -5,6 +5,9 @@
|
|
5
5
|
#ifdef USE_ARDUINO
|
6
6
|
#include <DNSServer.h>
|
7
7
|
#endif
|
8
|
+
#ifdef USE_ESP_IDF
|
9
|
+
#include "dns_server_esp32_idf.h"
|
10
|
+
#endif
|
8
11
|
#include "esphome/core/component.h"
|
9
12
|
#include "esphome/core/helpers.h"
|
10
13
|
#include "esphome/core/preferences.h"
|
@@ -19,41 +22,36 @@ class CaptivePortal : public AsyncWebHandler, public Component {
|
|
19
22
|
CaptivePortal(web_server_base::WebServerBase *base);
|
20
23
|
void setup() override;
|
21
24
|
void dump_config() override;
|
22
|
-
#ifdef USE_ARDUINO
|
23
25
|
void loop() override {
|
26
|
+
#ifdef USE_ARDUINO
|
24
27
|
if (this->dns_server_ != nullptr) {
|
25
28
|
this->dns_server_->processNextRequest();
|
26
|
-
} else {
|
27
|
-
this->disable_loop();
|
28
29
|
}
|
29
|
-
}
|
30
30
|
#endif
|
31
|
+
#ifdef USE_ESP_IDF
|
32
|
+
if (this->dns_server_ != nullptr) {
|
33
|
+
this->dns_server_->process_next_request();
|
34
|
+
}
|
35
|
+
#endif
|
36
|
+
}
|
31
37
|
float get_setup_priority() const override;
|
32
38
|
void start();
|
33
39
|
bool is_active() const { return this->active_; }
|
34
40
|
void end() {
|
35
41
|
this->active_ = false;
|
42
|
+
this->disable_loop(); // Stop processing DNS requests
|
36
43
|
this->base_->deinit();
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
44
|
+
if (this->dns_server_ != nullptr) {
|
45
|
+
this->dns_server_->stop();
|
46
|
+
this->dns_server_ = nullptr;
|
47
|
+
}
|
41
48
|
}
|
42
49
|
|
43
50
|
bool canHandle(AsyncWebServerRequest *request) const override {
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
if (request->url() == F("/"))
|
49
|
-
return true;
|
50
|
-
if (request->url() == F("/config.json"))
|
51
|
-
return true;
|
52
|
-
if (request->url() == F("/wifisave"))
|
53
|
-
return true;
|
54
|
-
}
|
55
|
-
|
56
|
-
return false;
|
51
|
+
// Handle all GET requests when captive portal is active
|
52
|
+
// This allows us to respond with the portal page for any URL,
|
53
|
+
// triggering OS captive portal detection
|
54
|
+
return this->active_ && request->method() == HTTP_GET;
|
57
55
|
}
|
58
56
|
|
59
57
|
void handle_config(AsyncWebServerRequest *request);
|
@@ -66,7 +64,7 @@ class CaptivePortal : public AsyncWebHandler, public Component {
|
|
66
64
|
web_server_base::WebServerBase *base_;
|
67
65
|
bool initialized_{false};
|
68
66
|
bool active_{false};
|
69
|
-
#
|
67
|
+
#if defined(USE_ARDUINO) || defined(USE_ESP_IDF)
|
70
68
|
std::unique_ptr<DNSServer> dns_server_{nullptr};
|
71
69
|
#endif
|
72
70
|
};
|
@@ -0,0 +1,205 @@
|
|
1
|
+
#include "dns_server_esp32_idf.h"
|
2
|
+
#ifdef USE_ESP_IDF
|
3
|
+
|
4
|
+
#include "esphome/core/log.h"
|
5
|
+
#include "esphome/core/hal.h"
|
6
|
+
#include "esphome/components/socket/socket.h"
|
7
|
+
#include <lwip/sockets.h>
|
8
|
+
#include <lwip/inet.h>
|
9
|
+
|
10
|
+
namespace esphome::captive_portal {
|
11
|
+
|
12
|
+
static const char *const TAG = "captive_portal.dns";
|
13
|
+
|
14
|
+
// DNS constants
|
15
|
+
static constexpr uint16_t DNS_PORT = 53;
|
16
|
+
static constexpr uint16_t DNS_QR_FLAG = 1 << 15;
|
17
|
+
static constexpr uint16_t DNS_OPCODE_MASK = 0x7800;
|
18
|
+
static constexpr uint16_t DNS_QTYPE_A = 0x0001;
|
19
|
+
static constexpr uint16_t DNS_QCLASS_IN = 0x0001;
|
20
|
+
static constexpr uint16_t DNS_ANSWER_TTL = 300;
|
21
|
+
|
22
|
+
// DNS Header structure
|
23
|
+
struct DNSHeader {
|
24
|
+
uint16_t id;
|
25
|
+
uint16_t flags;
|
26
|
+
uint16_t qd_count;
|
27
|
+
uint16_t an_count;
|
28
|
+
uint16_t ns_count;
|
29
|
+
uint16_t ar_count;
|
30
|
+
} __attribute__((packed));
|
31
|
+
|
32
|
+
// DNS Question structure
|
33
|
+
struct DNSQuestion {
|
34
|
+
uint16_t type;
|
35
|
+
uint16_t dns_class;
|
36
|
+
} __attribute__((packed));
|
37
|
+
|
38
|
+
// DNS Answer structure
|
39
|
+
struct DNSAnswer {
|
40
|
+
uint16_t ptr_offset;
|
41
|
+
uint16_t type;
|
42
|
+
uint16_t dns_class;
|
43
|
+
uint32_t ttl;
|
44
|
+
uint16_t addr_len;
|
45
|
+
uint32_t ip_addr;
|
46
|
+
} __attribute__((packed));
|
47
|
+
|
48
|
+
void DNSServer::start(const network::IPAddress &ip) {
|
49
|
+
this->server_ip_ = ip;
|
50
|
+
ESP_LOGV(TAG, "Starting DNS server on %s", ip.str().c_str());
|
51
|
+
|
52
|
+
// Create loop-monitored UDP socket
|
53
|
+
this->socket_ = socket::socket_ip_loop_monitored(SOCK_DGRAM, IPPROTO_UDP);
|
54
|
+
if (this->socket_ == nullptr) {
|
55
|
+
ESP_LOGE(TAG, "Socket create failed");
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
|
59
|
+
// Set socket options
|
60
|
+
int enable = 1;
|
61
|
+
this->socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
|
62
|
+
|
63
|
+
// Bind to port 53
|
64
|
+
struct sockaddr_storage server_addr = {};
|
65
|
+
socklen_t addr_len = socket::set_sockaddr_any((struct sockaddr *) &server_addr, sizeof(server_addr), DNS_PORT);
|
66
|
+
|
67
|
+
int err = this->socket_->bind((struct sockaddr *) &server_addr, addr_len);
|
68
|
+
if (err != 0) {
|
69
|
+
ESP_LOGE(TAG, "Bind failed: %d", errno);
|
70
|
+
this->socket_ = nullptr;
|
71
|
+
return;
|
72
|
+
}
|
73
|
+
ESP_LOGV(TAG, "Bound to port %d", DNS_PORT);
|
74
|
+
}
|
75
|
+
|
76
|
+
void DNSServer::stop() {
|
77
|
+
if (this->socket_ != nullptr) {
|
78
|
+
this->socket_->close();
|
79
|
+
this->socket_ = nullptr;
|
80
|
+
}
|
81
|
+
ESP_LOGV(TAG, "Stopped");
|
82
|
+
}
|
83
|
+
|
84
|
+
void DNSServer::process_next_request() {
|
85
|
+
// Process one request if socket is valid and data is available
|
86
|
+
if (this->socket_ == nullptr || !this->socket_->ready()) {
|
87
|
+
return;
|
88
|
+
}
|
89
|
+
struct sockaddr_in client_addr;
|
90
|
+
socklen_t client_addr_len = sizeof(client_addr);
|
91
|
+
|
92
|
+
// Receive DNS request using raw fd for recvfrom
|
93
|
+
int fd = this->socket_->get_fd();
|
94
|
+
if (fd < 0) {
|
95
|
+
return;
|
96
|
+
}
|
97
|
+
|
98
|
+
ssize_t len = recvfrom(fd, this->buffer_, sizeof(this->buffer_), MSG_DONTWAIT, (struct sockaddr *) &client_addr,
|
99
|
+
&client_addr_len);
|
100
|
+
|
101
|
+
if (len < 0) {
|
102
|
+
if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
|
103
|
+
ESP_LOGE(TAG, "recvfrom failed: %d", errno);
|
104
|
+
}
|
105
|
+
return;
|
106
|
+
}
|
107
|
+
|
108
|
+
ESP_LOGVV(TAG, "Received %d bytes from %s:%d", len, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
|
109
|
+
|
110
|
+
if (len < static_cast<ssize_t>(sizeof(DNSHeader) + 1)) {
|
111
|
+
ESP_LOGV(TAG, "Request too short: %d", len);
|
112
|
+
return;
|
113
|
+
}
|
114
|
+
|
115
|
+
// Parse DNS header
|
116
|
+
DNSHeader *header = (DNSHeader *) this->buffer_;
|
117
|
+
uint16_t flags = ntohs(header->flags);
|
118
|
+
uint16_t qd_count = ntohs(header->qd_count);
|
119
|
+
|
120
|
+
// Check if it's a standard query
|
121
|
+
if ((flags & DNS_QR_FLAG) || (flags & DNS_OPCODE_MASK) || qd_count != 1) {
|
122
|
+
ESP_LOGV(TAG, "Not a standard query: flags=0x%04X, qd_count=%d", flags, qd_count);
|
123
|
+
return; // Not a standard query
|
124
|
+
}
|
125
|
+
|
126
|
+
// Parse domain name (we don't actually care about it - redirect everything)
|
127
|
+
uint8_t *ptr = this->buffer_ + sizeof(DNSHeader);
|
128
|
+
uint8_t *end = this->buffer_ + len;
|
129
|
+
|
130
|
+
while (ptr < end && *ptr != 0) {
|
131
|
+
uint8_t label_len = *ptr;
|
132
|
+
if (label_len > 63) { // Check for invalid label length
|
133
|
+
return;
|
134
|
+
}
|
135
|
+
// Check if we have room for this label plus the length byte
|
136
|
+
if (ptr + label_len + 1 > end) {
|
137
|
+
return; // Would overflow
|
138
|
+
}
|
139
|
+
ptr += label_len + 1;
|
140
|
+
}
|
141
|
+
|
142
|
+
// Check if we reached a proper null terminator
|
143
|
+
if (ptr >= end || *ptr != 0) {
|
144
|
+
return; // Name not terminated or truncated
|
145
|
+
}
|
146
|
+
ptr++; // Skip the null terminator
|
147
|
+
|
148
|
+
// Check we have room for the question
|
149
|
+
if (ptr + sizeof(DNSQuestion) > end) {
|
150
|
+
return; // Request truncated
|
151
|
+
}
|
152
|
+
|
153
|
+
// Parse DNS question
|
154
|
+
DNSQuestion *question = (DNSQuestion *) ptr;
|
155
|
+
uint16_t qtype = ntohs(question->type);
|
156
|
+
uint16_t qclass = ntohs(question->dns_class);
|
157
|
+
|
158
|
+
// We only handle A queries
|
159
|
+
if (qtype != DNS_QTYPE_A || qclass != DNS_QCLASS_IN) {
|
160
|
+
ESP_LOGV(TAG, "Not an A query: type=0x%04X, class=0x%04X", qtype, qclass);
|
161
|
+
return; // Not an A query
|
162
|
+
}
|
163
|
+
|
164
|
+
// Build DNS response by modifying the request in-place
|
165
|
+
header->flags = htons(DNS_QR_FLAG | 0x8000); // Response + Authoritative
|
166
|
+
header->an_count = htons(1); // One answer
|
167
|
+
|
168
|
+
// Add answer section after the question
|
169
|
+
size_t question_len = (ptr + sizeof(DNSQuestion)) - this->buffer_ - sizeof(DNSHeader);
|
170
|
+
size_t answer_offset = sizeof(DNSHeader) + question_len;
|
171
|
+
|
172
|
+
// Check if we have room for the answer
|
173
|
+
if (answer_offset + sizeof(DNSAnswer) > sizeof(this->buffer_)) {
|
174
|
+
ESP_LOGW(TAG, "Response too large");
|
175
|
+
return;
|
176
|
+
}
|
177
|
+
|
178
|
+
DNSAnswer *answer = (DNSAnswer *) (this->buffer_ + answer_offset);
|
179
|
+
|
180
|
+
// Pointer to name in question (offset from start of packet)
|
181
|
+
answer->ptr_offset = htons(0xC000 | sizeof(DNSHeader));
|
182
|
+
answer->type = htons(DNS_QTYPE_A);
|
183
|
+
answer->dns_class = htons(DNS_QCLASS_IN);
|
184
|
+
answer->ttl = htonl(DNS_ANSWER_TTL);
|
185
|
+
answer->addr_len = htons(4);
|
186
|
+
|
187
|
+
// Get the raw IP address
|
188
|
+
ip4_addr_t addr = this->server_ip_;
|
189
|
+
answer->ip_addr = addr.addr;
|
190
|
+
|
191
|
+
size_t response_len = answer_offset + sizeof(DNSAnswer);
|
192
|
+
|
193
|
+
// Send response
|
194
|
+
ssize_t sent =
|
195
|
+
this->socket_->sendto(this->buffer_, response_len, 0, (struct sockaddr *) &client_addr, client_addr_len);
|
196
|
+
if (sent < 0) {
|
197
|
+
ESP_LOGV(TAG, "Send failed: %d", errno);
|
198
|
+
} else {
|
199
|
+
ESP_LOGV(TAG, "Sent %d bytes", sent);
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
} // namespace esphome::captive_portal
|
204
|
+
|
205
|
+
#endif // USE_ESP_IDF
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#pragma once
|
2
|
+
#ifdef USE_ESP_IDF
|
3
|
+
|
4
|
+
#include <memory>
|
5
|
+
#include "esphome/core/helpers.h"
|
6
|
+
#include "esphome/components/network/ip_address.h"
|
7
|
+
#include "esphome/components/socket/socket.h"
|
8
|
+
|
9
|
+
namespace esphome::captive_portal {
|
10
|
+
|
11
|
+
class DNSServer {
|
12
|
+
public:
|
13
|
+
void start(const network::IPAddress &ip);
|
14
|
+
void stop();
|
15
|
+
void process_next_request();
|
16
|
+
|
17
|
+
protected:
|
18
|
+
static constexpr size_t DNS_BUFFER_SIZE = 192;
|
19
|
+
|
20
|
+
std::unique_ptr<socket::Socket> socket_{nullptr};
|
21
|
+
network::IPAddress server_ip_;
|
22
|
+
uint8_t buffer_[DNS_BUFFER_SIZE];
|
23
|
+
};
|
24
|
+
|
25
|
+
} // namespace esphome::captive_portal
|
26
|
+
|
27
|
+
#endif // USE_ESP_IDF
|
@@ -155,7 +155,7 @@ void CCS811Component::dump_config() {
|
|
155
155
|
LOG_UPDATE_INTERVAL(this);
|
156
156
|
LOG_SENSOR(" ", "CO2 Sensor", this->co2_);
|
157
157
|
LOG_SENSOR(" ", "TVOC Sensor", this->tvoc_);
|
158
|
-
LOG_TEXT_SENSOR(" ", "Firmware Version Sensor", this->version_)
|
158
|
+
LOG_TEXT_SENSOR(" ", "Firmware Version Sensor", this->version_);
|
159
159
|
if (this->baseline_) {
|
160
160
|
ESP_LOGCONFIG(TAG, " Baseline: %04X", *this->baseline_);
|
161
161
|
} else {
|
@@ -367,9 +367,11 @@ void Climate::save_state_() {
|
|
367
367
|
state.uses_custom_fan_mode = true;
|
368
368
|
const auto &supported = traits.get_supported_custom_fan_modes();
|
369
369
|
std::vector<std::string> vec{supported.begin(), supported.end()};
|
370
|
-
|
371
|
-
|
372
|
-
|
370
|
+
for (size_t i = 0; i < vec.size(); i++) {
|
371
|
+
if (vec[i] == custom_fan_mode) {
|
372
|
+
state.custom_fan_mode = i;
|
373
|
+
break;
|
374
|
+
}
|
373
375
|
}
|
374
376
|
}
|
375
377
|
if (traits.get_supports_presets() && preset.has_value()) {
|
@@ -380,10 +382,11 @@ void Climate::save_state_() {
|
|
380
382
|
state.uses_custom_preset = true;
|
381
383
|
const auto &supported = traits.get_supported_custom_presets();
|
382
384
|
std::vector<std::string> vec{supported.begin(), supported.end()};
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
385
|
+
for (size_t i = 0; i < vec.size(); i++) {
|
386
|
+
if (vec[i] == custom_preset) {
|
387
|
+
state.custom_preset = i;
|
388
|
+
break;
|
389
|
+
}
|
387
390
|
}
|
388
391
|
}
|
389
392
|
if (traits.get_supports_swing_modes()) {
|
@@ -13,7 +13,7 @@ static const uint8_t C_M1106_CMD_SET_CO2_CALIB_RESPONSE[4] = {0x16, 0x01, 0x03,
|
|
13
13
|
|
14
14
|
uint8_t cm1106_checksum(const uint8_t *response, size_t len) {
|
15
15
|
uint8_t crc = 0;
|
16
|
-
for (
|
16
|
+
for (size_t i = 0; i < len - 1; i++) {
|
17
17
|
crc -= response[i];
|
18
18
|
}
|
19
19
|
return crc;
|
@@ -11,7 +11,7 @@ void CopyLock::setup() {
|
|
11
11
|
|
12
12
|
traits.set_assumed_state(source_->traits.get_assumed_state());
|
13
13
|
traits.set_requires_code(source_->traits.get_requires_code());
|
14
|
-
traits.
|
14
|
+
traits.set_supported_states_mask(source_->traits.get_supported_states_mask());
|
15
15
|
traits.set_supports_open(source_->traits.get_supports_open());
|
16
16
|
|
17
17
|
this->publish_state(source_->state);
|