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
@@ -7,12 +7,25 @@
7
7
  #include "esphome/core/helpers.h"
8
8
  #include "esphome/core/log.h"
9
9
  #include "esphome/core/preferences.h"
10
+ #include "esphome/core/hash_base.h"
10
11
 
11
12
  namespace esphome {
12
13
 
13
14
  /// ESPHomeOTAComponent provides a simple way to integrate Over-the-Air updates into your app using ArduinoOTA.
14
15
  class ESPHomeOTAComponent : public ota::OTAComponent {
15
16
  public:
17
+ enum class OTAState : uint8_t {
18
+ IDLE,
19
+ MAGIC_READ, // Reading magic bytes
20
+ MAGIC_ACK, // Sending OK and version after magic bytes
21
+ FEATURE_READ, // Reading feature flags from client
22
+ FEATURE_ACK, // Sending feature acknowledgment
23
+ #ifdef USE_OTA_PASSWORD
24
+ AUTH_SEND, // Sending authentication request
25
+ AUTH_READ, // Reading authentication data
26
+ #endif // USE_OTA_PASSWORD
27
+ DATA, // BLOCKING! Processing OTA data (update, etc.)
28
+ };
16
29
  #ifdef USE_OTA_PASSWORD
17
30
  void set_auth_password(const std::string &password) { password_ = password; }
18
31
  #endif // USE_OTA_PASSWORD
@@ -30,12 +43,38 @@ class ESPHomeOTAComponent : public ota::OTAComponent {
30
43
  protected:
31
44
  void handle_handshake_();
32
45
  void handle_data_();
46
+ #ifdef USE_OTA_PASSWORD
47
+ bool handle_auth_send_();
48
+ bool handle_auth_read_();
49
+ bool select_auth_type_();
50
+ size_t get_auth_hex_size_() const;
51
+ void cleanup_auth_();
52
+ void log_auth_warning_(const LogString *msg);
53
+ #endif // USE_OTA_PASSWORD
33
54
  bool readall_(uint8_t *buf, size_t len);
34
55
  bool writeall_(const uint8_t *buf, size_t len);
56
+
57
+ bool try_read_(size_t to_read, const LogString *desc);
58
+ bool try_write_(size_t to_write, const LogString *desc);
59
+
60
+ inline bool would_block_(int error_code) const { return error_code == EAGAIN || error_code == EWOULDBLOCK; }
61
+ bool handle_read_error_(ssize_t read, const LogString *desc);
62
+ bool handle_write_error_(ssize_t written, const LogString *desc);
63
+ inline void transition_ota_state_(OTAState next_state) {
64
+ this->ota_state_ = next_state;
65
+ this->handshake_buf_pos_ = 0; // Reset buffer position for next state
66
+ }
67
+
35
68
  void log_socket_error_(const LogString *msg);
36
69
  void log_read_error_(const LogString *what);
37
70
  void log_start_(const LogString *phase);
71
+ void log_remote_closed_(const LogString *during);
38
72
  void cleanup_connection_();
73
+ inline void send_error_and_cleanup_(ota::OTAResponseTypes error) {
74
+ uint8_t error_byte = static_cast<uint8_t>(error);
75
+ this->client_->write(&error_byte, 1); // Best effort, non-blocking
76
+ this->cleanup_connection_();
77
+ }
39
78
  void yield_and_feed_watchdog_();
40
79
 
41
80
  #ifdef USE_OTA_PASSWORD
@@ -44,11 +83,19 @@ class ESPHomeOTAComponent : public ota::OTAComponent {
44
83
 
45
84
  std::unique_ptr<socket::Socket> server_;
46
85
  std::unique_ptr<socket::Socket> client_;
86
+ std::unique_ptr<ota::OTABackend> backend_;
47
87
 
48
88
  uint32_t client_connect_time_{0};
49
89
  uint16_t port_;
50
- uint8_t magic_buf_[5];
51
- uint8_t magic_buf_pos_{0};
90
+ uint8_t handshake_buf_[5];
91
+ OTAState ota_state_{OTAState::IDLE};
92
+ uint8_t handshake_buf_pos_{0};
93
+ uint8_t ota_features_{0};
94
+ #ifdef USE_OTA_PASSWORD
95
+ std::unique_ptr<uint8_t[]> auth_buf_;
96
+ uint8_t auth_buf_pos_{0};
97
+ uint8_t auth_type_{0}; // Store auth type to know which hasher to use
98
+ #endif // USE_OTA_PASSWORD
52
99
  };
53
100
 
54
101
  } // namespace esphome
@@ -2,9 +2,15 @@ import logging
2
2
 
3
3
  from esphome import pins
4
4
  import esphome.codegen as cg
5
- from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant
5
+ from esphome.components.esp32 import (
6
+ add_idf_component,
7
+ add_idf_sdkconfig_option,
8
+ get_esp32_variant,
9
+ )
6
10
  from esphome.components.esp32.const import (
11
+ VARIANT_ESP32,
7
12
  VARIANT_ESP32C3,
13
+ VARIANT_ESP32P4,
8
14
  VARIANT_ESP32S2,
9
15
  VARIANT_ESP32S3,
10
16
  )
@@ -21,6 +27,7 @@ from esphome.const import (
21
27
  CONF_GATEWAY,
22
28
  CONF_ID,
23
29
  CONF_INTERRUPT_PIN,
30
+ CONF_MAC_ADDRESS,
24
31
  CONF_MANUAL_IP,
25
32
  CONF_MISO_PIN,
26
33
  CONF_MODE,
@@ -75,12 +82,14 @@ ETHERNET_TYPES = {
75
82
  "W5500": EthernetType.ETHERNET_TYPE_W5500,
76
83
  "OPENETH": EthernetType.ETHERNET_TYPE_OPENETH,
77
84
  "DM9051": EthernetType.ETHERNET_TYPE_DM9051,
85
+ "LAN8670": EthernetType.ETHERNET_TYPE_LAN8670,
78
86
  }
79
87
 
80
88
  # PHY types that need compile-time defines for conditional compilation
81
89
  _PHY_TYPE_TO_DEFINE = {
82
90
  "KSZ8081": "USE_ETHERNET_KSZ8081",
83
91
  "KSZ8081RNA": "USE_ETHERNET_KSZ8081",
92
+ "LAN8670": "USE_ETHERNET_LAN8670",
84
93
  # Add other PHY types here only if they need conditional compilation
85
94
  }
86
95
 
@@ -117,19 +126,15 @@ ManualIP = ethernet_ns.struct("ManualIP")
117
126
 
118
127
  def _is_framework_spi_polling_mode_supported():
119
128
  # SPI Ethernet without IRQ feature is added in
120
- # esp-idf >= (5.3+ ,5.2.1+, 5.1.4) and arduino-esp32 >= 3.0.0
129
+ # esp-idf >= (5.3+ ,5.2.1+, 5.1.4)
130
+ # Note: Arduino now uses ESP-IDF as a component, so we only check IDF version
121
131
  framework_version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]
122
- if CORE.using_esp_idf:
123
- if framework_version >= cv.Version(5, 3, 0):
124
- return True
125
- if cv.Version(5, 3, 0) > framework_version >= cv.Version(5, 2, 1):
126
- return True
127
- if cv.Version(5, 2, 0) > framework_version >= cv.Version(5, 1, 4): # noqa: SIM103
128
- return True
129
- return False
130
- if CORE.using_arduino:
131
- return framework_version >= cv.Version(3, 0, 0)
132
- # fail safe: Unknown framework
132
+ if framework_version >= cv.Version(5, 3, 0):
133
+ return True
134
+ if cv.Version(5, 3, 0) > framework_version >= cv.Version(5, 2, 1):
135
+ return True
136
+ if cv.Version(5, 2, 0) > framework_version >= cv.Version(5, 1, 4): # noqa: SIM103
137
+ return True
133
138
  return False
134
139
 
135
140
 
@@ -140,6 +145,7 @@ def _validate(config):
140
145
  else:
141
146
  use_address = CORE.name + config[CONF_DOMAIN]
142
147
  config[CONF_USE_ADDRESS] = use_address
148
+
143
149
  if config[CONF_TYPE] in SPI_ETHERNET_TYPES:
144
150
  if _is_framework_spi_polling_mode_supported():
145
151
  if CONF_POLLING_INTERVAL in config and CONF_INTERRUPT_PIN in config:
@@ -172,6 +178,12 @@ def _validate(config):
172
178
  del config[CONF_CLK_MODE]
173
179
  elif CONF_CLK not in config:
174
180
  raise cv.Invalid("'clk' is a required option for [ethernet].")
181
+ variant = get_esp32_variant()
182
+ if variant not in (VARIANT_ESP32, VARIANT_ESP32P4):
183
+ raise cv.Invalid(
184
+ f"{config[CONF_TYPE]} PHY requires RMII interface and is only supported "
185
+ f"on ESP32 classic and ESP32-P4, not {variant}"
186
+ )
175
187
 
176
188
  return config
177
189
 
@@ -186,6 +198,7 @@ BASE_SCHEMA = cv.Schema(
186
198
  "This option has been removed. Please use the [disabled] option under the "
187
199
  "new mdns component instead."
188
200
  ),
201
+ cv.Optional(CONF_MAC_ADDRESS): cv.mac_address,
189
202
  }
190
203
  ).extend(cv.COMPONENT_SCHEMA)
191
204
 
@@ -252,6 +265,7 @@ CONFIG_SCHEMA = cv.All(
252
265
  "W5500": SPI_SCHEMA,
253
266
  "OPENETH": BASE_SCHEMA,
254
267
  "DM9051": SPI_SCHEMA,
268
+ "LAN8670": RMII_SCHEMA,
255
269
  },
256
270
  upper=True,
257
271
  ),
@@ -322,11 +336,8 @@ async def to_code(config):
322
336
  cg.add(var.set_clock_speed(config[CONF_CLOCK_SPEED]))
323
337
 
324
338
  cg.add_define("USE_ETHERNET_SPI")
325
- if CORE.using_esp_idf:
326
- add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True)
327
- add_idf_sdkconfig_option(
328
- f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True
329
- )
339
+ add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True)
340
+ add_idf_sdkconfig_option(f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True)
330
341
  elif config[CONF_TYPE] == "OPENETH":
331
342
  cg.add_define("USE_ETHERNET_OPENETH")
332
343
  add_idf_sdkconfig_option("CONFIG_ETH_USE_OPENETH", True)
@@ -356,13 +367,19 @@ async def to_code(config):
356
367
  if phy_define := _PHY_TYPE_TO_DEFINE.get(config[CONF_TYPE]):
357
368
  cg.add_define(phy_define)
358
369
 
370
+ if mac_address := config.get(CONF_MAC_ADDRESS):
371
+ cg.add(var.set_fixed_mac(mac_address.parts))
372
+
359
373
  cg.add_define("USE_ETHERNET")
360
374
 
361
375
  # Disable WiFi when using Ethernet to save memory
362
- if CORE.using_esp_idf:
363
- add_idf_sdkconfig_option("CONFIG_ESP_WIFI_ENABLED", False)
364
- # Also disable WiFi/BT coexistence since WiFi is disabled
365
- add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", False)
376
+ add_idf_sdkconfig_option("CONFIG_ESP_WIFI_ENABLED", False)
377
+ # Also disable WiFi/BT coexistence since WiFi is disabled
378
+ add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", False)
379
+
380
+ if config[CONF_TYPE] == "LAN8670":
381
+ # Add LAN867x 10BASE-T1S PHY support component
382
+ add_idf_component(name="espressif/lan867x", ref="2.0.0")
366
383
 
367
384
  if CORE.using_arduino:
368
385
  cg.add_library("WiFi", None)
@@ -9,6 +9,10 @@
9
9
  #include <cinttypes>
10
10
  #include "esp_event.h"
11
11
 
12
+ #ifdef USE_ETHERNET_LAN8670
13
+ #include "esp_eth_phy_lan867x.h"
14
+ #endif
15
+
12
16
  #ifdef USE_ETHERNET_SPI
13
17
  #include <driver/gpio.h>
14
18
  #include <driver/spi_master.h>
@@ -37,17 +41,20 @@ static const char *const TAG = "ethernet";
37
41
 
38
42
  EthernetComponent *global_eth_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
39
43
 
44
+ void EthernetComponent::log_error_and_mark_failed_(esp_err_t err, const char *message) {
45
+ ESP_LOGE(TAG, "%s: (%d) %s", message, err, esp_err_to_name(err));
46
+ this->mark_failed();
47
+ }
48
+
40
49
  #define ESPHL_ERROR_CHECK(err, message) \
41
50
  if ((err) != ESP_OK) { \
42
- ESP_LOGE(TAG, message ": (%d) %s", err, esp_err_to_name(err)); \
43
- this->mark_failed(); \
51
+ this->log_error_and_mark_failed_(err, message); \
44
52
  return; \
45
53
  }
46
54
 
47
55
  #define ESPHL_ERROR_CHECK_RET(err, message, ret) \
48
56
  if ((err) != ESP_OK) { \
49
- ESP_LOGE(TAG, message ": (%d) %s", err, esp_err_to_name(err)); \
50
- this->mark_failed(); \
57
+ this->log_error_and_mark_failed_(err, message); \
51
58
  return ret; \
52
59
  }
53
60
 
@@ -200,6 +207,12 @@ void EthernetComponent::setup() {
200
207
  this->phy_ = esp_eth_phy_new_ksz80xx(&phy_config);
201
208
  break;
202
209
  }
210
+ #ifdef USE_ETHERNET_LAN8670
211
+ case ETHERNET_TYPE_LAN8670: {
212
+ this->phy_ = esp_eth_phy_new_lan867x(&phy_config);
213
+ break;
214
+ }
215
+ #endif
203
216
  #endif
204
217
  #ifdef USE_ETHERNET_SPI
205
218
  #if CONFIG_ETH_SPI_ETHERNET_W5500
@@ -243,7 +256,11 @@ void EthernetComponent::setup() {
243
256
 
244
257
  // use ESP internal eth mac
245
258
  uint8_t mac_addr[6];
246
- esp_read_mac(mac_addr, ESP_MAC_ETH);
259
+ if (this->fixed_mac_.has_value()) {
260
+ memcpy(mac_addr, this->fixed_mac_->data(), 6);
261
+ } else {
262
+ esp_read_mac(mac_addr, ESP_MAC_ETH);
263
+ }
247
264
  err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_S_MAC_ADDR, mac_addr);
248
265
  ESPHL_ERROR_CHECK(err, "set mac address error");
249
266
 
@@ -353,6 +370,12 @@ void EthernetComponent::dump_config() {
353
370
  eth_type = "DM9051";
354
371
  break;
355
372
 
373
+ #ifdef USE_ETHERNET_LAN8670
374
+ case ETHERNET_TYPE_LAN8670:
375
+ eth_type = "LAN8670";
376
+ break;
377
+ #endif
378
+
356
379
  default:
357
380
  eth_type = "Unknown";
358
381
  break;
@@ -28,6 +28,7 @@ enum EthernetType : uint8_t {
28
28
  ETHERNET_TYPE_W5500,
29
29
  ETHERNET_TYPE_OPENETH,
30
30
  ETHERNET_TYPE_DM9051,
31
+ ETHERNET_TYPE_LAN8670,
31
32
  };
32
33
 
33
34
  struct ManualIP {
@@ -83,6 +84,7 @@ class EthernetComponent : public Component {
83
84
  #endif
84
85
  void set_type(EthernetType type);
85
86
  void set_manual_ip(const ManualIP &manual_ip);
87
+ void set_fixed_mac(const std::array<uint8_t, 6> &mac) { this->fixed_mac_ = mac; }
86
88
 
87
89
  network::IPAddresses get_ip_addresses();
88
90
  network::IPAddress get_dns_address(uint8_t num);
@@ -104,6 +106,7 @@ class EthernetComponent : public Component {
104
106
  void start_connect_();
105
107
  void finish_connect_();
106
108
  void dump_connect_params_();
109
+ void log_error_and_mark_failed_(esp_err_t err, const char *message);
107
110
  #ifdef USE_ETHERNET_KSZ8081
108
111
  /// @brief Set `RMII Reference Clock Select` bit for KSZ8081.
109
112
  void ksz8081_set_clock_reference_(esp_eth_mac_t *mac);
@@ -154,12 +157,13 @@ class EthernetComponent : public Component {
154
157
  esp_netif_t *eth_netif_{nullptr};
155
158
  esp_eth_handle_t eth_handle_;
156
159
  esp_eth_phy_t *phy_{nullptr};
160
+ optional<std::array<uint8_t, 6>> fixed_mac_;
157
161
  };
158
162
 
159
163
  // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
160
164
  extern EthernetComponent *global_eth_component;
161
165
 
162
- #if defined(USE_ARDUINO) || ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2)
166
+ #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2)
163
167
  extern "C" esp_eth_phy_t *esp_eth_phy_new_jl1101(const eth_phy_config_t *config);
164
168
  #endif
165
169
 
@@ -39,11 +39,13 @@ async def to_code(config):
39
39
  pass
40
40
 
41
41
 
42
- def _process_git_config(config: dict, refresh) -> str:
42
+ def _process_git_config(config: dict, refresh, skip_update: bool = False) -> str:
43
+ # When skip_update is True, use NEVER_REFRESH to prevent updates
44
+ actual_refresh = git.NEVER_REFRESH if skip_update else refresh
43
45
  repo_dir, _ = git.clone_or_update(
44
46
  url=config[CONF_URL],
45
47
  ref=config.get(CONF_REF),
46
- refresh=refresh,
48
+ refresh=actual_refresh,
47
49
  domain=DOMAIN,
48
50
  username=config.get(CONF_USERNAME),
49
51
  password=config.get(CONF_PASSWORD),
@@ -70,12 +72,12 @@ def _process_git_config(config: dict, refresh) -> str:
70
72
  return components_dir
71
73
 
72
74
 
73
- def _process_single_config(config: dict):
75
+ def _process_single_config(config: dict, skip_update: bool = False):
74
76
  conf = config[CONF_SOURCE]
75
77
  if conf[CONF_TYPE] == TYPE_GIT:
76
78
  with cv.prepend_path([CONF_SOURCE]):
77
79
  components_dir = _process_git_config(
78
- config[CONF_SOURCE], config[CONF_REFRESH]
80
+ config[CONF_SOURCE], config[CONF_REFRESH], skip_update
79
81
  )
80
82
  elif conf[CONF_TYPE] == TYPE_LOCAL:
81
83
  components_dir = Path(CORE.relative_config_path(conf[CONF_PATH]))
@@ -105,7 +107,7 @@ def _process_single_config(config: dict):
105
107
  loader.install_meta_finder(components_dir, allowed_components=allowed_components)
106
108
 
107
109
 
108
- def do_external_components_pass(config: dict) -> None:
110
+ def do_external_components_pass(config: dict, skip_update: bool = False) -> None:
109
111
  conf = config.get(DOMAIN)
110
112
  if conf is None:
111
113
  return
@@ -113,4 +115,4 @@ def do_external_components_pass(config: dict) -> None:
113
115
  conf = CONFIG_SCHEMA(conf)
114
116
  for i, c in enumerate(conf):
115
117
  with cv.prepend_path(i):
116
- _process_single_config(c)
118
+ _process_single_config(c, skip_update)
@@ -80,7 +80,7 @@ void FingerprintGrowComponent::setup() {
80
80
  delay(20); // This delay guarantees the sensor will in fact be powered power.
81
81
 
82
82
  if (this->check_password_()) {
83
- if (this->new_password_ != -1) {
83
+ if (this->new_password_ != std::numeric_limits<uint32_t>::max()) {
84
84
  if (this->set_password_())
85
85
  return;
86
86
  } else {
@@ -6,6 +6,7 @@
6
6
  #include "esphome/components/binary_sensor/binary_sensor.h"
7
7
  #include "esphome/components/uart/uart.h"
8
8
 
9
+ #include <limits>
9
10
  #include <vector>
10
11
 
11
12
  namespace esphome {
@@ -177,7 +178,7 @@ class FingerprintGrowComponent : public PollingComponent, public uart::UARTDevic
177
178
  uint8_t address_[4] = {0xFF, 0xFF, 0xFF, 0xFF};
178
179
  uint16_t capacity_ = 64;
179
180
  uint32_t password_ = 0x0;
180
- uint32_t new_password_ = -1;
181
+ uint32_t new_password_ = std::numeric_limits<uint32_t>::max();
181
182
  GPIOPin *sensing_pin_{nullptr};
182
183
  GPIOPin *sensor_power_pin_{nullptr};
183
184
  uint8_t enrollment_image_ = 0;
@@ -3,7 +3,6 @@ import functools
3
3
  import hashlib
4
4
  from itertools import accumulate
5
5
  import logging
6
- import os
7
6
  from pathlib import Path
8
7
  import re
9
8
 
@@ -38,6 +37,7 @@ from esphome.const import (
38
37
  )
39
38
  from esphome.core import CORE, HexInt
40
39
  from esphome.helpers import cpp_string_escape
40
+ from esphome.types import ConfigType
41
41
 
42
42
  _LOGGER = logging.getLogger(__name__)
43
43
 
@@ -253,11 +253,11 @@ def validate_truetype_file(value):
253
253
  return CORE.relative_config_path(cv.file_(value))
254
254
 
255
255
 
256
- def add_local_file(value):
256
+ def add_local_file(value: ConfigType) -> ConfigType:
257
257
  if value in FONT_CACHE:
258
258
  return value
259
- path = value[CONF_PATH]
260
- if not os.path.isfile(path):
259
+ path = Path(value[CONF_PATH])
260
+ if not path.is_file():
261
261
  raise cv.Invalid(f"File '{path}' not found.")
262
262
  FONT_CACHE[value] = path
263
263
  return value
@@ -318,7 +318,7 @@ def download_gfont(value):
318
318
  external_files.compute_local_file_dir(DOMAIN)
319
319
  / f"{value[CONF_FAMILY]}@{value[CONF_WEIGHT]}@{value[CONF_ITALIC]}@v1.ttf"
320
320
  )
321
- if not external_files.is_file_recent(str(path), value[CONF_REFRESH]):
321
+ if not external_files.is_file_recent(path, value[CONF_REFRESH]):
322
322
  _LOGGER.debug("download_gfont: path=%s", path)
323
323
  try:
324
324
  req = requests.get(url, timeout=external_files.NETWORK_TIMEOUT)
@@ -179,7 +179,7 @@ void Graph::draw(Display *buff, uint16_t x_offset, uint16_t y_offset, Color colo
179
179
  if (b) {
180
180
  int16_t y = (int16_t) roundf((this->height_ - 1) * (1.0 - v)) - thick / 2 + y_offset;
181
181
  auto draw_pixel_at = [&buff, c, y_offset, this](int16_t x, int16_t y) {
182
- if (y >= y_offset && y < y_offset + this->height_)
182
+ if (y >= y_offset && static_cast<uint32_t>(y) < y_offset + this->height_)
183
183
  buff->draw_pixel_at(x, y, c);
184
184
  };
185
185
  if (!continuous || !has_prev || !prev_b || (abs(y - prev_y) <= thick)) {
@@ -116,7 +116,7 @@ void GraphicalDisplayMenu::draw_menu_internal_(display::Display *display, const
116
116
  int number_items_fit_to_screen = 0;
117
117
  const int max_item_index = this->displayed_item_->items_size() - 1;
118
118
 
119
- for (size_t i = 0; i <= max_item_index; i++) {
119
+ for (size_t i = 0; max_item_index >= 0 && i <= static_cast<size_t>(max_item_index); i++) {
120
120
  const auto *item = this->displayed_item_->get_item(i);
121
121
  const bool selected = i == this->cursor_index_;
122
122
  const display::Rect item_dimensions = this->measure_item(display, item, bounds, selected);
@@ -174,7 +174,8 @@ void GraphicalDisplayMenu::draw_menu_internal_(display::Display *display, const
174
174
 
175
175
  display->filled_rectangle(bounds->x, bounds->y, max_width, total_height, this->background_color_);
176
176
  auto y_offset = bounds->y;
177
- for (size_t i = first_item_index; i <= last_item_index; i++) {
177
+ for (size_t i = static_cast<size_t>(first_item_index);
178
+ last_item_index >= 0 && i <= static_cast<size_t>(last_item_index); i++) {
178
179
  const auto *item = this->displayed_item_->get_item(i);
179
180
  const bool selected = i == this->cursor_index_;
180
181
  display::Rect dimensions = menu_dimensions[i];
@@ -213,7 +213,7 @@ haier_protocol::HandlerError HonClimate::status_handler_(haier_protocol::FrameTy
213
213
  this->real_control_packet_size_);
214
214
  this->status_message_callback_.call((const char *) data, data_size);
215
215
  } else {
216
- ESP_LOGW(TAG, "Status packet too small: %d (should be >= %d)", data_size, this->real_control_packet_size_);
216
+ ESP_LOGW(TAG, "Status packet too small: %zu (should be >= %zu)", data_size, this->real_control_packet_size_);
217
217
  }
218
218
  switch (this->protocol_phase_) {
219
219
  case ProtocolPhases::SENDING_FIRST_STATUS_REQUEST:
@@ -827,7 +827,7 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *
827
827
  size_t expected_size =
828
828
  2 + this->status_message_header_size_ + this->real_control_packet_size_ + this->real_sensors_packet_size_;
829
829
  if (size < expected_size) {
830
- ESP_LOGW(TAG, "Unexpected message size %d (expexted >= %d)", size, expected_size);
830
+ ESP_LOGW(TAG, "Unexpected message size %u (expexted >= %zu)", size, expected_size);
831
831
  return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE;
832
832
  }
833
833
  uint16_t subtype = (((uint16_t) packet_buffer[0]) << 8) + packet_buffer[1];
@@ -178,7 +178,7 @@ class HonClimate : public HaierClimateBase {
178
178
  int extra_control_packet_bytes_{0};
179
179
  int extra_sensors_packet_bytes_{4};
180
180
  int status_message_header_size_{0};
181
- int real_control_packet_size_{sizeof(hon_protocol::HaierPacketControl)};
181
+ size_t real_control_packet_size_{sizeof(hon_protocol::HaierPacketControl)};
182
182
  int real_sensors_packet_size_{sizeof(hon_protocol::HaierPacketSensors) + 4};
183
183
  HonControlMethod control_method_;
184
184
  std::queue<haier_protocol::HaierMessage> control_messages_queue_;
@@ -7,24 +7,20 @@ namespace hdc1080 {
7
7
 
8
8
  static const char *const TAG = "hdc1080";
9
9
 
10
- static const uint8_t HDC1080_ADDRESS = 0x40; // 0b1000000 from datasheet
11
10
  static const uint8_t HDC1080_CMD_CONFIGURATION = 0x02;
12
11
  static const uint8_t HDC1080_CMD_TEMPERATURE = 0x00;
13
12
  static const uint8_t HDC1080_CMD_HUMIDITY = 0x01;
14
13
 
15
14
  void HDC1080Component::setup() {
16
- const uint8_t data[2] = {
17
- 0b00000000, // resolution 14bit for both humidity and temperature
18
- 0b00000000 // reserved
19
- };
15
+ const uint8_t config[2] = {0x00, 0x00}; // resolution 14bit for both humidity and temperature
20
16
 
21
- if (!this->write_bytes(HDC1080_CMD_CONFIGURATION, data, 2)) {
22
- // as instruction is same as powerup defaults (for now), interpret as warning if this fails
23
- ESP_LOGW(TAG, "HDC1080 initial config instruction error");
24
- this->status_set_warning();
17
+ // if configuration fails - there is a problem
18
+ if (this->write_register(HDC1080_CMD_CONFIGURATION, config, 2) != i2c::ERROR_OK) {
19
+ this->mark_failed();
25
20
  return;
26
21
  }
27
22
  }
23
+
28
24
  void HDC1080Component::dump_config() {
29
25
  ESP_LOGCONFIG(TAG, "HDC1080:");
30
26
  LOG_I2C_DEVICE(this);
@@ -35,39 +31,51 @@ void HDC1080Component::dump_config() {
35
31
  LOG_SENSOR(" ", "Temperature", this->temperature_);
36
32
  LOG_SENSOR(" ", "Humidity", this->humidity_);
37
33
  }
34
+
38
35
  void HDC1080Component::update() {
39
- uint16_t raw_temp;
36
+ // regardless of what sensor/s are defined in yaml configuration
37
+ // the hdc1080 setup configuration used, requires both temperature and humidity to be read
38
+
39
+ this->status_clear_warning();
40
+
40
41
  if (this->write(&HDC1080_CMD_TEMPERATURE, 1) != i2c::ERROR_OK) {
41
42
  this->status_set_warning();
42
43
  return;
43
44
  }
44
- delay(20);
45
- if (this->read(reinterpret_cast<uint8_t *>(&raw_temp), 2) != i2c::ERROR_OK) {
46
- this->status_set_warning();
47
- return;
48
- }
49
- raw_temp = i2c::i2ctohs(raw_temp);
50
- float temp = raw_temp * 0.0025177f - 40.0f; // raw * 2^-16 * 165 - 40
51
- this->temperature_->publish_state(temp);
52
45
 
53
- uint16_t raw_humidity;
54
- if (this->write(&HDC1080_CMD_HUMIDITY, 1) != i2c::ERROR_OK) {
55
- this->status_set_warning();
56
- return;
57
- }
58
- delay(20);
59
- if (this->read(reinterpret_cast<uint8_t *>(&raw_humidity), 2) != i2c::ERROR_OK) {
60
- this->status_set_warning();
61
- return;
62
- }
63
- raw_humidity = i2c::i2ctohs(raw_humidity);
64
- float humidity = raw_humidity * 0.001525879f; // raw * 2^-16 * 100
65
- this->humidity_->publish_state(humidity);
46
+ this->set_timeout(20, [this]() {
47
+ uint16_t raw_temperature;
48
+ if (this->read(reinterpret_cast<uint8_t *>(&raw_temperature), 2) != i2c::ERROR_OK) {
49
+ this->status_set_warning();
50
+ return;
51
+ }
66
52
 
67
- ESP_LOGD(TAG, "Got temperature=%.1f°C humidity=%.1f%%", temp, humidity);
68
- this->status_clear_warning();
53
+ if (this->temperature_ != nullptr) {
54
+ raw_temperature = i2c::i2ctohs(raw_temperature);
55
+ float temperature = raw_temperature * 0.0025177f - 40.0f; // raw * 2^-16 * 165 - 40
56
+ this->temperature_->publish_state(temperature);
57
+ }
58
+
59
+ if (this->write(&HDC1080_CMD_HUMIDITY, 1) != i2c::ERROR_OK) {
60
+ this->status_set_warning();
61
+ return;
62
+ }
63
+
64
+ this->set_timeout(20, [this]() {
65
+ uint16_t raw_humidity;
66
+ if (this->read(reinterpret_cast<uint8_t *>(&raw_humidity), 2) != i2c::ERROR_OK) {
67
+ this->status_set_warning();
68
+ return;
69
+ }
70
+
71
+ if (this->humidity_ != nullptr) {
72
+ raw_humidity = i2c::i2ctohs(raw_humidity);
73
+ float humidity = raw_humidity * 0.001525879f; // raw * 2^-16 * 100
74
+ this->humidity_->publish_state(humidity);
75
+ }
76
+ });
77
+ });
69
78
  }
70
- float HDC1080Component::get_setup_priority() const { return setup_priority::DATA; }
71
79
 
72
80
  } // namespace hdc1080
73
81
  } // namespace esphome
@@ -12,13 +12,11 @@ class HDC1080Component : public PollingComponent, public i2c::I2CDevice {
12
12
  void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
13
13
  void set_humidity(sensor::Sensor *humidity) { humidity_ = humidity; }
14
14
 
15
- /// Setup the sensor and check for connection.
16
15
  void setup() override;
17
16
  void dump_config() override;
18
- /// Retrieve the latest sensor values. This operation takes approximately 16ms.
19
17
  void update() override;
20
18
 
21
- float get_setup_priority() const override;
19
+ float get_setup_priority() const override { return setup_priority::DATA; }
22
20
 
23
21
  protected:
24
22
  sensor::Sensor *temperature_{nullptr};
@@ -87,7 +87,7 @@ void HomeassistantNumber::control(float value) {
87
87
  static constexpr auto ENTITY_ID_KEY = StringRef::from_lit("entity_id");
88
88
  static constexpr auto VALUE_KEY = StringRef::from_lit("value");
89
89
 
90
- api::HomeassistantServiceResponse resp;
90
+ api::HomeassistantActionRequest resp;
91
91
  resp.set_service(SERVICE_NAME);
92
92
 
93
93
  resp.data.emplace_back();
@@ -100,7 +100,7 @@ void HomeassistantNumber::control(float value) {
100
100
  entity_value.set_key(VALUE_KEY);
101
101
  entity_value.value = to_string(value);
102
102
 
103
- api::global_api_server->send_homeassistant_service_call(resp);
103
+ api::global_api_server->send_homeassistant_action(resp);
104
104
  }
105
105
 
106
106
  } // namespace homeassistant
@@ -44,7 +44,7 @@ void HomeassistantSwitch::write_state(bool state) {
44
44
  static constexpr auto SERVICE_OFF = StringRef::from_lit("homeassistant.turn_off");
45
45
  static constexpr auto ENTITY_ID_KEY = StringRef::from_lit("entity_id");
46
46
 
47
- api::HomeassistantServiceResponse resp;
47
+ api::HomeassistantActionRequest resp;
48
48
  if (state) {
49
49
  resp.set_service(SERVICE_ON);
50
50
  } else {
@@ -56,7 +56,7 @@ void HomeassistantSwitch::write_state(bool state) {
56
56
  entity_id_kv.set_key(ENTITY_ID_KEY);
57
57
  entity_id_kv.value = this->entity_id_;
58
58
 
59
- api::global_api_server->send_homeassistant_service_call(resp);
59
+ api::global_api_server->send_homeassistant_action(resp);
60
60
  }
61
61
 
62
62
  } // namespace homeassistant