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.
Files changed (343) hide show
  1. esphome/__main__.py +87 -31
  2. esphome/address_cache.py +142 -0
  3. esphome/automation.py +130 -32
  4. esphome/build_gen/platformio.py +1 -3
  5. esphome/codegen.py +1 -0
  6. esphome/components/animation/animation.cpp +2 -2
  7. esphome/components/api/__init__.py +166 -3
  8. esphome/components/api/api_connection.cpp +84 -41
  9. esphome/components/api/api_connection.h +22 -16
  10. esphome/components/api/api_frame_helper.cpp +33 -19
  11. esphome/components/api/api_frame_helper.h +19 -4
  12. esphome/components/api/api_frame_helper_noise.cpp +41 -53
  13. esphome/components/api/api_frame_helper_noise.h +1 -1
  14. esphome/components/api/api_frame_helper_plaintext.cpp +22 -31
  15. esphome/components/api/api_frame_helper_plaintext.h +1 -1
  16. esphome/components/api/api_pb2.cpp +189 -15
  17. esphome/components/api/api_pb2.h +132 -20
  18. esphome/components/api/api_pb2_dump.cpp +97 -9
  19. esphome/components/api/api_pb2_service.cpp +118 -160
  20. esphome/components/api/api_pb2_service.h +31 -3
  21. esphome/components/api/api_server.cpp +68 -10
  22. esphome/components/api/api_server.h +32 -4
  23. esphome/components/api/custom_api_device.h +8 -8
  24. esphome/components/api/homeassistant_service.h +123 -6
  25. esphome/components/api/proto.h +6 -2
  26. esphome/components/api/user_services.h +2 -2
  27. esphome/components/as7341/sensor.py +1 -1
  28. esphome/components/audio/__init__.py +1 -1
  29. esphome/components/audio/audio.cpp +1 -1
  30. esphome/components/audio/audio_decoder.cpp +9 -9
  31. esphome/components/bl0906/bl0906.cpp +2 -2
  32. esphome/components/bl0942/bl0942.cpp +2 -2
  33. esphome/components/ble_client/__init__.py +1 -1
  34. esphome/components/bluetooth_proxy/__init__.py +4 -30
  35. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +11 -4
  36. esphome/components/bluetooth_proxy/bluetooth_connection.h +2 -2
  37. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +2 -2
  38. esphome/components/camera_encoder/__init__.py +2 -4
  39. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +4 -2
  40. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +3 -1
  41. esphome/components/canbus/canbus.cpp +7 -5
  42. esphome/components/canbus/canbus.h +4 -4
  43. esphome/components/captive_portal/__init__.py +18 -1
  44. esphome/components/captive_portal/captive_portal.cpp +40 -46
  45. esphome/components/captive_portal/captive_portal.h +20 -22
  46. esphome/components/captive_portal/dns_server_esp32_idf.cpp +205 -0
  47. esphome/components/captive_portal/dns_server_esp32_idf.h +27 -0
  48. esphome/components/ccs811/ccs811.cpp +1 -1
  49. esphome/components/climate/climate.cpp +10 -7
  50. esphome/components/cm1106/cm1106.cpp +1 -1
  51. esphome/components/copy/lock/copy_lock.cpp +1 -1
  52. esphome/components/cover/cover.cpp +1 -0
  53. esphome/components/daikin_arc/daikin_arc.cpp +19 -12
  54. esphome/components/deep_sleep/__init__.py +9 -2
  55. esphome/components/deep_sleep/deep_sleep_component.h +11 -9
  56. esphome/components/deep_sleep/deep_sleep_esp32.cpp +51 -27
  57. esphome/components/ektf2232/touchscreen/__init__.py +8 -5
  58. esphome/components/ektf2232/touchscreen/ektf2232.cpp +4 -4
  59. esphome/components/ektf2232/touchscreen/ektf2232.h +2 -2
  60. esphome/components/epaper_spi/__init__.py +1 -0
  61. esphome/components/epaper_spi/display.py +80 -0
  62. esphome/components/epaper_spi/epaper_spi.cpp +227 -0
  63. esphome/components/epaper_spi/epaper_spi.h +93 -0
  64. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.cpp +42 -0
  65. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.h +45 -0
  66. esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +135 -0
  67. esphome/components/epaper_spi/epaper_spi_spectra_e6.h +23 -0
  68. esphome/components/es7210/es7210.cpp +3 -3
  69. esphome/components/esp32/__init__.py +254 -339
  70. esphome/components/esp32/boards.py +81 -0
  71. esphome/components/esp32/preferences.cpp +23 -17
  72. esphome/components/esp32_ble/__init__.py +159 -44
  73. esphome/components/esp32_ble/ble.cpp +47 -3
  74. esphome/components/esp32_ble/ble.h +18 -0
  75. esphome/components/esp32_ble/ble_advertising.cpp +7 -3
  76. esphome/components/esp32_ble/ble_advertising.h +4 -0
  77. esphome/components/esp32_ble/ble_uuid.cpp +16 -42
  78. esphome/components/esp32_ble_beacon/__init__.py +3 -4
  79. esphome/components/esp32_ble_client/ble_client_base.cpp +14 -12
  80. esphome/components/esp32_ble_server/__init__.py +28 -14
  81. esphome/components/esp32_ble_server/ble_characteristic.cpp +67 -57
  82. esphome/components/esp32_ble_server/ble_characteristic.h +27 -16
  83. esphome/components/esp32_ble_server/ble_descriptor.cpp +4 -3
  84. esphome/components/esp32_ble_server/ble_descriptor.h +13 -9
  85. esphome/components/esp32_ble_server/ble_server.cpp +59 -24
  86. esphome/components/esp32_ble_server/ble_server.h +38 -20
  87. esphome/components/esp32_ble_server/ble_server_automations.cpp +49 -33
  88. esphome/components/esp32_ble_server/ble_server_automations.h +39 -24
  89. esphome/components/esp32_ble_tracker/__init__.py +25 -80
  90. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -4
  91. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +0 -3
  92. esphome/components/esp32_camera/__init__.py +1 -3
  93. esphome/components/esp32_can/esp32_can.cpp +22 -4
  94. esphome/components/esp32_can/esp32_can.h +3 -0
  95. esphome/components/esp32_hosted/__init__.py +2 -1
  96. esphome/components/esp32_improv/esp32_improv_component.cpp +102 -44
  97. esphome/components/esp32_improv/esp32_improv_component.h +6 -1
  98. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  99. esphome/components/esp8266/__init__.py +3 -3
  100. esphome/components/esphome/ota/__init__.py +21 -2
  101. esphome/components/esphome/ota/ota_esphome.cpp +455 -145
  102. esphome/components/esphome/ota/ota_esphome.h +49 -2
  103. esphome/components/ethernet/__init__.py +39 -22
  104. esphome/components/ethernet/ethernet_component.cpp +28 -5
  105. esphome/components/ethernet/ethernet_component.h +5 -1
  106. esphome/components/external_components/__init__.py +8 -6
  107. esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
  108. esphome/components/fingerprint_grow/fingerprint_grow.h +2 -1
  109. esphome/components/font/__init__.py +5 -5
  110. esphome/components/graph/graph.cpp +1 -1
  111. esphome/components/graphical_display_menu/graphical_display_menu.cpp +3 -2
  112. esphome/components/haier/hon_climate.cpp +2 -2
  113. esphome/components/haier/hon_climate.h +1 -1
  114. esphome/components/hdc1080/hdc1080.cpp +42 -34
  115. esphome/components/hdc1080/hdc1080.h +1 -3
  116. esphome/components/homeassistant/number/homeassistant_number.cpp +2 -2
  117. esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
  118. esphome/components/http_request/__init__.py +3 -3
  119. esphome/components/htu21d/htu21d.cpp +13 -18
  120. esphome/components/htu21d/htu21d.h +1 -1
  121. esphome/components/i2s_audio/__init__.py +1 -2
  122. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  123. esphome/components/ili9xxx/ili9xxx_display.cpp +2 -2
  124. esphome/components/improv_serial/improv_serial_component.cpp +12 -15
  125. esphome/components/improv_serial/improv_serial_component.h +6 -8
  126. esphome/components/json/json_util.cpp +35 -43
  127. esphome/components/json/json_util.h +57 -0
  128. esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +2 -2
  129. esphome/components/key_collector/key_collector.h +4 -4
  130. esphome/components/libretiny/__init__.py +6 -6
  131. esphome/components/libretiny/preferences.cpp +23 -16
  132. esphome/components/light/light_call.cpp +98 -120
  133. esphome/components/light/light_call.h +17 -7
  134. esphome/components/lm75b/__init__.py +0 -0
  135. esphome/components/lm75b/lm75b.cpp +39 -0
  136. esphome/components/lm75b/lm75b.h +19 -0
  137. esphome/components/lm75b/sensor.py +34 -0
  138. esphome/components/lock/lock.h +12 -6
  139. esphome/components/logger/__init__.py +15 -27
  140. esphome/components/logger/logger.cpp +10 -20
  141. esphome/components/logger/logger.h +105 -62
  142. esphome/components/logger/logger_esp32.cpp +0 -48
  143. esphome/components/logger/logger_zephyr.cpp +2 -3
  144. esphome/components/logger/select/logger_level_select.cpp +6 -7
  145. esphome/components/logger/select/logger_level_select.h +7 -0
  146. esphome/components/ltr501/ltr501.cpp +7 -6
  147. esphome/components/ltr_als_ps/ltr_als_ps.cpp +7 -6
  148. esphome/components/matrix_keypad/matrix_keypad.h +4 -4
  149. esphome/components/max7219digit/max7219digit.cpp +1 -1
  150. esphome/components/mcp2515/mcp2515.cpp +31 -3
  151. esphome/components/mcp2515/mcp2515_defs.h +3 -1
  152. esphome/components/md5/md5.cpp +0 -26
  153. esphome/components/md5/md5.h +10 -20
  154. esphome/components/mdns/__init__.py +19 -6
  155. esphome/components/mdns/mdns_component.cpp +27 -59
  156. esphome/components/mdns/mdns_component.h +23 -10
  157. esphome/components/mdns/mdns_esp32.cpp +7 -7
  158. esphome/components/mdns/mdns_esp8266.cpp +6 -6
  159. esphome/components/mdns/mdns_libretiny.cpp +3 -3
  160. esphome/components/mdns/mdns_rp2040.cpp +3 -3
  161. esphome/components/mipi/__init__.py +1 -5
  162. esphome/components/mipi_spi/display.py +24 -8
  163. esphome/components/mipi_spi/mipi_spi.h +3 -3
  164. esphome/components/mixer/speaker/mixer_speaker.cpp +3 -3
  165. esphome/components/mmc5603/mmc5603.cpp +3 -3
  166. esphome/components/modbus/modbus.cpp +27 -13
  167. esphome/components/modbus/modbus.h +5 -3
  168. esphome/components/modbus/modbus_definitions.h +86 -0
  169. esphome/components/modbus_controller/__init__.py +29 -1
  170. esphome/components/modbus_controller/const.py +4 -0
  171. esphome/components/modbus_controller/modbus_controller.cpp +38 -13
  172. esphome/components/modbus_controller/modbus_controller.h +18 -29
  173. esphome/components/mpr121/mpr121.cpp +41 -42
  174. esphome/components/mpr121/mpr121.h +0 -1
  175. esphome/components/nau7802/nau7802.cpp +2 -2
  176. esphome/components/network/__init__.py +7 -3
  177. esphome/components/nextion/display.py +4 -4
  178. esphome/components/nextion/nextion.cpp +8 -8
  179. esphome/components/number/__init__.py +2 -0
  180. esphome/components/number/number_call.cpp +23 -12
  181. esphome/components/number/number_call.h +5 -0
  182. esphome/components/online_image/bmp_image.cpp +2 -1
  183. esphome/components/online_image/jpeg_image.cpp +4 -2
  184. esphome/components/openthread/openthread.cpp +6 -7
  185. esphome/components/openthread/openthread.h +0 -1
  186. esphome/components/ota/ota_backend.h +1 -0
  187. esphome/components/packages/__init__.py +10 -8
  188. esphome/components/packet_transport/packet_transport.cpp +2 -0
  189. esphome/components/pid/pid_controller.cpp +1 -1
  190. esphome/components/prometheus/prometheus_handler.cpp +239 -239
  191. esphome/components/psram/__init__.py +30 -28
  192. esphome/components/qmc5883l/qmc5883l.cpp +15 -0
  193. esphome/components/qmc5883l/qmc5883l.h +3 -0
  194. esphome/components/qmc5883l/sensor.py +31 -12
  195. esphome/components/remote_base/gobox_protocol.cpp +3 -3
  196. esphome/components/remote_receiver/__init__.py +14 -2
  197. esphome/components/remote_receiver/{remote_receiver_esp8266.cpp → remote_receiver.cpp} +2 -2
  198. esphome/components/remote_receiver/remote_receiver.h +4 -0
  199. esphome/components/remote_receiver/remote_receiver_esp32.cpp +18 -1
  200. esphome/components/remote_transmitter/__init__.py +2 -2
  201. esphome/components/remote_transmitter/remote_transmitter.cpp +103 -0
  202. esphome/components/rp2040/__init__.py +11 -11
  203. esphome/components/rtttl/rtttl.cpp +2 -2
  204. esphome/components/scd30/sensor.py +1 -1
  205. esphome/components/script/__init__.py +1 -1
  206. esphome/components/script/script.h +7 -7
  207. esphome/components/select/select.cpp +5 -4
  208. esphome/components/select/select_call.cpp +1 -1
  209. esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
  210. esphome/components/sensor/__init__.py +2 -0
  211. esphome/components/sha256/__init__.py +22 -0
  212. esphome/components/sha256/sha256.cpp +116 -0
  213. esphome/components/sha256/sha256.h +60 -0
  214. esphome/components/socket/lwip_raw_tcp_impl.cpp +34 -6
  215. esphome/components/sonoff_d1/sonoff_d1.cpp +1 -1
  216. esphome/components/spi/__init__.py +0 -3
  217. esphome/components/split_buffer/__init__.py +5 -0
  218. esphome/components/split_buffer/split_buffer.cpp +133 -0
  219. esphome/components/split_buffer/split_buffer.h +40 -0
  220. esphome/components/sps30/sps30.cpp +14 -10
  221. esphome/components/sps30/sps30.h +2 -0
  222. esphome/components/st7567_i2c/st7567_i2c.cpp +3 -1
  223. esphome/components/st7789v/st7789v.cpp +3 -2
  224. esphome/components/statsd/statsd.cpp +1 -1
  225. esphome/components/substitutions/__init__.py +3 -1
  226. esphome/components/substitutions/jinja.py +13 -3
  227. esphome/components/sx126x/__init__.py +16 -0
  228. esphome/components/sx126x/sx126x.cpp +15 -1
  229. esphome/components/sx126x/sx126x.h +9 -1
  230. esphome/components/sx126x/sx126x_reg.h +2 -0
  231. esphome/components/text_sensor/text_sensor.cpp +16 -0
  232. esphome/components/text_sensor/text_sensor.h +3 -10
  233. esphome/components/tormatic/tormatic_cover.cpp +1 -1
  234. esphome/components/tuya/select/tuya_select.cpp +1 -1
  235. esphome/components/tuya/tuya.cpp +29 -4
  236. esphome/components/uart/__init__.py +36 -26
  237. esphome/components/uart/uart.h +6 -0
  238. esphome/components/uart/uart_component.cpp +8 -0
  239. esphome/components/uart/uart_component.h +28 -0
  240. esphome/components/uart/uart_component_esp_idf.cpp +64 -10
  241. esphome/components/uart/uart_component_esp_idf.h +5 -2
  242. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
  243. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +1 -1
  244. esphome/components/uponor_smatrix/uponor_smatrix.cpp +3 -3
  245. esphome/components/usb_host/__init__.py +2 -1
  246. esphome/components/usb_host/usb_host.h +82 -13
  247. esphome/components/usb_host/usb_host_client.cpp +180 -24
  248. esphome/components/usb_host/usb_host_component.cpp +1 -1
  249. esphome/components/usb_uart/__init__.py +0 -1
  250. esphome/components/usb_uart/ch34x.cpp +4 -4
  251. esphome/components/usb_uart/cp210x.cpp +3 -3
  252. esphome/components/usb_uart/usb_uart.cpp +88 -32
  253. esphome/components/usb_uart/usb_uart.h +30 -6
  254. esphome/components/valve/valve.cpp +1 -0
  255. esphome/components/veml7700/veml7700.cpp +7 -6
  256. esphome/components/version/version_text_sensor.cpp +2 -1
  257. esphome/components/voice_assistant/voice_assistant.cpp +3 -2
  258. esphome/components/waveshare_epaper/waveshare_epaper.cpp +4 -4
  259. esphome/components/web_server/list_entities.cpp +3 -4
  260. esphome/components/web_server/list_entities.h +8 -10
  261. esphome/components/web_server/ota/__init__.py +1 -1
  262. esphome/components/web_server/ota/ota_web_server.cpp +9 -3
  263. esphome/components/web_server/web_server.cpp +509 -404
  264. esphome/components/web_server/web_server.h +5 -6
  265. esphome/components/web_server/web_server_v1.cpp +21 -19
  266. esphome/components/web_server_base/__init__.py +5 -2
  267. esphome/components/web_server_base/web_server_base.h +27 -7
  268. esphome/components/web_server_idf/__init__.py +1 -1
  269. esphome/components/web_server_idf/multipart.cpp +2 -2
  270. esphome/components/web_server_idf/multipart.h +2 -2
  271. esphome/components/web_server_idf/utils.cpp +2 -2
  272. esphome/components/web_server_idf/utils.h +2 -2
  273. esphome/components/web_server_idf/web_server_idf.cpp +118 -26
  274. esphome/components/web_server_idf/web_server_idf.h +12 -10
  275. esphome/components/wifi/__init__.py +13 -11
  276. esphome/components/wifi/wifi_component.cpp +73 -56
  277. esphome/components/wifi/wifi_component.h +4 -4
  278. esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
  279. esphome/components/wifi/wifi_component_esp_idf.cpp +24 -4
  280. esphome/components/wireguard/__init__.py +1 -1
  281. esphome/components/wts01/__init__.py +0 -0
  282. esphome/components/wts01/sensor.py +41 -0
  283. esphome/components/wts01/wts01.cpp +91 -0
  284. esphome/components/wts01/wts01.h +27 -0
  285. esphome/components/zephyr/__init__.py +5 -5
  286. esphome/components/zwave_proxy/__init__.py +43 -0
  287. esphome/components/zwave_proxy/zwave_proxy.cpp +346 -0
  288. esphome/components/zwave_proxy/zwave_proxy.h +93 -0
  289. esphome/config.py +79 -24
  290. esphome/config_validation.py +13 -15
  291. esphome/const.py +9 -2
  292. esphome/core/__init__.py +31 -22
  293. esphome/core/component.cpp +28 -18
  294. esphome/core/component_iterator.h +2 -1
  295. esphome/core/config.py +15 -15
  296. esphome/core/defines.h +19 -0
  297. esphome/core/hash_base.h +56 -0
  298. esphome/core/helpers.cpp +19 -3
  299. esphome/core/helpers.h +26 -0
  300. esphome/core/scheduler.cpp +5 -21
  301. esphome/core/scheduler.h +19 -8
  302. esphome/core/string_ref.h +1 -1
  303. esphome/core/time.cpp +5 -5
  304. esphome/cpp_generator.py +4 -29
  305. esphome/dashboard/const.py +21 -4
  306. esphome/dashboard/core.py +10 -8
  307. esphome/dashboard/dns.py +15 -0
  308. esphome/dashboard/entries.py +15 -21
  309. esphome/dashboard/models.py +76 -0
  310. esphome/dashboard/settings.py +7 -7
  311. esphome/dashboard/status/mdns.py +46 -2
  312. esphome/dashboard/web_server.py +367 -93
  313. esphome/espota2.py +111 -31
  314. esphome/external_files.py +6 -7
  315. esphome/git.py +8 -0
  316. esphome/helpers.py +124 -77
  317. esphome/loader.py +8 -9
  318. esphome/platformio_api.py +25 -18
  319. esphome/storage_json.py +26 -21
  320. esphome/types.py +30 -2
  321. esphome/util.py +32 -16
  322. esphome/vscode.py +8 -8
  323. esphome/wizard.py +10 -10
  324. esphome/writer.py +50 -15
  325. esphome/yaml_util.py +37 -31
  326. esphome/zeroconf.py +12 -3
  327. {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/METADATA +11 -11
  328. {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/RECORD +332 -312
  329. esphome/components/event_emitter/__init__.py +0 -5
  330. esphome/components/event_emitter/event_emitter.cpp +0 -14
  331. esphome/components/event_emitter/event_emitter.h +0 -63
  332. esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -125
  333. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +0 -107
  334. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +0 -110
  335. esphome/components/uart/uart_component_esp32_arduino.cpp +0 -214
  336. esphome/components/uart/uart_component_esp32_arduino.h +0 -60
  337. esphome/components/wifi/wifi_component_esp32_arduino.cpp +0 -860
  338. esphome/core/string_ref.cpp +0 -12
  339. esphome/dashboard/util/file.py +0 -63
  340. {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/WHEEL +0 -0
  341. {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/entry_points.txt +0 -0
  342. {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/licenses/LICENSE +0 -0
  343. {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,8 @@
1
1
  #include "wifi_component.h"
2
2
  #ifdef USE_WIFI
3
3
  #include <cinttypes>
4
- #include <map>
5
4
 
6
- #ifdef USE_ESP_IDF
5
+ #ifdef USE_ESP32
7
6
  #if (ESP_IDF_VERSION_MAJOR >= 5 && ESP_IDF_VERSION_MINOR >= 1)
8
7
  #include <esp_eap_client.h>
9
8
  #else
@@ -11,7 +10,7 @@
11
10
  #endif
12
11
  #endif
13
12
 
14
- #if defined(USE_ESP32) || defined(USE_ESP_IDF)
13
+ #if defined(USE_ESP32)
15
14
  #include <esp_wifi.h>
16
15
  #endif
17
16
  #ifdef USE_ESP8266
@@ -42,6 +41,25 @@ namespace wifi {
42
41
 
43
42
  static const char *const TAG = "wifi";
44
43
 
44
+ #if defined(USE_ESP32) && defined(USE_WIFI_WPA2_EAP) && ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
45
+ static const char *eap_phase2_to_str(esp_eap_ttls_phase2_types type) {
46
+ switch (type) {
47
+ case ESP_EAP_TTLS_PHASE2_PAP:
48
+ return "pap";
49
+ case ESP_EAP_TTLS_PHASE2_CHAP:
50
+ return "chap";
51
+ case ESP_EAP_TTLS_PHASE2_MSCHAP:
52
+ return "mschap";
53
+ case ESP_EAP_TTLS_PHASE2_MSCHAPV2:
54
+ return "mschapv2";
55
+ case ESP_EAP_TTLS_PHASE2_EAP:
56
+ return "eap";
57
+ default:
58
+ return "unknown";
59
+ }
60
+ }
61
+ #endif
62
+
45
63
  float WiFiComponent::get_setup_priority() const { return setup_priority::WIFI; }
46
64
 
47
65
  void WiFiComponent::setup() {
@@ -266,30 +284,34 @@ void WiFiComponent::setup_ap_config_() {
266
284
  std::string name = App.get_name();
267
285
  if (name.length() > 32) {
268
286
  if (App.is_name_add_mac_suffix_enabled()) {
269
- name.erase(name.begin() + 25, name.end() - 7); // Remove characters between 25 and the mac address
287
+ // Keep first 25 chars and last 7 chars (MAC suffix), remove middle
288
+ name.erase(25, name.length() - 32);
270
289
  } else {
271
- name = name.substr(0, 32);
290
+ name.resize(32);
272
291
  }
273
292
  }
274
293
  this->ap_.set_ssid(name);
275
294
  }
295
+ this->ap_setup_ = this->wifi_start_ap_(this->ap_);
296
+
297
+ auto ip_address = this->wifi_soft_ap_ip().str();
276
298
  ESP_LOGCONFIG(TAG,
277
299
  "Setting up AP:\n"
278
300
  " AP SSID: '%s'\n"
279
- " AP Password: '%s'",
280
- this->ap_.get_ssid().c_str(), this->ap_.get_password().c_str());
281
- if (this->ap_.get_manual_ip().has_value()) {
282
- auto manual = *this->ap_.get_manual_ip();
301
+ " AP Password: '%s'\n"
302
+ " IP Address: %s",
303
+ this->ap_.get_ssid().c_str(), this->ap_.get_password().c_str(), ip_address.c_str());
304
+
305
+ auto manual_ip = this->ap_.get_manual_ip();
306
+ if (manual_ip.has_value()) {
283
307
  ESP_LOGCONFIG(TAG,
284
308
  " AP Static IP: '%s'\n"
285
309
  " AP Gateway: '%s'\n"
286
310
  " AP Subnet: '%s'",
287
- manual.static_ip.str().c_str(), manual.gateway.str().c_str(), manual.subnet.str().c_str());
311
+ manual_ip->static_ip.str().c_str(), manual_ip->gateway.str().c_str(),
312
+ manual_ip->subnet.str().c_str());
288
313
  }
289
314
 
290
- this->ap_setup_ = this->wifi_start_ap_(this->ap_);
291
- ESP_LOGCONFIG(TAG, " IP Address: %s", this->wifi_soft_ap_ip().str().c_str());
292
-
293
315
  if (!this->has_sta()) {
294
316
  this->state_ = WIFI_COMPONENT_STATE_AP;
295
317
  }
@@ -312,9 +334,9 @@ void WiFiComponent::set_sta(const WiFiAP &ap) {
312
334
  }
313
335
  void WiFiComponent::clear_sta() { this->sta_.clear(); }
314
336
  void WiFiComponent::save_wifi_sta(const std::string &ssid, const std::string &password) {
315
- SavedWifiSettings save{};
316
- snprintf(save.ssid, sizeof(save.ssid), "%s", ssid.c_str());
317
- snprintf(save.password, sizeof(save.password), "%s", password.c_str());
337
+ SavedWifiSettings save{}; // zero-initialized - all bytes set to \0, guaranteeing null termination
338
+ strncpy(save.ssid, ssid.c_str(), sizeof(save.ssid) - 1); // max 32 chars, byte 32 remains \0
339
+ strncpy(save.password, password.c_str(), sizeof(save.password) - 1); // max 64 chars, byte 64 remains \0
318
340
  this->pref_.save(&save);
319
341
  // ensure it's written immediately
320
342
  global_preferences->sync();
@@ -331,8 +353,7 @@ void WiFiComponent::start_connecting(const WiFiAP &ap, bool two) {
331
353
  ESP_LOGV(TAG, "Connection Params:");
332
354
  ESP_LOGV(TAG, " SSID: '%s'", ap.get_ssid().c_str());
333
355
  if (ap.get_bssid().has_value()) {
334
- bssid_t b = *ap.get_bssid();
335
- ESP_LOGV(TAG, " BSSID: %02X:%02X:%02X:%02X:%02X:%02X", b[0], b[1], b[2], b[3], b[4], b[5]);
356
+ ESP_LOGV(TAG, " BSSID: %s", format_mac_address_pretty(ap.get_bssid()->data()).c_str());
336
357
  } else {
337
358
  ESP_LOGV(TAG, " BSSID: Not Set");
338
359
  }
@@ -344,15 +365,8 @@ void WiFiComponent::start_connecting(const WiFiAP &ap, bool two) {
344
365
  ESP_LOGV(TAG, " Identity: " LOG_SECRET("'%s'"), eap_config.identity.c_str());
345
366
  ESP_LOGV(TAG, " Username: " LOG_SECRET("'%s'"), eap_config.username.c_str());
346
367
  ESP_LOGV(TAG, " Password: " LOG_SECRET("'%s'"), eap_config.password.c_str());
347
- #ifdef USE_ESP_IDF
348
- #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
349
- std::map<esp_eap_ttls_phase2_types, std::string> phase2types = {{ESP_EAP_TTLS_PHASE2_PAP, "pap"},
350
- {ESP_EAP_TTLS_PHASE2_CHAP, "chap"},
351
- {ESP_EAP_TTLS_PHASE2_MSCHAP, "mschap"},
352
- {ESP_EAP_TTLS_PHASE2_MSCHAPV2, "mschapv2"},
353
- {ESP_EAP_TTLS_PHASE2_EAP, "eap"}};
354
- ESP_LOGV(TAG, " TTLS Phase 2: " LOG_SECRET("'%s'"), phase2types[eap_config.ttls_phase_2].c_str());
355
- #endif
368
+ #if defined(USE_ESP32) && defined(USE_WIFI_WPA2_EAP) && ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
369
+ ESP_LOGV(TAG, " TTLS Phase 2: " LOG_SECRET("'%s'"), eap_phase2_to_str(eap_config.ttls_phase_2));
356
370
  #endif
357
371
  bool ca_cert_present = eap_config.ca_cert != nullptr && strlen(eap_config.ca_cert);
358
372
  bool client_cert_present = eap_config.client_cert != nullptr && strlen(eap_config.client_cert);
@@ -446,7 +460,6 @@ void WiFiComponent::print_connect_params_() {
446
460
  ESP_LOGCONFIG(TAG, " Disabled");
447
461
  return;
448
462
  }
449
- ESP_LOGCONFIG(TAG, " SSID: " LOG_SECRET("'%s'"), wifi_ssid().c_str());
450
463
  for (auto &ip : wifi_sta_ip_addresses()) {
451
464
  if (ip.is_set()) {
452
465
  ESP_LOGCONFIG(TAG, " IP Address: %s", ip.str().c_str());
@@ -454,24 +467,23 @@ void WiFiComponent::print_connect_params_() {
454
467
  }
455
468
  int8_t rssi = wifi_rssi();
456
469
  ESP_LOGCONFIG(TAG,
457
- " BSSID: " LOG_SECRET("%02X:%02X:%02X:%02X:%02X:%02X") "\n"
458
- " Hostname: '%s'\n"
459
- " Signal strength: %d dB %s",
460
- bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5], App.get_name().c_str(), rssi,
461
- LOG_STR_ARG(get_signal_bars(rssi)));
470
+ " SSID: " LOG_SECRET("'%s'") "\n"
471
+ " BSSID: " LOG_SECRET("%s") "\n"
472
+ " Hostname: '%s'\n"
473
+ " Signal strength: %d dB %s\n"
474
+ " Channel: %" PRId32 "\n"
475
+ " Subnet: %s\n"
476
+ " Gateway: %s\n"
477
+ " DNS1: %s\n"
478
+ " DNS2: %s",
479
+ wifi_ssid().c_str(), format_mac_address_pretty(bssid.data()).c_str(), App.get_name().c_str(), rssi,
480
+ LOG_STR_ARG(get_signal_bars(rssi)), get_wifi_channel(), wifi_subnet_mask_().str().c_str(),
481
+ wifi_gateway_ip_().str().c_str(), wifi_dns_ip_(0).str().c_str(), wifi_dns_ip_(1).str().c_str());
462
482
  #ifdef ESPHOME_LOG_HAS_VERBOSE
463
483
  if (this->selected_ap_.get_bssid().has_value()) {
464
484
  ESP_LOGV(TAG, " Priority: %.1f", this->get_sta_priority(*this->selected_ap_.get_bssid()));
465
485
  }
466
486
  #endif
467
- ESP_LOGCONFIG(TAG,
468
- " Channel: %" PRId32 "\n"
469
- " Subnet: %s\n"
470
- " Gateway: %s\n"
471
- " DNS1: %s\n"
472
- " DNS2: %s",
473
- get_wifi_channel(), wifi_subnet_mask_().str().c_str(), wifi_gateway_ip_().str().c_str(),
474
- wifi_dns_ip_(0).str().c_str(), wifi_dns_ip_(1).str().c_str());
475
487
  #ifdef USE_WIFI_11KV_SUPPORT
476
488
  ESP_LOGCONFIG(TAG,
477
489
  " BTM: %s\n"
@@ -557,6 +569,25 @@ static void insertion_sort_scan_results(std::vector<WiFiScanResult> &results) {
557
569
  }
558
570
  }
559
571
 
572
+ // Helper function to log scan results - marked noinline to prevent re-inlining into loop
573
+ __attribute__((noinline)) static void log_scan_result(const WiFiScanResult &res) {
574
+ char bssid_s[18];
575
+ auto bssid = res.get_bssid();
576
+ format_mac_addr_upper(bssid.data(), bssid_s);
577
+
578
+ if (res.get_matches()) {
579
+ ESP_LOGI(TAG, "- '%s' %s" LOG_SECRET("(%s) ") "%s", res.get_ssid().c_str(), res.get_is_hidden() ? "(HIDDEN) " : "",
580
+ bssid_s, LOG_STR_ARG(get_signal_bars(res.get_rssi())));
581
+ ESP_LOGD(TAG,
582
+ " Channel: %u\n"
583
+ " RSSI: %d dB",
584
+ res.get_channel(), res.get_rssi());
585
+ } else {
586
+ ESP_LOGD(TAG, "- " LOG_SECRET("'%s'") " " LOG_SECRET("(%s) ") "%s", res.get_ssid().c_str(), bssid_s,
587
+ LOG_STR_ARG(get_signal_bars(res.get_rssi())));
588
+ }
589
+ }
590
+
560
591
  void WiFiComponent::check_scanning_finished() {
561
592
  if (!this->scan_done_) {
562
593
  if (millis() - this->action_started_ > 30000) {
@@ -591,21 +622,7 @@ void WiFiComponent::check_scanning_finished() {
591
622
  insertion_sort_scan_results(this->scan_result_);
592
623
 
593
624
  for (auto &res : this->scan_result_) {
594
- char bssid_s[18];
595
- auto bssid = res.get_bssid();
596
- format_mac_addr_upper(bssid.data(), bssid_s);
597
-
598
- if (res.get_matches()) {
599
- ESP_LOGI(TAG, "- '%s' %s" LOG_SECRET("(%s) ") "%s", res.get_ssid().c_str(),
600
- res.get_is_hidden() ? "(HIDDEN) " : "", bssid_s, LOG_STR_ARG(get_signal_bars(res.get_rssi())));
601
- ESP_LOGD(TAG,
602
- " Channel: %u\n"
603
- " RSSI: %d dB",
604
- res.get_channel(), res.get_rssi());
605
- } else {
606
- ESP_LOGD(TAG, "- " LOG_SECRET("'%s'") " " LOG_SECRET("(%s) ") "%s", res.get_ssid().c_str(), bssid_s,
607
- LOG_STR_ARG(get_signal_bars(res.get_rssi())));
608
- }
625
+ log_scan_result(res);
609
626
  }
610
627
 
611
628
  if (!this->scan_result_[0].get_matches()) {
@@ -20,7 +20,7 @@
20
20
  #include <WiFi.h>
21
21
  #endif
22
22
 
23
- #if defined(USE_ESP_IDF) && defined(USE_WIFI_WPA2_EAP)
23
+ #if defined(USE_ESP32) && defined(USE_WIFI_WPA2_EAP)
24
24
  #if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1)
25
25
  #include <esp_eap_client.h>
26
26
  #else
@@ -113,7 +113,7 @@ struct EAPAuth {
113
113
  const char *client_cert;
114
114
  const char *client_key;
115
115
  // used for EAP-TTLS
116
- #ifdef USE_ESP_IDF
116
+ #ifdef USE_ESP32
117
117
  esp_eap_ttls_phase2_types ttls_phase_2;
118
118
  #endif
119
119
  };
@@ -199,7 +199,7 @@ enum WiFiPowerSaveMode : uint8_t {
199
199
  WIFI_POWER_SAVE_HIGH,
200
200
  };
201
201
 
202
- #ifdef USE_ESP_IDF
202
+ #ifdef USE_ESP32
203
203
  struct IDFWiFiEvent;
204
204
  #endif
205
205
 
@@ -368,7 +368,7 @@ class WiFiComponent : public Component {
368
368
  void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info);
369
369
  void wifi_scan_done_callback_();
370
370
  #endif
371
- #ifdef USE_ESP_IDF
371
+ #ifdef USE_ESP32
372
372
  void wifi_process_event_(IDFWiFiEvent *data);
373
373
  #endif
374
374
 
@@ -301,7 +301,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
301
301
  // if we have certs, this must be EAP-TLS
302
302
  ret = wifi_station_set_enterprise_cert_key((uint8_t *) eap.client_cert, client_cert_len + 1,
303
303
  (uint8_t *) eap.client_key, client_key_len + 1,
304
- (uint8_t *) eap.password.c_str(), strlen(eap.password.c_str()));
304
+ (uint8_t *) eap.password.c_str(), eap.password.length());
305
305
  if (ret) {
306
306
  ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_cert_key failed: %d", ret);
307
307
  }
@@ -1,7 +1,7 @@
1
1
  #include "wifi_component.h"
2
2
 
3
3
  #ifdef USE_WIFI
4
- #ifdef USE_ESP_IDF
4
+ #ifdef USE_ESP32
5
5
 
6
6
  #include <esp_event.h>
7
7
  #include <esp_netif.h>
@@ -27,6 +27,10 @@
27
27
  #include "dhcpserver/dhcpserver.h"
28
28
  #endif // USE_WIFI_AP
29
29
 
30
+ #ifdef USE_CAPTIVE_PORTAL
31
+ #include "esphome/components/captive_portal/captive_portal.h"
32
+ #endif
33
+
30
34
  #include "lwip/apps/sntp.h"
31
35
  #include "lwip/dns.h"
32
36
  #include "lwip/err.h"
@@ -404,11 +408,11 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
404
408
  #if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1)
405
409
  err = esp_eap_client_set_certificate_and_key((uint8_t *) eap.client_cert, client_cert_len + 1,
406
410
  (uint8_t *) eap.client_key, client_key_len + 1,
407
- (uint8_t *) eap.password.c_str(), strlen(eap.password.c_str()));
411
+ (uint8_t *) eap.password.c_str(), eap.password.length());
408
412
  #else
409
413
  err = esp_wifi_sta_wpa2_ent_set_cert_key((uint8_t *) eap.client_cert, client_cert_len + 1,
410
414
  (uint8_t *) eap.client_key, client_key_len + 1,
411
- (uint8_t *) eap.password.c_str(), strlen(eap.password.c_str()));
415
+ (uint8_t *) eap.password.c_str(), eap.password.length());
412
416
  #endif
413
417
  if (err != ESP_OK) {
414
418
  ESP_LOGV(TAG, "set_cert_key failed %d", err);
@@ -918,6 +922,22 @@ bool WiFiComponent::wifi_ap_ip_config_(optional<ManualIP> manual_ip) {
918
922
  return false;
919
923
  }
920
924
 
925
+ #if defined(USE_CAPTIVE_PORTAL) && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
926
+ // Configure DHCP Option 114 (Captive Portal URI) if captive portal is enabled
927
+ // This provides a standards-compliant way for clients to discover the captive portal
928
+ if (captive_portal::global_captive_portal != nullptr) {
929
+ static char captive_portal_uri[32];
930
+ snprintf(captive_portal_uri, sizeof(captive_portal_uri), "http://%s", network::IPAddress(&info.ip).str().c_str());
931
+ err = esp_netif_dhcps_option(s_ap_netif, ESP_NETIF_OP_SET, ESP_NETIF_CAPTIVEPORTAL_URI, captive_portal_uri,
932
+ strlen(captive_portal_uri));
933
+ if (err != ESP_OK) {
934
+ ESP_LOGV(TAG, "Failed to set DHCP captive portal URI: %s", esp_err_to_name(err));
935
+ } else {
936
+ ESP_LOGV(TAG, "DHCP Captive Portal URI set to: %s", captive_portal_uri);
937
+ }
938
+ }
939
+ #endif
940
+
921
941
  err = esp_netif_dhcps_start(s_ap_netif);
922
942
 
923
943
  if (err != ESP_OK) {
@@ -1050,5 +1070,5 @@ network::IPAddress WiFiComponent::wifi_dns_ip_(int num) {
1050
1070
  } // namespace wifi
1051
1071
  } // namespace esphome
1052
1072
 
1053
- #endif // USE_ESP_IDF
1073
+ #endif // USE_ESP32
1054
1074
  #endif
@@ -118,7 +118,7 @@ async def to_code(config):
118
118
 
119
119
  # Workaround for crash on IDF 5+
120
120
  # See https://github.com/trombik/esp_wireguard/issues/33#issuecomment-1568503651
121
- if CORE.using_esp_idf:
121
+ if CORE.is_esp32:
122
122
  add_idf_sdkconfig_option("CONFIG_LWIP_PPP_SUPPORT", True)
123
123
 
124
124
  # This flag is added here because the esp_wireguard library statically
File without changes
@@ -0,0 +1,41 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components import sensor, uart
3
+ import esphome.config_validation as cv
4
+ from esphome.const import (
5
+ DEVICE_CLASS_TEMPERATURE,
6
+ STATE_CLASS_MEASUREMENT,
7
+ UNIT_CELSIUS,
8
+ )
9
+
10
+ CONF_WTS01_ID = "wts01_id"
11
+ CODEOWNERS = ["@alepee"]
12
+ DEPENDENCIES = ["uart"]
13
+
14
+ wts01_ns = cg.esphome_ns.namespace("wts01")
15
+ WTS01Sensor = wts01_ns.class_(
16
+ "WTS01Sensor", cg.Component, uart.UARTDevice, sensor.Sensor
17
+ )
18
+
19
+ CONFIG_SCHEMA = (
20
+ sensor.sensor_schema(
21
+ WTS01Sensor,
22
+ unit_of_measurement=UNIT_CELSIUS,
23
+ accuracy_decimals=1,
24
+ device_class=DEVICE_CLASS_TEMPERATURE,
25
+ state_class=STATE_CLASS_MEASUREMENT,
26
+ )
27
+ .extend(cv.COMPONENT_SCHEMA)
28
+ .extend(uart.UART_DEVICE_SCHEMA)
29
+ )
30
+
31
+ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
32
+ "wts01",
33
+ baud_rate=9600,
34
+ require_rx=True,
35
+ )
36
+
37
+
38
+ async def to_code(config):
39
+ var = await sensor.new_sensor(config)
40
+ await cg.register_component(var, config)
41
+ await uart.register_uart_device(var, config)
@@ -0,0 +1,91 @@
1
+ #include "wts01.h"
2
+ #include "esphome/core/log.h"
3
+ #include <cmath>
4
+
5
+ namespace esphome {
6
+ namespace wts01 {
7
+
8
+ constexpr uint8_t HEADER_1 = 0x55;
9
+ constexpr uint8_t HEADER_2 = 0x01;
10
+ constexpr uint8_t HEADER_3 = 0x01;
11
+ constexpr uint8_t HEADER_4 = 0x04;
12
+
13
+ static const char *const TAG = "wts01";
14
+
15
+ void WTS01Sensor::loop() {
16
+ // Process all available data at once
17
+ while (this->available()) {
18
+ uint8_t c;
19
+ if (this->read_byte(&c)) {
20
+ this->handle_char_(c);
21
+ }
22
+ }
23
+ }
24
+
25
+ void WTS01Sensor::dump_config() { LOG_SENSOR("", "WTS01 Sensor", this); }
26
+
27
+ void WTS01Sensor::handle_char_(uint8_t c) {
28
+ // State machine for processing the header. Reset if something doesn't match.
29
+ if (this->buffer_pos_ == 0 && c != HEADER_1) {
30
+ return;
31
+ }
32
+
33
+ if (this->buffer_pos_ == 1 && c != HEADER_2) {
34
+ this->buffer_pos_ = 0;
35
+ return;
36
+ }
37
+
38
+ if (this->buffer_pos_ == 2 && c != HEADER_3) {
39
+ this->buffer_pos_ = 0;
40
+ return;
41
+ }
42
+
43
+ if (this->buffer_pos_ == 3 && c != HEADER_4) {
44
+ this->buffer_pos_ = 0;
45
+ return;
46
+ }
47
+
48
+ // Add byte to buffer
49
+ this->buffer_[this->buffer_pos_++] = c;
50
+
51
+ // Process complete packet
52
+ if (this->buffer_pos_ >= PACKET_SIZE) {
53
+ this->process_packet_();
54
+ this->buffer_pos_ = 0;
55
+ }
56
+ }
57
+
58
+ void WTS01Sensor::process_packet_() {
59
+ // Based on Tasmota implementation
60
+ // Format: 55 01 01 04 01 11 16 12 95
61
+ // header T Td Ck - T = Temperature, Td = Temperature decimal, Ck = Checksum
62
+ uint8_t calculated_checksum = 0;
63
+ for (uint8_t i = 0; i < PACKET_SIZE - 1; i++) {
64
+ calculated_checksum += this->buffer_[i];
65
+ }
66
+
67
+ uint8_t received_checksum = this->buffer_[PACKET_SIZE - 1];
68
+ if (calculated_checksum != received_checksum) {
69
+ ESP_LOGW(TAG, "WTS01 Checksum doesn't match: 0x%02X != 0x%02X", received_checksum, calculated_checksum);
70
+ return;
71
+ }
72
+
73
+ // Extract temperature value
74
+ int8_t temp = this->buffer_[6];
75
+ int32_t sign = 1;
76
+
77
+ // Handle negative temperatures
78
+ if (temp < 0) {
79
+ sign = -1;
80
+ }
81
+
82
+ // Calculate temperature (temp + decimal/100)
83
+ float temperature = static_cast<float>(temp) + (sign * static_cast<float>(this->buffer_[7]) / 100.0f);
84
+
85
+ ESP_LOGV(TAG, "Received new temperature: %.2f°C", temperature);
86
+
87
+ this->publish_state(temperature);
88
+ }
89
+
90
+ } // namespace wts01
91
+ } // namespace esphome
@@ -0,0 +1,27 @@
1
+ #pragma once
2
+
3
+ #include "esphome/core/component.h"
4
+ #include "esphome/components/sensor/sensor.h"
5
+ #include "esphome/components/uart/uart.h"
6
+
7
+ namespace esphome {
8
+ namespace wts01 {
9
+
10
+ constexpr uint8_t PACKET_SIZE = 9;
11
+
12
+ class WTS01Sensor : public sensor::Sensor, public uart::UARTDevice, public Component {
13
+ public:
14
+ void loop() override;
15
+ void dump_config() override;
16
+ float get_setup_priority() const override { return setup_priority::DATA; }
17
+
18
+ protected:
19
+ uint8_t buffer_[PACKET_SIZE];
20
+ uint8_t buffer_pos_{0};
21
+
22
+ void handle_char_(uint8_t c);
23
+ void process_packet_();
24
+ };
25
+
26
+ } // namespace wts01
27
+ } // namespace esphome
@@ -1,4 +1,4 @@
1
- import os
1
+ from pathlib import Path
2
2
  from typing import TypedDict
3
3
 
4
4
  import esphome.codegen as cg
@@ -48,7 +48,7 @@ class ZephyrData(TypedDict):
48
48
  bootloader: str
49
49
  prj_conf: dict[str, tuple[PrjConfValueType, bool]]
50
50
  overlay: str
51
- extra_build_files: dict[str, str]
51
+ extra_build_files: dict[str, Path]
52
52
  pm_static: list[Section]
53
53
  user: dict[str, list[str]]
54
54
 
@@ -93,7 +93,7 @@ def zephyr_add_overlay(content):
93
93
  zephyr_data()[KEY_OVERLAY] += content
94
94
 
95
95
 
96
- def add_extra_build_file(filename: str, path: str) -> bool:
96
+ def add_extra_build_file(filename: str, path: Path) -> bool:
97
97
  """Add an extra build file to the project."""
98
98
  extra_build_files = zephyr_data()[KEY_EXTRA_BUILD_FILES]
99
99
  if filename not in extra_build_files:
@@ -102,7 +102,7 @@ def add_extra_build_file(filename: str, path: str) -> bool:
102
102
  return False
103
103
 
104
104
 
105
- def add_extra_script(stage: str, filename: str, path: str):
105
+ def add_extra_script(stage: str, filename: str, path: Path) -> None:
106
106
  """Add an extra script to the project."""
107
107
  key = f"{stage}:{filename}"
108
108
  if add_extra_build_file(filename, path):
@@ -144,7 +144,7 @@ def zephyr_to_code(config):
144
144
  add_extra_script(
145
145
  "pre",
146
146
  "pre_build.py",
147
- os.path.join(os.path.dirname(__file__), "pre_build.py.script"),
147
+ Path(__file__).parent / "pre_build.py.script",
148
148
  )
149
149
 
150
150
 
@@ -0,0 +1,43 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components import uart
3
+ import esphome.config_validation as cv
4
+ from esphome.const import CONF_ID, CONF_POWER_SAVE_MODE, CONF_WIFI
5
+ import esphome.final_validate as fv
6
+
7
+ CODEOWNERS = ["@kbx81"]
8
+ DEPENDENCIES = ["api", "uart"]
9
+
10
+ zwave_proxy_ns = cg.esphome_ns.namespace("zwave_proxy")
11
+ ZWaveProxy = zwave_proxy_ns.class_("ZWaveProxy", cg.Component, uart.UARTDevice)
12
+
13
+
14
+ def final_validate(config):
15
+ full_config = fv.full_config.get()
16
+ if (wifi_conf := full_config.get(CONF_WIFI)) and (
17
+ wifi_conf.get(CONF_POWER_SAVE_MODE).lower() != "none"
18
+ ):
19
+ raise cv.Invalid(
20
+ f"{CONF_WIFI} {CONF_POWER_SAVE_MODE} must be set to 'none' when using Z-Wave proxy"
21
+ )
22
+
23
+ return config
24
+
25
+
26
+ CONFIG_SCHEMA = (
27
+ cv.Schema(
28
+ {
29
+ cv.GenerateID(): cv.declare_id(ZWaveProxy),
30
+ }
31
+ )
32
+ .extend(cv.COMPONENT_SCHEMA)
33
+ .extend(uart.UART_DEVICE_SCHEMA)
34
+ )
35
+
36
+ FINAL_VALIDATE_SCHEMA = final_validate
37
+
38
+
39
+ async def to_code(config):
40
+ var = cg.new_Pvariable(config[CONF_ID])
41
+ await cg.register_component(var, config)
42
+ await uart.register_uart_device(var, config)
43
+ cg.add_define("USE_ZWAVE_PROXY")