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
esphome/config_validation.py
CHANGED
@@ -15,7 +15,7 @@ from ipaddress import (
|
|
15
15
|
ip_network,
|
16
16
|
)
|
17
17
|
import logging
|
18
|
-
import
|
18
|
+
from pathlib import Path
|
19
19
|
import re
|
20
20
|
from string import ascii_letters, digits
|
21
21
|
import uuid as uuid_
|
@@ -1609,34 +1609,32 @@ def dimensions(value):
|
|
1609
1609
|
return dimensions([match.group(1), match.group(2)])
|
1610
1610
|
|
1611
1611
|
|
1612
|
-
def directory(value):
|
1612
|
+
def directory(value: object) -> Path:
|
1613
1613
|
value = string(value)
|
1614
1614
|
path = CORE.relative_config_path(value)
|
1615
1615
|
|
1616
|
-
if not
|
1616
|
+
if not path.exists():
|
1617
1617
|
raise Invalid(
|
1618
|
-
f"Could not find directory '{path}'. Please make sure it exists (full path: {
|
1618
|
+
f"Could not find directory '{path}'. Please make sure it exists (full path: {path.resolve()})."
|
1619
1619
|
)
|
1620
|
-
if not
|
1620
|
+
if not path.is_dir():
|
1621
1621
|
raise Invalid(
|
1622
|
-
f"Path '{path}' is not a directory (full path: {
|
1622
|
+
f"Path '{path}' is not a directory (full path: {path.resolve()})."
|
1623
1623
|
)
|
1624
|
-
return
|
1624
|
+
return path
|
1625
1625
|
|
1626
1626
|
|
1627
|
-
def file_(value):
|
1627
|
+
def file_(value: object) -> Path:
|
1628
1628
|
value = string(value)
|
1629
1629
|
path = CORE.relative_config_path(value)
|
1630
1630
|
|
1631
|
-
if not
|
1632
|
-
raise Invalid(
|
1633
|
-
f"Could not find file '{path}'. Please make sure it exists (full path: {os.path.abspath(path)})."
|
1634
|
-
)
|
1635
|
-
if not os.path.isfile(path):
|
1631
|
+
if not path.exists():
|
1636
1632
|
raise Invalid(
|
1637
|
-
f"
|
1633
|
+
f"Could not find file '{path}'. Please make sure it exists (full path: {path.resolve()})."
|
1638
1634
|
)
|
1639
|
-
|
1635
|
+
if not path.is_file():
|
1636
|
+
raise Invalid(f"Path '{path}' is not a file (full path: {path.resolve()}).")
|
1637
|
+
return path
|
1640
1638
|
|
1641
1639
|
|
1642
1640
|
ENTITY_ID_CHARACTERS = "abcdefghijklmnopqrstuvwxyz0123456789_"
|
esphome/const.py
CHANGED
@@ -4,7 +4,7 @@ from enum import Enum
|
|
4
4
|
|
5
5
|
from esphome.enum import StrEnum
|
6
6
|
|
7
|
-
__version__ = "2025.
|
7
|
+
__version__ = "2025.10.0b1"
|
8
8
|
|
9
9
|
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
10
10
|
VALID_SUBSTITUTIONS_CHARACTERS = (
|
@@ -174,6 +174,7 @@ CONF_CALIBRATE_LINEAR = "calibrate_linear"
|
|
174
174
|
CONF_CALIBRATION = "calibration"
|
175
175
|
CONF_CAPACITANCE = "capacitance"
|
176
176
|
CONF_CAPACITY = "capacity"
|
177
|
+
CONF_CAPTURE_RESPONSE = "capture_response"
|
177
178
|
CONF_CARBON_MONOXIDE = "carbon_monoxide"
|
178
179
|
CONF_CARRIER_DUTY_PERCENT = "carrier_duty_percent"
|
179
180
|
CONF_CARRIER_FREQUENCY = "carrier_frequency"
|
@@ -186,6 +187,7 @@ CONF_CHARACTERISTIC_UUID = "characteristic_uuid"
|
|
186
187
|
CONF_CHECK = "check"
|
187
188
|
CONF_CHIPSET = "chipset"
|
188
189
|
CONF_CLEAN_SESSION = "clean_session"
|
190
|
+
CONF_CLEAR = "clear"
|
189
191
|
CONF_CLEAR_IMPEDANCE = "clear_impedance"
|
190
192
|
CONF_CLIENT_CERTIFICATE = "client_certificate"
|
191
193
|
CONF_CLIENT_CERTIFICATE_KEY = "client_certificate_key"
|
@@ -541,6 +543,7 @@ CONF_MANUAL_IP = "manual_ip"
|
|
541
543
|
CONF_MANUFACTURER_ID = "manufacturer_id"
|
542
544
|
CONF_MASK_DISTURBER = "mask_disturber"
|
543
545
|
CONF_MAX_BRIGHTNESS = "max_brightness"
|
546
|
+
CONF_MAX_CONNECTIONS = "max_connections"
|
544
547
|
CONF_MAX_COOLING_RUN_TIME = "max_cooling_run_time"
|
545
548
|
CONF_MAX_CURRENT = "max_current"
|
546
549
|
CONF_MAX_DURATION = "max_duration"
|
@@ -670,9 +673,11 @@ CONF_ON_PRESET_SET = "on_preset_set"
|
|
670
673
|
CONF_ON_PRESS = "on_press"
|
671
674
|
CONF_ON_RAW_VALUE = "on_raw_value"
|
672
675
|
CONF_ON_RELEASE = "on_release"
|
676
|
+
CONF_ON_RESPONSE = "on_response"
|
673
677
|
CONF_ON_SHUTDOWN = "on_shutdown"
|
674
678
|
CONF_ON_SPEED_SET = "on_speed_set"
|
675
679
|
CONF_ON_STATE = "on_state"
|
680
|
+
CONF_ON_SUCCESS = "on_success"
|
676
681
|
CONF_ON_TAG = "on_tag"
|
677
682
|
CONF_ON_TAG_REMOVED = "on_tag_removed"
|
678
683
|
CONF_ON_TIME = "on_time"
|
@@ -815,6 +820,7 @@ CONF_RESET_DURATION = "reset_duration"
|
|
815
820
|
CONF_RESET_PIN = "reset_pin"
|
816
821
|
CONF_RESIZE = "resize"
|
817
822
|
CONF_RESOLUTION = "resolution"
|
823
|
+
CONF_RESPONSE_TEMPLATE = "response_template"
|
818
824
|
CONF_RESTART = "restart"
|
819
825
|
CONF_RESTORE = "restore"
|
820
826
|
CONF_RESTORE_MODE = "restore_mode"
|
@@ -1167,7 +1173,7 @@ UNIT_KILOMETER = "km"
|
|
1167
1173
|
UNIT_KILOMETER_PER_HOUR = "km/h"
|
1168
1174
|
UNIT_KILOVOLT_AMPS = "kVA"
|
1169
1175
|
UNIT_KILOVOLT_AMPS_HOURS = "kVAh"
|
1170
|
-
UNIT_KILOVOLT_AMPS_REACTIVE = "
|
1176
|
+
UNIT_KILOVOLT_AMPS_REACTIVE = "kvar"
|
1171
1177
|
UNIT_KILOVOLT_AMPS_REACTIVE_HOURS = "kvarh"
|
1172
1178
|
UNIT_KILOWATT = "kW"
|
1173
1179
|
UNIT_KILOWATT_HOURS = "kWh"
|
@@ -1268,6 +1274,7 @@ DEVICE_CLASS_PLUG = "plug"
|
|
1268
1274
|
DEVICE_CLASS_PM1 = "pm1"
|
1269
1275
|
DEVICE_CLASS_PM10 = "pm10"
|
1270
1276
|
DEVICE_CLASS_PM25 = "pm25"
|
1277
|
+
DEVICE_CLASS_PM4 = "pm4"
|
1271
1278
|
DEVICE_CLASS_POWER = "power"
|
1272
1279
|
DEVICE_CLASS_POWER_FACTOR = "power_factor"
|
1273
1280
|
DEVICE_CLASS_PRECIPITATION = "precipitation"
|
esphome/core/__init__.py
CHANGED
@@ -3,6 +3,7 @@ from contextlib import contextmanager
|
|
3
3
|
import logging
|
4
4
|
import math
|
5
5
|
import os
|
6
|
+
from pathlib import Path
|
6
7
|
import re
|
7
8
|
from typing import TYPE_CHECKING
|
8
9
|
|
@@ -39,6 +40,8 @@ from esphome.helpers import ensure_unique_string, get_str_env, is_ha_addon
|
|
39
40
|
from esphome.util import OrderedDict
|
40
41
|
|
41
42
|
if TYPE_CHECKING:
|
43
|
+
from esphome.address_cache import AddressCache
|
44
|
+
|
42
45
|
from ..cpp_generator import MockObj, MockObjClass, Statement
|
43
46
|
from ..types import ConfigType, EntityMetadata
|
44
47
|
|
@@ -381,7 +384,7 @@ class DocumentLocation:
|
|
381
384
|
|
382
385
|
@classmethod
|
383
386
|
def from_mark(cls, mark):
|
384
|
-
return cls(mark.name, mark.line, mark.column)
|
387
|
+
return cls(str(mark.name), mark.line, mark.column)
|
385
388
|
|
386
389
|
def __str__(self):
|
387
390
|
return f"{self.document} {self.line}:{self.column}"
|
@@ -536,9 +539,9 @@ class EsphomeCore:
|
|
536
539
|
# The first key to this dict should always be the integration name
|
537
540
|
self.data = {}
|
538
541
|
# The relative path to the configuration YAML
|
539
|
-
self.config_path:
|
542
|
+
self.config_path: Path | None = None
|
540
543
|
# The relative path to where all build files are stored
|
541
|
-
self.build_path:
|
544
|
+
self.build_path: Path | None = None
|
542
545
|
# The validated configuration, this is None until the config has been validated
|
543
546
|
self.config: ConfigType | None = None
|
544
547
|
# The pending tasks in the task queue (mostly for C++ generation)
|
@@ -583,6 +586,8 @@ class EsphomeCore:
|
|
583
586
|
self.id_classes = {}
|
584
587
|
# The current component being processed during validation
|
585
588
|
self.current_component: str | None = None
|
589
|
+
# Address cache for DNS and mDNS lookups from command line arguments
|
590
|
+
self.address_cache: AddressCache | None = None
|
586
591
|
|
587
592
|
def reset(self):
|
588
593
|
from esphome.pins import PIN_SCHEMA_REGISTRY
|
@@ -610,6 +615,7 @@ class EsphomeCore:
|
|
610
615
|
self.platform_counts = defaultdict(int)
|
611
616
|
self.unique_ids = {}
|
612
617
|
self.current_component = None
|
618
|
+
self.address_cache = None
|
613
619
|
PIN_SCHEMA_REGISTRY.reset()
|
614
620
|
|
615
621
|
@contextmanager
|
@@ -659,43 +665,46 @@ class EsphomeCore:
|
|
659
665
|
return None
|
660
666
|
|
661
667
|
@property
|
662
|
-
def config_dir(self):
|
663
|
-
|
668
|
+
def config_dir(self) -> Path:
|
669
|
+
if self.config_path.is_dir():
|
670
|
+
return self.config_path.absolute()
|
671
|
+
return self.config_path.absolute().parent
|
664
672
|
|
665
673
|
@property
|
666
|
-
def data_dir(self):
|
674
|
+
def data_dir(self) -> Path:
|
667
675
|
if is_ha_addon():
|
668
|
-
return
|
676
|
+
return Path("/data")
|
669
677
|
if "ESPHOME_DATA_DIR" in os.environ:
|
670
|
-
return get_str_env("ESPHOME_DATA_DIR", None)
|
678
|
+
return Path(get_str_env("ESPHOME_DATA_DIR", None))
|
671
679
|
return self.relative_config_path(".esphome")
|
672
680
|
|
673
681
|
@property
|
674
|
-
def config_filename(self):
|
675
|
-
return
|
682
|
+
def config_filename(self) -> str:
|
683
|
+
return self.config_path.name
|
676
684
|
|
677
|
-
def relative_config_path(self, *path):
|
678
|
-
path_ =
|
679
|
-
return
|
685
|
+
def relative_config_path(self, *path: str | Path) -> Path:
|
686
|
+
path_ = Path(*path).expanduser()
|
687
|
+
return self.config_dir / path_
|
680
688
|
|
681
|
-
def relative_internal_path(self, *path: str) ->
|
682
|
-
|
689
|
+
def relative_internal_path(self, *path: str | Path) -> Path:
|
690
|
+
path_ = Path(*path).expanduser()
|
691
|
+
return self.data_dir / path_
|
683
692
|
|
684
|
-
def relative_build_path(self, *path):
|
685
|
-
path_ =
|
686
|
-
return
|
693
|
+
def relative_build_path(self, *path: str | Path) -> Path:
|
694
|
+
path_ = Path(*path).expanduser()
|
695
|
+
return self.build_path / path_
|
687
696
|
|
688
|
-
def relative_src_path(self, *path):
|
697
|
+
def relative_src_path(self, *path: str | Path) -> Path:
|
689
698
|
return self.relative_build_path("src", *path)
|
690
699
|
|
691
|
-
def relative_pioenvs_path(self, *path):
|
700
|
+
def relative_pioenvs_path(self, *path: str | Path) -> Path:
|
692
701
|
return self.relative_build_path(".pioenvs", *path)
|
693
702
|
|
694
|
-
def relative_piolibdeps_path(self, *path):
|
703
|
+
def relative_piolibdeps_path(self, *path: str | Path) -> Path:
|
695
704
|
return self.relative_build_path(".piolibdeps", *path)
|
696
705
|
|
697
706
|
@property
|
698
|
-
def firmware_bin(self):
|
707
|
+
def firmware_bin(self) -> Path:
|
699
708
|
if self.is_libretiny:
|
700
709
|
return self.relative_pioenvs_path(self.name, "firmware.uf2")
|
701
710
|
return self.relative_pioenvs_path(self.name, "firmware.bin")
|
esphome/core/component.cpp
CHANGED
@@ -33,12 +33,22 @@ static const char *const TAG = "component";
|
|
33
33
|
// Using namespace-scope static to avoid guard variables (saves 16 bytes total)
|
34
34
|
// This is safe because ESPHome is single-threaded during initialization
|
35
35
|
namespace {
|
36
|
+
struct ComponentErrorMessage {
|
37
|
+
const Component *component;
|
38
|
+
const char *message;
|
39
|
+
};
|
40
|
+
|
41
|
+
struct ComponentPriorityOverride {
|
42
|
+
const Component *component;
|
43
|
+
float priority;
|
44
|
+
};
|
45
|
+
|
36
46
|
// Error messages for failed components
|
37
47
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
38
|
-
std::unique_ptr<std::vector<
|
48
|
+
std::unique_ptr<std::vector<ComponentErrorMessage>> component_error_messages;
|
39
49
|
// Setup priority overrides - freed after setup completes
|
40
50
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
41
|
-
std::unique_ptr<std::vector<
|
51
|
+
std::unique_ptr<std::vector<ComponentPriorityOverride>> setup_priority_overrides;
|
42
52
|
} // namespace
|
43
53
|
|
44
54
|
namespace setup_priority {
|
@@ -134,9 +144,9 @@ void Component::call_dump_config() {
|
|
134
144
|
// Look up error message from global vector
|
135
145
|
const char *error_msg = nullptr;
|
136
146
|
if (component_error_messages) {
|
137
|
-
for (const auto &
|
138
|
-
if (
|
139
|
-
error_msg =
|
147
|
+
for (const auto &entry : *component_error_messages) {
|
148
|
+
if (entry.component == this) {
|
149
|
+
error_msg = entry.message;
|
140
150
|
break;
|
141
151
|
}
|
142
152
|
}
|
@@ -306,17 +316,17 @@ void Component::status_set_error(const char *message) {
|
|
306
316
|
if (message != nullptr) {
|
307
317
|
// Lazy allocate the error messages vector if needed
|
308
318
|
if (!component_error_messages) {
|
309
|
-
component_error_messages = std::make_unique<std::vector<
|
319
|
+
component_error_messages = std::make_unique<std::vector<ComponentErrorMessage>>();
|
310
320
|
}
|
311
321
|
// Check if this component already has an error message
|
312
|
-
for (auto &
|
313
|
-
if (
|
314
|
-
|
322
|
+
for (auto &entry : *component_error_messages) {
|
323
|
+
if (entry.component == this) {
|
324
|
+
entry.message = message;
|
315
325
|
return;
|
316
326
|
}
|
317
327
|
}
|
318
328
|
// Add new error message
|
319
|
-
component_error_messages->emplace_back(this, message);
|
329
|
+
component_error_messages->emplace_back(ComponentErrorMessage{this, message});
|
320
330
|
}
|
321
331
|
}
|
322
332
|
void Component::status_clear_warning() {
|
@@ -356,9 +366,9 @@ float Component::get_actual_setup_priority() const {
|
|
356
366
|
// Check if there's an override in the global vector
|
357
367
|
if (setup_priority_overrides) {
|
358
368
|
// Linear search is fine for small n (typically < 5 overrides)
|
359
|
-
for (const auto &
|
360
|
-
if (
|
361
|
-
return
|
369
|
+
for (const auto &entry : *setup_priority_overrides) {
|
370
|
+
if (entry.component == this) {
|
371
|
+
return entry.priority;
|
362
372
|
}
|
363
373
|
}
|
364
374
|
}
|
@@ -367,21 +377,21 @@ float Component::get_actual_setup_priority() const {
|
|
367
377
|
void Component::set_setup_priority(float priority) {
|
368
378
|
// Lazy allocate the vector if needed
|
369
379
|
if (!setup_priority_overrides) {
|
370
|
-
setup_priority_overrides = std::make_unique<std::vector<
|
380
|
+
setup_priority_overrides = std::make_unique<std::vector<ComponentPriorityOverride>>();
|
371
381
|
// Reserve some space to avoid reallocations (most configs have < 10 overrides)
|
372
382
|
setup_priority_overrides->reserve(10);
|
373
383
|
}
|
374
384
|
|
375
385
|
// Check if this component already has an override
|
376
|
-
for (auto &
|
377
|
-
if (
|
378
|
-
|
386
|
+
for (auto &entry : *setup_priority_overrides) {
|
387
|
+
if (entry.component == this) {
|
388
|
+
entry.priority = priority;
|
379
389
|
return;
|
380
390
|
}
|
381
391
|
}
|
382
392
|
|
383
393
|
// Add new override
|
384
|
-
setup_priority_overrides->emplace_back(this, priority);
|
394
|
+
setup_priority_overrides->emplace_back(ComponentPriorityOverride{this, priority});
|
385
395
|
}
|
386
396
|
|
387
397
|
bool Component::has_overridden_loop() const {
|
@@ -168,8 +168,9 @@ class ComponentIterator {
|
|
168
168
|
UPDATE,
|
169
169
|
#endif
|
170
170
|
MAX,
|
171
|
-
}
|
171
|
+
};
|
172
172
|
uint16_t at_{0}; // Supports up to 65,535 entities per type
|
173
|
+
IteratorState state_{IteratorState::NONE};
|
173
174
|
bool include_internal_{false};
|
174
175
|
|
175
176
|
template<typename Container>
|
esphome/core/config.py
CHANGED
@@ -136,21 +136,21 @@ def validate_ids_and_references(config: ConfigType) -> ConfigType:
|
|
136
136
|
return config
|
137
137
|
|
138
138
|
|
139
|
-
def valid_include(value):
|
139
|
+
def valid_include(value: str) -> str:
|
140
140
|
# Look for "<...>" includes
|
141
141
|
if value.startswith("<") and value.endswith(">"):
|
142
142
|
return value
|
143
143
|
try:
|
144
|
-
return cv.directory(value)
|
144
|
+
return str(cv.directory(value))
|
145
145
|
except cv.Invalid:
|
146
146
|
pass
|
147
|
-
|
148
|
-
|
147
|
+
path = cv.file_(value)
|
148
|
+
ext = path.suffix
|
149
149
|
if ext not in VALID_INCLUDE_EXTS:
|
150
150
|
raise cv.Invalid(
|
151
151
|
f"Include has invalid file extension {ext} - valid extensions are {', '.join(VALID_INCLUDE_EXTS)}"
|
152
152
|
)
|
153
|
-
return
|
153
|
+
return str(path)
|
154
154
|
|
155
155
|
|
156
156
|
def valid_project_name(value: str):
|
@@ -311,9 +311,9 @@ def preload_core_config(config, result) -> str:
|
|
311
311
|
CORE.data[KEY_CORE] = {}
|
312
312
|
|
313
313
|
if CONF_BUILD_PATH not in conf:
|
314
|
-
build_path = get_str_env("ESPHOME_BUILD_PATH", "build")
|
315
|
-
conf[CONF_BUILD_PATH] =
|
316
|
-
CORE.build_path = CORE.
|
314
|
+
build_path = Path(get_str_env("ESPHOME_BUILD_PATH", "build"))
|
315
|
+
conf[CONF_BUILD_PATH] = str(build_path / CORE.name)
|
316
|
+
CORE.build_path = CORE.data_dir / conf[CONF_BUILD_PATH]
|
317
317
|
|
318
318
|
target_platforms = []
|
319
319
|
|
@@ -339,12 +339,12 @@ def preload_core_config(config, result) -> str:
|
|
339
339
|
return target_platforms[0]
|
340
340
|
|
341
341
|
|
342
|
-
def include_file(path, basename):
|
343
|
-
parts = basename.
|
342
|
+
def include_file(path: Path, basename: Path):
|
343
|
+
parts = basename.parts
|
344
344
|
dst = CORE.relative_src_path(*parts)
|
345
345
|
copy_file_if_changed(path, dst)
|
346
346
|
|
347
|
-
|
347
|
+
ext = path.suffix
|
348
348
|
if ext in [".h", ".hpp", ".tcc"]:
|
349
349
|
# Header, add include statement
|
350
350
|
cg.add_global(cg.RawStatement(f'#include "{basename}"'))
|
@@ -377,18 +377,18 @@ async def add_arduino_global_workaround():
|
|
377
377
|
|
378
378
|
|
379
379
|
@coroutine_with_priority(CoroPriority.FINAL)
|
380
|
-
async def add_includes(includes):
|
380
|
+
async def add_includes(includes: list[str]) -> None:
|
381
381
|
# Add includes at the very end, so that the included files can access global variables
|
382
382
|
for include in includes:
|
383
383
|
path = CORE.relative_config_path(include)
|
384
|
-
if
|
384
|
+
if path.is_dir():
|
385
385
|
# Directory, copy tree
|
386
386
|
for p in walk_files(path):
|
387
|
-
basename =
|
387
|
+
basename = p.relative_to(path.parent)
|
388
388
|
include_file(p, basename)
|
389
389
|
else:
|
390
390
|
# Copy file
|
391
|
-
basename =
|
391
|
+
basename = Path(path.name)
|
392
392
|
include_file(path, basename)
|
393
393
|
|
394
394
|
|
esphome/core/defines.h
CHANGED
@@ -48,6 +48,7 @@
|
|
48
48
|
#define USE_LIGHT
|
49
49
|
#define USE_LOCK
|
50
50
|
#define USE_LOGGER
|
51
|
+
#define USE_LOGGER_RUNTIME_TAG_LEVELS
|
51
52
|
#define USE_LVGL
|
52
53
|
#define USE_LVGL_ANIMIMG
|
53
54
|
#define USE_LVGL_ARC
|
@@ -82,6 +83,7 @@
|
|
82
83
|
#define USE_LVGL_TILEVIEW
|
83
84
|
#define USE_LVGL_TOUCHSCREEN
|
84
85
|
#define USE_MDNS
|
86
|
+
#define MDNS_SERVICE_COUNT 3
|
85
87
|
#define USE_MEDIA_PLAYER
|
86
88
|
#define USE_NEXTION_TFT_UPLOAD
|
87
89
|
#define USE_NUMBER
|
@@ -100,6 +102,7 @@
|
|
100
102
|
#define USE_UART_DEBUGGER
|
101
103
|
#define USE_UPDATE
|
102
104
|
#define USE_VALVE
|
105
|
+
#define USE_ZWAVE_PROXY
|
103
106
|
|
104
107
|
// Feature flags which do not work for zephyr
|
105
108
|
#ifndef USE_ZEPHYR
|
@@ -109,19 +112,26 @@
|
|
109
112
|
#define USE_API
|
110
113
|
#define USE_API_CLIENT_CONNECTED_TRIGGER
|
111
114
|
#define USE_API_CLIENT_DISCONNECTED_TRIGGER
|
115
|
+
#define USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
116
|
+
#define USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
112
117
|
#define USE_API_HOMEASSISTANT_SERVICES
|
113
118
|
#define USE_API_HOMEASSISTANT_STATES
|
114
119
|
#define USE_API_NOISE
|
115
120
|
#define USE_API_PLAINTEXT
|
116
121
|
#define USE_API_SERVICES
|
122
|
+
#define API_MAX_SEND_QUEUE 8
|
117
123
|
#define USE_MD5
|
124
|
+
#define USE_SHA256
|
118
125
|
#define USE_MQTT
|
119
126
|
#define USE_NETWORK
|
120
127
|
#define USE_ONLINE_IMAGE_BMP_SUPPORT
|
121
128
|
#define USE_ONLINE_IMAGE_PNG_SUPPORT
|
122
129
|
#define USE_ONLINE_IMAGE_JPEG_SUPPORT
|
123
130
|
#define USE_OTA
|
131
|
+
#define USE_OTA_MD5
|
124
132
|
#define USE_OTA_PASSWORD
|
133
|
+
#define USE_OTA_SHA256
|
134
|
+
#define ALLOW_OTA_DOWNGRADE_MD5
|
125
135
|
#define USE_OTA_STATE_CALLBACK
|
126
136
|
#define USE_OTA_VERSION 2
|
127
137
|
#define USE_TIME_TIMEZONE
|
@@ -151,11 +161,20 @@
|
|
151
161
|
#define BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE 16
|
152
162
|
#define USE_CAPTIVE_PORTAL
|
153
163
|
#define USE_ESP32_BLE
|
164
|
+
#define USE_ESP32_BLE_MAX_CONNECTIONS 3
|
154
165
|
#define USE_ESP32_BLE_CLIENT
|
155
166
|
#define USE_ESP32_BLE_DEVICE
|
156
167
|
#define USE_ESP32_BLE_SERVER
|
157
168
|
#define USE_ESP32_BLE_UUID
|
158
169
|
#define USE_ESP32_BLE_ADVERTISING
|
170
|
+
#define USE_ESP32_BLE_SERVER_SET_VALUE_ACTION
|
171
|
+
#define USE_ESP32_BLE_SERVER_DESCRIPTOR_SET_VALUE_ACTION
|
172
|
+
#define USE_ESP32_BLE_SERVER_NOTIFY_ACTION
|
173
|
+
#define USE_ESP32_BLE_SERVER_CHARACTERISTIC_ON_WRITE
|
174
|
+
#define USE_ESP32_BLE_SERVER_DESCRIPTOR_ON_WRITE
|
175
|
+
#define USE_ESP32_BLE_SERVER_ON_CONNECT
|
176
|
+
#define USE_ESP32_BLE_SERVER_ON_DISCONNECT
|
177
|
+
#define USE_ESP32_CAMERA_JPEG_ENCODER
|
159
178
|
#define USE_I2C
|
160
179
|
#define USE_IMPROV
|
161
180
|
#define USE_MICROPHONE
|
esphome/core/hash_base.h
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <cstdint>
|
4
|
+
#include <cstddef>
|
5
|
+
#include <cstring>
|
6
|
+
#include "esphome/core/helpers.h"
|
7
|
+
|
8
|
+
namespace esphome {
|
9
|
+
|
10
|
+
/// Base class for hash algorithms
|
11
|
+
class HashBase {
|
12
|
+
public:
|
13
|
+
virtual ~HashBase() = default;
|
14
|
+
|
15
|
+
/// Initialize a new hash computation
|
16
|
+
virtual void init() = 0;
|
17
|
+
|
18
|
+
/// Add bytes of data for the hash
|
19
|
+
virtual void add(const uint8_t *data, size_t len) = 0;
|
20
|
+
void add(const char *data, size_t len) { this->add((const uint8_t *) data, len); }
|
21
|
+
|
22
|
+
/// Compute the hash based on provided data
|
23
|
+
virtual void calculate() = 0;
|
24
|
+
|
25
|
+
/// Retrieve the hash as bytes
|
26
|
+
void get_bytes(uint8_t *output) { memcpy(output, this->digest_, this->get_size()); }
|
27
|
+
|
28
|
+
/// Retrieve the hash as hex characters
|
29
|
+
void get_hex(char *output) {
|
30
|
+
for (size_t i = 0; i < this->get_size(); i++) {
|
31
|
+
uint8_t byte = this->digest_[i];
|
32
|
+
output[i * 2] = format_hex_char(byte >> 4);
|
33
|
+
output[i * 2 + 1] = format_hex_char(byte & 0x0F);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
/// Compare the hash against a provided byte-encoded hash
|
38
|
+
bool equals_bytes(const uint8_t *expected) { return memcmp(this->digest_, expected, this->get_size()) == 0; }
|
39
|
+
|
40
|
+
/// Compare the hash against a provided hex-encoded hash
|
41
|
+
bool equals_hex(const char *expected) {
|
42
|
+
uint8_t parsed[32]; // Fixed size for max hash (SHA256 = 32 bytes)
|
43
|
+
if (!parse_hex(expected, parsed, this->get_size())) {
|
44
|
+
return false;
|
45
|
+
}
|
46
|
+
return this->equals_bytes(parsed);
|
47
|
+
}
|
48
|
+
|
49
|
+
/// Get the size of the hash in bytes (16 for MD5, 32 for SHA256)
|
50
|
+
virtual size_t get_size() const = 0;
|
51
|
+
|
52
|
+
protected:
|
53
|
+
uint8_t digest_[32]; // Storage sized for max(MD5=16, SHA256=32) bytes
|
54
|
+
};
|
55
|
+
|
56
|
+
} // namespace esphome
|
esphome/core/helpers.cpp
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
#include "esphome/core/defines.h"
|
4
4
|
#include "esphome/core/hal.h"
|
5
5
|
#include "esphome/core/log.h"
|
6
|
+
#include "esphome/core/string_ref.h"
|
6
7
|
|
7
8
|
#include <strings.h>
|
8
9
|
#include <algorithm>
|
@@ -348,17 +349,34 @@ ParseOnOffState parse_on_off(const char *str, const char *on, const char *off) {
|
|
348
349
|
return PARSE_NONE;
|
349
350
|
}
|
350
351
|
|
351
|
-
|
352
|
+
static inline void normalize_accuracy_decimals(float &value, int8_t &accuracy_decimals) {
|
352
353
|
if (accuracy_decimals < 0) {
|
353
354
|
auto multiplier = powf(10.0f, accuracy_decimals);
|
354
355
|
value = roundf(value * multiplier) / multiplier;
|
355
356
|
accuracy_decimals = 0;
|
356
357
|
}
|
358
|
+
}
|
359
|
+
|
360
|
+
std::string value_accuracy_to_string(float value, int8_t accuracy_decimals) {
|
361
|
+
normalize_accuracy_decimals(value, accuracy_decimals);
|
357
362
|
char tmp[32]; // should be enough, but we should maybe improve this at some point.
|
358
363
|
snprintf(tmp, sizeof(tmp), "%.*f", accuracy_decimals, value);
|
359
364
|
return std::string(tmp);
|
360
365
|
}
|
361
366
|
|
367
|
+
std::string value_accuracy_with_uom_to_string(float value, int8_t accuracy_decimals, StringRef unit_of_measurement) {
|
368
|
+
normalize_accuracy_decimals(value, accuracy_decimals);
|
369
|
+
// Buffer sized for float (up to ~15 chars) + space + typical UOM (usually <20 chars like "μS/cm")
|
370
|
+
// snprintf truncates safely if exceeded, though ESPHome UOMs are typically short
|
371
|
+
char tmp[64];
|
372
|
+
if (unit_of_measurement.empty()) {
|
373
|
+
snprintf(tmp, sizeof(tmp), "%.*f", accuracy_decimals, value);
|
374
|
+
} else {
|
375
|
+
snprintf(tmp, sizeof(tmp), "%.*f %s", accuracy_decimals, value, unit_of_measurement.c_str());
|
376
|
+
}
|
377
|
+
return std::string(tmp);
|
378
|
+
}
|
379
|
+
|
362
380
|
int8_t step_to_accuracy_decimals(float step) {
|
363
381
|
// use printf %g to find number of digits based on temperature step
|
364
382
|
char buf[32];
|
@@ -613,8 +631,6 @@ bool mac_address_is_valid(const uint8_t *mac) {
|
|
613
631
|
if (mac[i] != 0) {
|
614
632
|
is_all_zeros = false;
|
615
633
|
}
|
616
|
-
}
|
617
|
-
for (uint8_t i = 0; i < 6; i++) {
|
618
634
|
if (mac[i] != 0xFF) {
|
619
635
|
is_all_ones = false;
|
620
636
|
}
|
esphome/core/helpers.h
CHANGED
@@ -45,6 +45,9 @@
|
|
45
45
|
|
46
46
|
namespace esphome {
|
47
47
|
|
48
|
+
// Forward declaration to avoid circular dependency with string_ref.h
|
49
|
+
class StringRef;
|
50
|
+
|
48
51
|
/// @name STL backports
|
49
52
|
///@{
|
50
53
|
|
@@ -82,6 +85,16 @@ template<typename T> constexpr T byteswap(T n) {
|
|
82
85
|
return m;
|
83
86
|
}
|
84
87
|
template<> constexpr uint8_t byteswap(uint8_t n) { return n; }
|
88
|
+
#ifdef USE_LIBRETINY
|
89
|
+
// LibreTiny's Beken framework redefines __builtin_bswap functions as non-constexpr
|
90
|
+
template<> inline uint16_t byteswap(uint16_t n) { return __builtin_bswap16(n); }
|
91
|
+
template<> inline uint32_t byteswap(uint32_t n) { return __builtin_bswap32(n); }
|
92
|
+
template<> inline uint64_t byteswap(uint64_t n) { return __builtin_bswap64(n); }
|
93
|
+
template<> inline int8_t byteswap(int8_t n) { return n; }
|
94
|
+
template<> inline int16_t byteswap(int16_t n) { return __builtin_bswap16(n); }
|
95
|
+
template<> inline int32_t byteswap(int32_t n) { return __builtin_bswap32(n); }
|
96
|
+
template<> inline int64_t byteswap(int64_t n) { return __builtin_bswap64(n); }
|
97
|
+
#else
|
85
98
|
template<> constexpr uint16_t byteswap(uint16_t n) { return __builtin_bswap16(n); }
|
86
99
|
template<> constexpr uint32_t byteswap(uint32_t n) { return __builtin_bswap32(n); }
|
87
100
|
template<> constexpr uint64_t byteswap(uint64_t n) { return __builtin_bswap64(n); }
|
@@ -89,6 +102,7 @@ template<> constexpr int8_t byteswap(int8_t n) { return n; }
|
|
89
102
|
template<> constexpr int16_t byteswap(int16_t n) { return __builtin_bswap16(n); }
|
90
103
|
template<> constexpr int32_t byteswap(int32_t n) { return __builtin_bswap32(n); }
|
91
104
|
template<> constexpr int64_t byteswap(int64_t n) { return __builtin_bswap64(n); }
|
105
|
+
#endif
|
92
106
|
|
93
107
|
///@}
|
94
108
|
|
@@ -116,6 +130,16 @@ template<typename T, size_t N> class StaticVector {
|
|
116
130
|
}
|
117
131
|
}
|
118
132
|
|
133
|
+
// Return reference to next element and increment count (with bounds checking)
|
134
|
+
T &emplace_next() {
|
135
|
+
if (count_ >= N) {
|
136
|
+
// Should never happen with proper size calculation
|
137
|
+
// Return reference to last element to avoid crash
|
138
|
+
return data_[N - 1];
|
139
|
+
}
|
140
|
+
return data_[count_++];
|
141
|
+
}
|
142
|
+
|
119
143
|
size_t size() const { return count_; }
|
120
144
|
bool empty() const { return count_ == 0; }
|
121
145
|
|
@@ -589,6 +613,8 @@ ParseOnOffState parse_on_off(const char *str, const char *on = nullptr, const ch
|
|
589
613
|
|
590
614
|
/// Create a string from a value and an accuracy in decimals.
|
591
615
|
std::string value_accuracy_to_string(float value, int8_t accuracy_decimals);
|
616
|
+
/// Create a string from a value, an accuracy in decimals, and a unit of measurement.
|
617
|
+
std::string value_accuracy_with_uom_to_string(float value, int8_t accuracy_decimals, StringRef unit_of_measurement);
|
592
618
|
|
593
619
|
/// Derive accuracy in decimals from an increment step.
|
594
620
|
int8_t step_to_accuracy_decimals(float step);
|