esphome 2025.9.3__py3-none-any.whl → 2025.10.0b2__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 (351) hide show
  1. esphome/__main__.py +94 -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 +7 -7
  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/dashboard_import/dashboard_import.cpp +1 -1
  55. esphome/components/dashboard_import/dashboard_import.h +1 -1
  56. esphome/components/deep_sleep/__init__.py +9 -2
  57. esphome/components/deep_sleep/deep_sleep_component.h +11 -9
  58. esphome/components/deep_sleep/deep_sleep_esp32.cpp +51 -27
  59. esphome/components/ektf2232/touchscreen/__init__.py +8 -5
  60. esphome/components/ektf2232/touchscreen/ektf2232.cpp +4 -4
  61. esphome/components/ektf2232/touchscreen/ektf2232.h +2 -2
  62. esphome/components/epaper_spi/__init__.py +1 -0
  63. esphome/components/epaper_spi/display.py +80 -0
  64. esphome/components/epaper_spi/epaper_spi.cpp +227 -0
  65. esphome/components/epaper_spi/epaper_spi.h +93 -0
  66. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.cpp +42 -0
  67. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.h +45 -0
  68. esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +135 -0
  69. esphome/components/epaper_spi/epaper_spi_spectra_e6.h +23 -0
  70. esphome/components/es7210/es7210.cpp +3 -3
  71. esphome/components/esp32/__init__.py +256 -340
  72. esphome/components/esp32/boards.py +81 -0
  73. esphome/components/esp32/preferences.cpp +23 -17
  74. esphome/components/esp32_ble/__init__.py +167 -44
  75. esphome/components/esp32_ble/ble.cpp +47 -3
  76. esphome/components/esp32_ble/ble.h +18 -0
  77. esphome/components/esp32_ble/ble_advertising.cpp +7 -3
  78. esphome/components/esp32_ble/ble_advertising.h +4 -0
  79. esphome/components/esp32_ble/ble_uuid.cpp +16 -42
  80. esphome/components/esp32_ble_beacon/__init__.py +3 -4
  81. esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +0 -4
  82. esphome/components/esp32_ble_client/ble_client_base.cpp +14 -12
  83. esphome/components/esp32_ble_server/__init__.py +28 -14
  84. esphome/components/esp32_ble_server/ble_characteristic.cpp +67 -57
  85. esphome/components/esp32_ble_server/ble_characteristic.h +27 -16
  86. esphome/components/esp32_ble_server/ble_descriptor.cpp +4 -3
  87. esphome/components/esp32_ble_server/ble_descriptor.h +13 -9
  88. esphome/components/esp32_ble_server/ble_server.cpp +59 -24
  89. esphome/components/esp32_ble_server/ble_server.h +38 -20
  90. esphome/components/esp32_ble_server/ble_server_automations.cpp +49 -33
  91. esphome/components/esp32_ble_server/ble_server_automations.h +39 -24
  92. esphome/components/esp32_ble_tracker/__init__.py +25 -80
  93. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -8
  94. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +0 -3
  95. esphome/components/esp32_camera/__init__.py +1 -3
  96. esphome/components/esp32_can/esp32_can.cpp +22 -4
  97. esphome/components/esp32_can/esp32_can.h +3 -0
  98. esphome/components/esp32_hosted/__init__.py +2 -1
  99. esphome/components/esp32_improv/esp32_improv_component.cpp +135 -65
  100. esphome/components/esp32_improv/esp32_improv_component.h +7 -1
  101. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  102. esphome/components/esp8266/__init__.py +3 -3
  103. esphome/components/esphome/ota/__init__.py +21 -2
  104. esphome/components/esphome/ota/ota_esphome.cpp +456 -146
  105. esphome/components/esphome/ota/ota_esphome.h +49 -2
  106. esphome/components/ethernet/__init__.py +39 -22
  107. esphome/components/ethernet/ethernet_component.cpp +28 -5
  108. esphome/components/ethernet/ethernet_component.h +5 -1
  109. esphome/components/external_components/__init__.py +8 -6
  110. esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
  111. esphome/components/fingerprint_grow/fingerprint_grow.h +2 -1
  112. esphome/components/font/__init__.py +5 -5
  113. esphome/components/graph/graph.cpp +1 -1
  114. esphome/components/graphical_display_menu/graphical_display_menu.cpp +3 -2
  115. esphome/components/haier/hon_climate.cpp +2 -2
  116. esphome/components/haier/hon_climate.h +1 -1
  117. esphome/components/hdc1080/hdc1080.cpp +42 -34
  118. esphome/components/hdc1080/hdc1080.h +1 -3
  119. esphome/components/homeassistant/number/homeassistant_number.cpp +2 -2
  120. esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
  121. esphome/components/http_request/__init__.py +3 -3
  122. esphome/components/htu21d/htu21d.cpp +13 -18
  123. esphome/components/htu21d/htu21d.h +1 -1
  124. esphome/components/i2s_audio/__init__.py +1 -2
  125. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  126. esphome/components/ili9xxx/ili9xxx_display.cpp +2 -2
  127. esphome/components/improv_serial/improv_serial_component.cpp +12 -15
  128. esphome/components/improv_serial/improv_serial_component.h +6 -8
  129. esphome/components/json/json_util.cpp +42 -44
  130. esphome/components/json/json_util.h +57 -0
  131. esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +2 -2
  132. esphome/components/key_collector/key_collector.h +4 -4
  133. esphome/components/libretiny/__init__.py +6 -6
  134. esphome/components/libretiny/preferences.cpp +23 -16
  135. esphome/components/light/light_call.cpp +98 -120
  136. esphome/components/light/light_call.h +17 -7
  137. esphome/components/lm75b/__init__.py +0 -0
  138. esphome/components/lm75b/lm75b.cpp +39 -0
  139. esphome/components/lm75b/lm75b.h +19 -0
  140. esphome/components/lm75b/sensor.py +34 -0
  141. esphome/components/lock/lock.h +12 -6
  142. esphome/components/logger/__init__.py +15 -27
  143. esphome/components/logger/logger.cpp +10 -20
  144. esphome/components/logger/logger.h +105 -62
  145. esphome/components/logger/logger_esp32.cpp +0 -48
  146. esphome/components/logger/logger_zephyr.cpp +2 -3
  147. esphome/components/logger/select/logger_level_select.cpp +6 -7
  148. esphome/components/logger/select/logger_level_select.h +7 -0
  149. esphome/components/ltr501/ltr501.cpp +7 -6
  150. esphome/components/ltr_als_ps/ltr_als_ps.cpp +7 -6
  151. esphome/components/matrix_keypad/matrix_keypad.h +4 -4
  152. esphome/components/max7219digit/max7219digit.cpp +1 -1
  153. esphome/components/mcp23xxx_base/mcp23xxx_base.h +3 -3
  154. esphome/components/mcp2515/mcp2515.cpp +31 -3
  155. esphome/components/mcp2515/mcp2515_defs.h +3 -1
  156. esphome/components/md5/md5.cpp +0 -26
  157. esphome/components/md5/md5.h +10 -20
  158. esphome/components/mdns/__init__.py +93 -19
  159. esphome/components/mdns/mdns_component.cpp +57 -94
  160. esphome/components/mdns/mdns_component.h +35 -11
  161. esphome/components/mdns/mdns_esp32.cpp +7 -13
  162. esphome/components/mdns/mdns_esp8266.cpp +7 -7
  163. esphome/components/mdns/mdns_libretiny.cpp +3 -4
  164. esphome/components/mdns/mdns_rp2040.cpp +3 -4
  165. esphome/components/mipi/__init__.py +1 -5
  166. esphome/components/mipi_spi/display.py +24 -8
  167. esphome/components/mipi_spi/mipi_spi.h +3 -3
  168. esphome/components/mixer/speaker/mixer_speaker.cpp +3 -3
  169. esphome/components/mmc5603/mmc5603.cpp +3 -3
  170. esphome/components/modbus/modbus.cpp +27 -13
  171. esphome/components/modbus/modbus.h +5 -3
  172. esphome/components/modbus/modbus_definitions.h +86 -0
  173. esphome/components/modbus_controller/__init__.py +29 -1
  174. esphome/components/modbus_controller/const.py +4 -0
  175. esphome/components/modbus_controller/modbus_controller.cpp +38 -13
  176. esphome/components/modbus_controller/modbus_controller.h +18 -29
  177. esphome/components/mpr121/mpr121.cpp +41 -42
  178. esphome/components/mpr121/mpr121.h +0 -1
  179. esphome/components/nau7802/nau7802.cpp +2 -2
  180. esphome/components/network/__init__.py +7 -3
  181. esphome/components/nextion/display.py +4 -4
  182. esphome/components/nextion/nextion.cpp +8 -8
  183. esphome/components/number/__init__.py +2 -0
  184. esphome/components/number/number_call.cpp +23 -12
  185. esphome/components/number/number_call.h +5 -0
  186. esphome/components/online_image/bmp_image.cpp +2 -1
  187. esphome/components/online_image/jpeg_image.cpp +4 -2
  188. esphome/components/opentherm/opentherm.cpp +5 -5
  189. esphome/components/opentherm/opentherm.h +3 -3
  190. esphome/components/openthread/openthread.cpp +11 -10
  191. esphome/components/openthread/openthread.h +0 -1
  192. esphome/components/ota/ota_backend.h +1 -0
  193. esphome/components/packages/__init__.py +10 -8
  194. esphome/components/packet_transport/packet_transport.cpp +2 -0
  195. esphome/components/pid/pid_controller.cpp +1 -1
  196. esphome/components/prometheus/prometheus_handler.cpp +239 -239
  197. esphome/components/psram/__init__.py +30 -28
  198. esphome/components/qmc5883l/qmc5883l.cpp +15 -0
  199. esphome/components/qmc5883l/qmc5883l.h +3 -0
  200. esphome/components/qmc5883l/sensor.py +31 -12
  201. esphome/components/remote_base/gobox_protocol.cpp +3 -3
  202. esphome/components/remote_receiver/__init__.py +14 -2
  203. esphome/components/remote_receiver/{remote_receiver_esp8266.cpp → remote_receiver.cpp} +2 -2
  204. esphome/components/remote_receiver/remote_receiver.h +4 -0
  205. esphome/components/remote_receiver/remote_receiver_esp32.cpp +18 -1
  206. esphome/components/remote_transmitter/__init__.py +2 -2
  207. esphome/components/remote_transmitter/remote_transmitter.cpp +103 -0
  208. esphome/components/rp2040/__init__.py +11 -11
  209. esphome/components/rtttl/rtttl.cpp +2 -2
  210. esphome/components/scd30/sensor.py +1 -1
  211. esphome/components/script/__init__.py +1 -1
  212. esphome/components/script/script.h +7 -7
  213. esphome/components/select/select.cpp +5 -4
  214. esphome/components/select/select_call.cpp +1 -1
  215. esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
  216. esphome/components/sensor/__init__.py +2 -0
  217. esphome/components/sha256/__init__.py +22 -0
  218. esphome/components/sha256/sha256.cpp +116 -0
  219. esphome/components/sha256/sha256.h +60 -0
  220. esphome/components/socket/lwip_raw_tcp_impl.cpp +34 -6
  221. esphome/components/sonoff_d1/sonoff_d1.cpp +1 -1
  222. esphome/components/spi/__init__.py +0 -3
  223. esphome/components/split_buffer/__init__.py +5 -0
  224. esphome/components/split_buffer/split_buffer.cpp +133 -0
  225. esphome/components/split_buffer/split_buffer.h +40 -0
  226. esphome/components/sps30/sps30.cpp +14 -10
  227. esphome/components/sps30/sps30.h +2 -0
  228. esphome/components/st7567_i2c/st7567_i2c.cpp +3 -1
  229. esphome/components/st7789v/st7789v.cpp +3 -2
  230. esphome/components/statsd/statsd.cpp +1 -1
  231. esphome/components/substitutions/__init__.py +3 -1
  232. esphome/components/substitutions/jinja.py +13 -3
  233. esphome/components/sx126x/__init__.py +16 -0
  234. esphome/components/sx126x/sx126x.cpp +15 -1
  235. esphome/components/sx126x/sx126x.h +9 -1
  236. esphome/components/sx126x/sx126x_reg.h +2 -0
  237. esphome/components/text_sensor/text_sensor.cpp +16 -0
  238. esphome/components/text_sensor/text_sensor.h +3 -10
  239. esphome/components/tormatic/tormatic_cover.cpp +1 -1
  240. esphome/components/tuya/select/tuya_select.cpp +1 -1
  241. esphome/components/tuya/tuya.cpp +29 -4
  242. esphome/components/uart/__init__.py +37 -27
  243. esphome/components/uart/uart.h +6 -0
  244. esphome/components/uart/uart_component.cpp +8 -0
  245. esphome/components/uart/uart_component.h +28 -0
  246. esphome/components/uart/uart_component_esp_idf.cpp +64 -10
  247. esphome/components/uart/uart_component_esp_idf.h +5 -2
  248. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
  249. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +1 -1
  250. esphome/components/uponor_smatrix/uponor_smatrix.cpp +3 -3
  251. esphome/components/usb_host/__init__.py +12 -2
  252. esphome/components/usb_host/usb_host.h +89 -14
  253. esphome/components/usb_host/usb_host_client.cpp +157 -22
  254. esphome/components/usb_host/usb_host_component.cpp +1 -1
  255. esphome/components/usb_uart/__init__.py +0 -1
  256. esphome/components/usb_uart/ch34x.cpp +4 -4
  257. esphome/components/usb_uart/cp210x.cpp +3 -3
  258. esphome/components/usb_uart/usb_uart.cpp +88 -32
  259. esphome/components/usb_uart/usb_uart.h +30 -6
  260. esphome/components/valve/valve.cpp +1 -0
  261. esphome/components/veml7700/veml7700.cpp +7 -6
  262. esphome/components/version/version_text_sensor.cpp +2 -1
  263. esphome/components/voice_assistant/voice_assistant.cpp +3 -2
  264. esphome/components/waveshare_epaper/waveshare_epaper.cpp +4 -4
  265. esphome/components/web_server/list_entities.cpp +3 -4
  266. esphome/components/web_server/list_entities.h +8 -10
  267. esphome/components/web_server/ota/__init__.py +1 -1
  268. esphome/components/web_server/ota/ota_web_server.cpp +9 -3
  269. esphome/components/web_server/web_server.cpp +509 -404
  270. esphome/components/web_server/web_server.h +5 -6
  271. esphome/components/web_server/web_server_v1.cpp +21 -19
  272. esphome/components/web_server_base/__init__.py +5 -2
  273. esphome/components/web_server_base/web_server_base.h +27 -7
  274. esphome/components/web_server_idf/__init__.py +1 -1
  275. esphome/components/web_server_idf/multipart.cpp +2 -2
  276. esphome/components/web_server_idf/multipart.h +2 -2
  277. esphome/components/web_server_idf/utils.cpp +2 -2
  278. esphome/components/web_server_idf/utils.h +2 -2
  279. esphome/components/web_server_idf/web_server_idf.cpp +118 -26
  280. esphome/components/web_server_idf/web_server_idf.h +12 -10
  281. esphome/components/wifi/__init__.py +13 -11
  282. esphome/components/wifi/wifi_component.cpp +74 -56
  283. esphome/components/wifi/wifi_component.h +4 -4
  284. esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
  285. esphome/components/wifi/wifi_component_esp_idf.cpp +24 -4
  286. esphome/components/wireguard/__init__.py +1 -1
  287. esphome/components/wts01/__init__.py +0 -0
  288. esphome/components/wts01/sensor.py +41 -0
  289. esphome/components/wts01/wts01.cpp +91 -0
  290. esphome/components/wts01/wts01.h +27 -0
  291. esphome/components/zephyr/__init__.py +5 -5
  292. esphome/components/zwave_proxy/__init__.py +43 -0
  293. esphome/components/zwave_proxy/zwave_proxy.cpp +346 -0
  294. esphome/components/zwave_proxy/zwave_proxy.h +93 -0
  295. esphome/config.py +79 -24
  296. esphome/config_validation.py +13 -15
  297. esphome/const.py +9 -2
  298. esphome/core/__init__.py +33 -22
  299. esphome/core/component.cpp +28 -18
  300. esphome/core/component_iterator.h +2 -1
  301. esphome/core/config.py +15 -15
  302. esphome/core/defines.h +21 -0
  303. esphome/core/entity_helpers.py +9 -6
  304. esphome/core/hash_base.h +56 -0
  305. esphome/core/helpers.cpp +19 -3
  306. esphome/core/helpers.h +26 -0
  307. esphome/core/scheduler.cpp +5 -21
  308. esphome/core/scheduler.h +19 -8
  309. esphome/core/string_ref.h +1 -1
  310. esphome/core/time.cpp +5 -5
  311. esphome/cpp_generator.py +4 -29
  312. esphome/dashboard/const.py +21 -4
  313. esphome/dashboard/core.py +10 -8
  314. esphome/dashboard/dns.py +15 -0
  315. esphome/dashboard/entries.py +15 -21
  316. esphome/dashboard/models.py +76 -0
  317. esphome/dashboard/settings.py +7 -7
  318. esphome/dashboard/status/mdns.py +46 -2
  319. esphome/dashboard/web_server.py +367 -93
  320. esphome/espota2.py +112 -32
  321. esphome/external_files.py +6 -7
  322. esphome/git.py +8 -0
  323. esphome/helpers.py +124 -77
  324. esphome/loader.py +8 -9
  325. esphome/pins.py +2 -2
  326. esphome/platformio_api.py +56 -18
  327. esphome/storage_json.py +26 -21
  328. esphome/types.py +30 -2
  329. esphome/util.py +32 -16
  330. esphome/vscode.py +8 -8
  331. esphome/wizard.py +10 -10
  332. esphome/writer.py +50 -15
  333. esphome/yaml_util.py +37 -31
  334. esphome/zeroconf.py +12 -3
  335. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/METADATA +12 -12
  336. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/RECORD +340 -320
  337. esphome/components/event_emitter/__init__.py +0 -5
  338. esphome/components/event_emitter/event_emitter.cpp +0 -14
  339. esphome/components/event_emitter/event_emitter.h +0 -63
  340. esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -125
  341. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +0 -107
  342. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +0 -110
  343. esphome/components/uart/uart_component_esp32_arduino.cpp +0 -214
  344. esphome/components/uart/uart_component_esp32_arduino.h +0 -60
  345. esphome/components/wifi/wifi_component_esp32_arduino.cpp +0 -860
  346. esphome/core/string_ref.cpp +0 -12
  347. esphome/dashboard/util/file.py +0 -63
  348. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/WHEEL +0 -0
  349. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/entry_points.txt +0 -0
  350. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/licenses/LICENSE +0 -0
  351. {esphome-2025.9.3.dist-info → esphome-2025.10.0b2.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,10 @@
1
+ from ast import literal_eval
1
2
  import logging
2
3
  import math
3
4
  import re
4
5
 
5
6
  import jinja2 as jinja
6
- from jinja2.nativetypes import NativeEnvironment
7
+ from jinja2.sandbox import SandboxedEnvironment
7
8
 
8
9
  TemplateError = jinja.TemplateError
9
10
  TemplateSyntaxError = jinja.TemplateSyntaxError
@@ -70,7 +71,7 @@ class Jinja:
70
71
  """
71
72
 
72
73
  def __init__(self, context_vars):
73
- self.env = NativeEnvironment(
74
+ self.env = SandboxedEnvironment(
74
75
  trim_blocks=True,
75
76
  lstrip_blocks=True,
76
77
  block_start_string="<%",
@@ -90,6 +91,15 @@ class Jinja:
90
91
  **SAFE_GLOBAL_FUNCTIONS,
91
92
  }
92
93
 
94
+ def safe_eval(self, expr):
95
+ try:
96
+ result = literal_eval(expr)
97
+ if not isinstance(result, str):
98
+ return result
99
+ except (ValueError, SyntaxError, MemoryError, TypeError):
100
+ pass
101
+ return expr
102
+
93
103
  def expand(self, content_str):
94
104
  """
95
105
  Renders a string that may contain Jinja expressions or statements
@@ -106,7 +116,7 @@ class Jinja:
106
116
  override_vars = content_str.upvalues
107
117
  try:
108
118
  template = self.env.from_string(content_str)
109
- result = template.render(override_vars)
119
+ result = self.safe_eval(template.render(override_vars))
110
120
  if isinstance(result, Undefined):
111
121
  # This happens when the expression is simply an undefined variable. Jinja does not
112
122
  # raise an exception, instead we get "Undefined".
@@ -15,6 +15,10 @@ CONF_BANDWIDTH = "bandwidth"
15
15
  CONF_BITRATE = "bitrate"
16
16
  CONF_CODING_RATE = "coding_rate"
17
17
  CONF_CRC_ENABLE = "crc_enable"
18
+ CONF_CRC_INVERTED = "crc_inverted"
19
+ CONF_CRC_SIZE = "crc_size"
20
+ CONF_CRC_POLYNOMIAL = "crc_polynomial"
21
+ CONF_CRC_INITIAL = "crc_initial"
18
22
  CONF_DEVIATION = "deviation"
19
23
  CONF_DIO1_PIN = "dio1_pin"
20
24
  CONF_HW_VERSION = "hw_version"
@@ -188,6 +192,14 @@ CONFIG_SCHEMA = (
188
192
  cv.Required(CONF_BUSY_PIN): pins.internal_gpio_input_pin_schema,
189
193
  cv.Optional(CONF_CODING_RATE, default="CR_4_5"): cv.enum(CODING_RATE),
190
194
  cv.Optional(CONF_CRC_ENABLE, default=False): cv.boolean,
195
+ cv.Optional(CONF_CRC_INVERTED, default=True): cv.boolean,
196
+ cv.Optional(CONF_CRC_SIZE, default=2): cv.int_range(min=1, max=2),
197
+ cv.Optional(CONF_CRC_POLYNOMIAL, default=0x1021): cv.All(
198
+ cv.hex_int, cv.Range(min=0, max=0xFFFF)
199
+ ),
200
+ cv.Optional(CONF_CRC_INITIAL, default=0x1D0F): cv.All(
201
+ cv.hex_int, cv.Range(min=0, max=0xFFFF)
202
+ ),
191
203
  cv.Optional(CONF_DEVIATION, default=5000): cv.int_range(min=0, max=100000),
192
204
  cv.Required(CONF_DIO1_PIN): pins.internal_gpio_input_pin_schema,
193
205
  cv.Required(CONF_FREQUENCY): cv.int_range(min=137000000, max=1020000000),
@@ -251,6 +263,10 @@ async def to_code(config):
251
263
  cg.add(var.set_shaping(config[CONF_SHAPING]))
252
264
  cg.add(var.set_bitrate(config[CONF_BITRATE]))
253
265
  cg.add(var.set_crc_enable(config[CONF_CRC_ENABLE]))
266
+ cg.add(var.set_crc_inverted(config[CONF_CRC_INVERTED]))
267
+ cg.add(var.set_crc_size(config[CONF_CRC_SIZE]))
268
+ cg.add(var.set_crc_polynomial(config[CONF_CRC_POLYNOMIAL]))
269
+ cg.add(var.set_crc_initial(config[CONF_CRC_INITIAL]))
254
270
  cg.add(var.set_payload_length(config[CONF_PAYLOAD_LENGTH]))
255
271
  cg.add(var.set_preamble_size(config[CONF_PREAMBLE_SIZE]))
256
272
  cg.add(var.set_preamble_detect(config[CONF_PREAMBLE_DETECT]))
@@ -235,6 +235,16 @@ void SX126x::configure() {
235
235
  buf[7] = (fdev >> 0) & 0xFF;
236
236
  this->write_opcode_(RADIO_SET_MODULATIONPARAMS, buf, 8);
237
237
 
238
+ // set crc params
239
+ if (this->crc_enable_) {
240
+ buf[0] = this->crc_initial_ >> 8;
241
+ buf[1] = this->crc_initial_ & 0xFF;
242
+ this->write_register_(REG_CRC_INITIAL, buf, 2);
243
+ buf[0] = this->crc_polynomial_ >> 8;
244
+ buf[1] = this->crc_polynomial_ & 0xFF;
245
+ this->write_register_(REG_CRC_POLYNOMIAL, buf, 2);
246
+ }
247
+
238
248
  // set packet params and sync word
239
249
  this->set_packet_params_(this->get_max_packet_size());
240
250
  if (!this->sync_value_.empty()) {
@@ -276,7 +286,11 @@ void SX126x::set_packet_params_(uint8_t payload_length) {
276
286
  buf[4] = 0x00;
277
287
  buf[5] = (this->payload_length_ > 0) ? 0x00 : 0x01;
278
288
  buf[6] = payload_length;
279
- buf[7] = this->crc_enable_ ? 0x06 : 0x01;
289
+ if (this->crc_enable_) {
290
+ buf[7] = (this->crc_inverted_ ? 0x04 : 0x00) + (this->crc_size_ & 0x02);
291
+ } else {
292
+ buf[7] = 0x01;
293
+ }
280
294
  buf[8] = 0x00;
281
295
  this->write_opcode_(RADIO_SET_PACKETPARAMS, buf, 9);
282
296
  }
@@ -67,6 +67,10 @@ class SX126x : public Component,
67
67
  void set_busy_pin(InternalGPIOPin *busy_pin) { this->busy_pin_ = busy_pin; }
68
68
  void set_coding_rate(uint8_t coding_rate) { this->coding_rate_ = coding_rate; }
69
69
  void set_crc_enable(bool crc_enable) { this->crc_enable_ = crc_enable; }
70
+ void set_crc_inverted(bool crc_inverted) { this->crc_inverted_ = crc_inverted; }
71
+ void set_crc_size(uint8_t crc_size) { this->crc_size_ = crc_size; }
72
+ void set_crc_polynomial(uint16_t crc_polynomial) { this->crc_polynomial_ = crc_polynomial; }
73
+ void set_crc_initial(uint16_t crc_initial) { this->crc_initial_ = crc_initial; }
70
74
  void set_deviation(uint32_t deviation) { this->deviation_ = deviation; }
71
75
  void set_dio1_pin(InternalGPIOPin *dio1_pin) { this->dio1_pin_ = dio1_pin; }
72
76
  void set_frequency(uint32_t frequency) { this->frequency_ = frequency; }
@@ -118,6 +122,11 @@ class SX126x : public Component,
118
122
  char version_[16];
119
123
  SX126xBw bandwidth_{SX126X_BW_125000};
120
124
  uint32_t bitrate_{0};
125
+ bool crc_enable_{false};
126
+ bool crc_inverted_{false};
127
+ uint8_t crc_size_{0};
128
+ uint16_t crc_polynomial_{0};
129
+ uint16_t crc_initial_{0};
121
130
  uint32_t deviation_{0};
122
131
  uint32_t frequency_{0};
123
132
  uint32_t payload_length_{0};
@@ -131,7 +140,6 @@ class SX126x : public Component,
131
140
  uint8_t shaping_{0};
132
141
  uint8_t spreading_factor_{0};
133
142
  int8_t pa_power_{0};
134
- bool crc_enable_{false};
135
143
  bool rx_start_{false};
136
144
  bool rf_switch_{false};
137
145
  };
@@ -53,6 +53,8 @@ enum SX126xOpCode : uint8_t {
53
53
 
54
54
  enum SX126xRegister : uint16_t {
55
55
  REG_VERSION_STRING = 0x0320,
56
+ REG_CRC_INITIAL = 0x06BC,
57
+ REG_CRC_POLYNOMIAL = 0x06BE,
56
58
  REG_GFSK_SYNCWORD = 0x06C0,
57
59
  REG_LORA_SYNCWORD = 0x0740,
58
60
  REG_OCP = 0x08E7,
@@ -6,6 +6,22 @@ namespace text_sensor {
6
6
 
7
7
  static const char *const TAG = "text_sensor";
8
8
 
9
+ void log_text_sensor(const char *tag, const char *prefix, const char *type, TextSensor *obj) {
10
+ if (obj == nullptr) {
11
+ return;
12
+ }
13
+
14
+ ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str());
15
+
16
+ if (!obj->get_device_class_ref().empty()) {
17
+ ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj->get_device_class_ref().c_str());
18
+ }
19
+
20
+ if (!obj->get_icon_ref().empty()) {
21
+ ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj->get_icon_ref().c_str());
22
+ }
23
+ }
24
+
9
25
  void TextSensor::publish_state(const std::string &state) {
10
26
  this->raw_state = state;
11
27
  if (this->raw_callback_) {
@@ -11,16 +11,9 @@
11
11
  namespace esphome {
12
12
  namespace text_sensor {
13
13
 
14
- #define LOG_TEXT_SENSOR(prefix, type, obj) \
15
- if ((obj) != nullptr) { \
16
- ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
17
- if (!(obj)->get_device_class_ref().empty()) { \
18
- ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class_ref().c_str()); \
19
- } \
20
- if (!(obj)->get_icon_ref().empty()) { \
21
- ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \
22
- } \
23
- }
14
+ void log_text_sensor(const char *tag, const char *prefix, const char *type, TextSensor *obj);
15
+
16
+ #define LOG_TEXT_SENSOR(prefix, type, obj) log_text_sensor(TAG, prefix, LOG_STR_LITERAL(type), obj)
24
17
 
25
18
  #define SUB_TEXT_SENSOR(name) \
26
19
  protected: \
@@ -251,7 +251,7 @@ void Tormatic::stop_at_target_() {
251
251
  // Read a GateStatus from the unit. The unit only sends messages in response to
252
252
  // status requests or commands, so a message needs to be sent first.
253
253
  optional<GateStatus> Tormatic::read_gate_status_() {
254
- if (this->available() < sizeof(MessageHeader)) {
254
+ if (this->available() < static_cast<int>(sizeof(MessageHeader))) {
255
255
  return {};
256
256
  }
257
257
 
@@ -50,7 +50,7 @@ void TuyaSelect::dump_config() {
50
50
  " Options are:",
51
51
  this->select_id_, this->is_int_ ? "int" : "enum");
52
52
  auto options = this->traits.get_options();
53
- for (auto i = 0; i < this->mappings_.size(); i++) {
53
+ for (size_t i = 0; i < this->mappings_.size(); i++) {
54
54
  ESP_LOGCONFIG(TAG, " %i: %s", this->mappings_.at(i), options.at(i).c_str());
55
55
  }
56
56
  }
@@ -215,12 +215,37 @@ void Tuya::handle_command_(uint8_t command, uint8_t version, const uint8_t *buff
215
215
  this->send_empty_command_(TuyaCommandType::DATAPOINT_QUERY);
216
216
  }
217
217
  break;
218
- case TuyaCommandType::WIFI_RESET:
219
- ESP_LOGE(TAG, "WIFI_RESET is not handled");
220
- break;
221
218
  case TuyaCommandType::WIFI_SELECT:
222
- ESP_LOGE(TAG, "WIFI_SELECT is not handled");
219
+ case TuyaCommandType::WIFI_RESET: {
220
+ const bool is_select = (len >= 1);
221
+ // Send WIFI_SELECT ACK
222
+ TuyaCommand ack;
223
+ ack.cmd = is_select ? TuyaCommandType::WIFI_SELECT : TuyaCommandType::WIFI_RESET;
224
+ ack.payload.clear();
225
+ this->send_command_(ack);
226
+ // Establish pairing mode for correct first WIFI_STATE byte, EZ (0x00) default
227
+ uint8_t first = 0x00;
228
+ const char *mode_str = "EZ";
229
+ if (is_select && buffer[0] == 0x01) {
230
+ first = 0x01;
231
+ mode_str = "AP";
232
+ }
233
+ // Send WIFI_STATE response, MCU exits pairing mode
234
+ TuyaCommand st;
235
+ st.cmd = TuyaCommandType::WIFI_STATE;
236
+ st.payload.resize(1);
237
+ st.payload[0] = first;
238
+ this->send_command_(st);
239
+ st.payload[0] = 0x02;
240
+ this->send_command_(st);
241
+ st.payload[0] = 0x03;
242
+ this->send_command_(st);
243
+ st.payload[0] = 0x04;
244
+ this->send_command_(st);
245
+ ESP_LOGI(TAG, "%s received (%s), replied with WIFI_STATE confirming connection established",
246
+ is_select ? "WIFI_SELECT" : "WIFI_RESET", mode_str);
223
247
  break;
248
+ }
224
249
  case TuyaCommandType::DATAPOINT_DELIVER:
225
250
  break;
226
251
  case TuyaCommandType::DATAPOINT_REPORT_ASYNC:
@@ -1,3 +1,4 @@
1
+ import math
1
2
  import re
2
3
 
3
4
  from esphome import automation, pins
@@ -14,9 +15,9 @@ from esphome.const import (
14
15
  CONF_DIRECTION,
15
16
  CONF_DUMMY_RECEIVER,
16
17
  CONF_DUMMY_RECEIVER_ID,
18
+ CONF_FLOW_CONTROL_PIN,
17
19
  CONF_ID,
18
20
  CONF_INVERT,
19
- CONF_INVERTED,
20
21
  CONF_LAMBDA,
21
22
  CONF_NUMBER,
22
23
  CONF_PORT,
@@ -39,9 +40,6 @@ uart_ns = cg.esphome_ns.namespace("uart")
39
40
  UARTComponent = uart_ns.class_("UARTComponent")
40
41
 
41
42
  IDFUARTComponent = uart_ns.class_("IDFUARTComponent", UARTComponent, cg.Component)
42
- ESP32ArduinoUARTComponent = uart_ns.class_(
43
- "ESP32ArduinoUARTComponent", UARTComponent, cg.Component
44
- )
45
43
  ESP8266UartComponent = uart_ns.class_(
46
44
  "ESP8266UartComponent", UARTComponent, cg.Component
47
45
  )
@@ -53,7 +51,6 @@ HostUartComponent = uart_ns.class_("HostUartComponent", UARTComponent, cg.Compon
53
51
 
54
52
  NATIVE_UART_CLASSES = (
55
53
  str(IDFUARTComponent),
56
- str(ESP32ArduinoUARTComponent),
57
54
  str(ESP8266UartComponent),
58
55
  str(RP2040UartComponent),
59
56
  str(LibreTinyUARTComponent),
@@ -119,20 +116,6 @@ def validate_rx_pin(value):
119
116
  return value
120
117
 
121
118
 
122
- def validate_invert_esp32(config):
123
- if (
124
- CORE.is_esp32
125
- and CORE.using_arduino
126
- and CONF_TX_PIN in config
127
- and CONF_RX_PIN in config
128
- and config[CONF_TX_PIN][CONF_INVERTED] != config[CONF_RX_PIN][CONF_INVERTED]
129
- ):
130
- raise cv.Invalid(
131
- "Different invert values for TX and RX pin are not supported for ESP32 when using Arduino."
132
- )
133
- return config
134
-
135
-
136
119
  def validate_host_config(config):
137
120
  if CORE.is_host:
138
121
  if CONF_TX_PIN in config or CONF_RX_PIN in config:
@@ -151,10 +134,7 @@ def _uart_declare_type(value):
151
134
  if CORE.is_esp8266:
152
135
  return cv.declare_id(ESP8266UartComponent)(value)
153
136
  if CORE.is_esp32:
154
- if CORE.using_arduino:
155
- return cv.declare_id(ESP32ArduinoUARTComponent)(value)
156
- if CORE.using_esp_idf:
157
- return cv.declare_id(IDFUARTComponent)(value)
137
+ return cv.declare_id(IDFUARTComponent)(value)
158
138
  if CORE.is_rp2040:
159
139
  return cv.declare_id(RP2040UartComponent)(value)
160
140
  if CORE.is_libretiny:
@@ -174,6 +154,8 @@ UART_PARITY_OPTIONS = {
174
154
  CONF_STOP_BITS = "stop_bits"
175
155
  CONF_DATA_BITS = "data_bits"
176
156
  CONF_PARITY = "parity"
157
+ CONF_RX_FULL_THRESHOLD = "rx_full_threshold"
158
+ CONF_RX_TIMEOUT = "rx_timeout"
177
159
 
178
160
  UARTDirection = uart_ns.enum("UARTDirection")
179
161
  UART_DIRECTIONS = {
@@ -241,8 +223,17 @@ CONFIG_SCHEMA = cv.All(
241
223
  cv.Required(CONF_BAUD_RATE): cv.int_range(min=1),
242
224
  cv.Optional(CONF_TX_PIN): pins.internal_gpio_output_pin_schema,
243
225
  cv.Optional(CONF_RX_PIN): validate_rx_pin,
226
+ cv.Optional(CONF_FLOW_CONTROL_PIN): cv.All(
227
+ cv.only_on_esp32, pins.internal_gpio_output_pin_schema
228
+ ),
244
229
  cv.Optional(CONF_PORT): cv.All(validate_port, cv.only_on(PLATFORM_HOST)),
245
230
  cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes,
231
+ cv.Optional(CONF_RX_FULL_THRESHOLD): cv.All(
232
+ cv.only_on_esp32, cv.validate_bytes, cv.int_range(min=1, max=120)
233
+ ),
234
+ cv.SplitDefault(CONF_RX_TIMEOUT, esp32=2): cv.All(
235
+ cv.only_on_esp32, cv.validate_bytes, cv.int_range(min=0, max=92)
236
+ ),
246
237
  cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True),
247
238
  cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8),
248
239
  cv.Optional(CONF_PARITY, default="NONE"): cv.enum(
@@ -255,7 +246,6 @@ CONFIG_SCHEMA = cv.All(
255
246
  }
256
247
  ).extend(cv.COMPONENT_SCHEMA),
257
248
  cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN, CONF_PORT),
258
- validate_invert_esp32,
259
249
  validate_host_config,
260
250
  )
261
251
 
@@ -298,9 +288,27 @@ async def to_code(config):
298
288
  if CONF_RX_PIN in config:
299
289
  rx_pin = await cg.gpio_pin_expression(config[CONF_RX_PIN])
300
290
  cg.add(var.set_rx_pin(rx_pin))
291
+ if CONF_FLOW_CONTROL_PIN in config:
292
+ flow_control_pin = await cg.gpio_pin_expression(config[CONF_FLOW_CONTROL_PIN])
293
+ cg.add(var.set_flow_control_pin(flow_control_pin))
301
294
  if CONF_PORT in config:
302
295
  cg.add(var.set_name(config[CONF_PORT]))
303
296
  cg.add(var.set_rx_buffer_size(config[CONF_RX_BUFFER_SIZE]))
297
+ if CORE.is_esp32:
298
+ if CONF_RX_FULL_THRESHOLD not in config:
299
+ # Calculate rx_full_threshold to be 10ms
300
+ bytelength = config[CONF_DATA_BITS] + config[CONF_STOP_BITS] + 1
301
+ if config[CONF_PARITY] != "NONE":
302
+ bytelength += 1
303
+ config[CONF_RX_FULL_THRESHOLD] = max(
304
+ 1,
305
+ min(
306
+ 120,
307
+ math.floor((config[CONF_BAUD_RATE] / (bytelength * 1000 / 10)) - 1),
308
+ ),
309
+ )
310
+ cg.add(var.set_rx_full_threshold(config[CONF_RX_FULL_THRESHOLD]))
311
+ cg.add(var.set_rx_timeout(config[CONF_RX_TIMEOUT]))
304
312
  cg.add(var.set_stop_bits(config[CONF_STOP_BITS]))
305
313
  cg.add(var.set_data_bits(config[CONF_DATA_BITS]))
306
314
  cg.add(var.set_parity(config[CONF_PARITY]))
@@ -339,7 +347,7 @@ def final_validate_device_schema(
339
347
 
340
348
  def validate_pin(opt, device):
341
349
  def validator(value):
342
- if opt in device:
350
+ if opt in device and not CORE.testing_mode:
343
351
  raise cv.Invalid(
344
352
  f"The uart {opt} is used both by {name} and {device[opt]}, "
345
353
  f"but can only be used by one. Please create a new uart bus for {name}."
@@ -444,8 +452,10 @@ async def uart_write_to_code(config, action_id, template_arg, args):
444
452
 
445
453
  FILTER_SOURCE_FILES = filter_source_files_from_platform(
446
454
  {
447
- "uart_component_esp32_arduino.cpp": {PlatformFramework.ESP32_ARDUINO},
448
- "uart_component_esp_idf.cpp": {PlatformFramework.ESP32_IDF},
455
+ "uart_component_esp_idf.cpp": {
456
+ PlatformFramework.ESP32_IDF,
457
+ PlatformFramework.ESP32_ARDUINO,
458
+ },
449
459
  "uart_component_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO},
450
460
  "uart_component_host.cpp": {PlatformFramework.HOST_NATIVE},
451
461
  "uart_component_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO},
@@ -18,6 +18,12 @@ class UARTDevice {
18
18
 
19
19
  void write_byte(uint8_t data) { this->parent_->write_byte(data); }
20
20
 
21
+ void set_rx_full_threshold(size_t rx_full_threshold) { this->parent_->set_rx_full_threshold(rx_full_threshold); }
22
+ void set_rx_full_threshold_ms(size_t time) { this->parent_->set_rx_full_threshold_ms(time); }
23
+ size_t get_rx_full_threshold() { return this->parent_->get_rx_full_threshold(); }
24
+ void set_rx_timeout(size_t rx_timeout) { this->parent_->set_rx_timeout(rx_timeout); }
25
+ size_t get_rx_timeout() { return this->parent_->get_rx_timeout(); }
26
+
21
27
  void write_array(const uint8_t *data, size_t len) { this->parent_->write_array(data, len); }
22
28
  void write_array(const std::vector<uint8_t> &data) { this->parent_->write_array(data); }
23
29
  template<size_t N> void write_array(const std::array<uint8_t, N> &data) {
@@ -20,5 +20,13 @@ bool UARTComponent::check_read_timeout_(size_t len) {
20
20
  return true;
21
21
  }
22
22
 
23
+ void UARTComponent::set_rx_full_threshold_ms(uint8_t time) {
24
+ uint8_t bytelength = this->data_bits_ + this->stop_bits_ + 1;
25
+ if (this->parity_ != UARTParityOptions::UART_CONFIG_PARITY_NONE)
26
+ bytelength += 1;
27
+ int32_t val = clamp<int32_t>((this->baud_rate_ / (bytelength * 1000 / time)) - 1, 1, 120);
28
+ this->set_rx_full_threshold(val);
29
+ }
30
+
23
31
  } // namespace uart
24
32
  } // namespace esphome
@@ -6,6 +6,7 @@
6
6
  #include "esphome/core/component.h"
7
7
  #include "esphome/core/hal.h"
8
8
  #include "esphome/core/log.h"
9
+ #include "esphome/core/helpers.h"
9
10
  #ifdef USE_UART_DEBUGGER
10
11
  #include "esphome/core/automation.h"
11
12
  #endif
@@ -82,6 +83,10 @@ class UARTComponent {
82
83
  // @param rx_pin Pointer to the internal GPIO pin used for reception.
83
84
  void set_rx_pin(InternalGPIOPin *rx_pin) { this->rx_pin_ = rx_pin; }
84
85
 
86
+ // Sets the flow control pin for the UART bus.
87
+ // @param flow_control_pin Pointer to the internal GPIO pin used for flow control.
88
+ void set_flow_control_pin(InternalGPIOPin *flow_control_pin) { this->flow_control_pin_ = flow_control_pin; }
89
+
85
90
  // Sets the size of the RX buffer.
86
91
  // @param rx_buffer_size Size of the RX buffer in bytes.
87
92
  void set_rx_buffer_size(size_t rx_buffer_size) { this->rx_buffer_size_ = rx_buffer_size; }
@@ -90,6 +95,26 @@ class UARTComponent {
90
95
  // @return Size of the RX buffer in bytes.
91
96
  size_t get_rx_buffer_size() { return this->rx_buffer_size_; }
92
97
 
98
+ // Sets the RX FIFO full interrupt threshold.
99
+ // @param rx_full_threshold RX full interrupt threshold in bytes.
100
+ virtual void set_rx_full_threshold(size_t rx_full_threshold) {}
101
+
102
+ // Sets the RX FIFO full interrupt threshold.
103
+ // @param time RX full interrupt threshold in ms.
104
+ void set_rx_full_threshold_ms(uint8_t time);
105
+
106
+ // Gets the RX FIFO full interrupt threshold.
107
+ // @return RX full interrupt threshold in bytes.
108
+ size_t get_rx_full_threshold() { return this->rx_full_threshold_; }
109
+
110
+ // Sets the RX timeout interrupt threshold.
111
+ // @param rx_timeout RX timeout interrupt threshold (unit: time of sending one byte).
112
+ virtual void set_rx_timeout(size_t rx_timeout) {}
113
+
114
+ // Gets the RX timeout interrupt threshold.
115
+ // @return RX timeout interrupt threshold (unit: time of sending one byte).
116
+ size_t get_rx_timeout() { return this->rx_timeout_; }
117
+
93
118
  // Sets the number of stop bits used in UART communication.
94
119
  // @param stop_bits Number of stop bits.
95
120
  void set_stop_bits(uint8_t stop_bits) { this->stop_bits_ = stop_bits; }
@@ -161,7 +186,10 @@ class UARTComponent {
161
186
 
162
187
  InternalGPIOPin *tx_pin_;
163
188
  InternalGPIOPin *rx_pin_;
189
+ InternalGPIOPin *flow_control_pin_;
164
190
  size_t rx_buffer_size_;
191
+ size_t rx_full_threshold_{1};
192
+ size_t rx_timeout_{0};
165
193
  uint32_t baud_rate_;
166
194
  uint8_t stop_bits_;
167
195
  uint8_t data_bits_;
@@ -1,4 +1,4 @@
1
- #ifdef USE_ESP_IDF
1
+ #ifdef USE_ESP32
2
2
 
3
3
  #include "uart_component_esp_idf.h"
4
4
  #include <cinttypes>
@@ -90,6 +90,12 @@ void IDFUARTComponent::setup() {
90
90
 
91
91
  xSemaphoreTake(this->lock_, portMAX_DELAY);
92
92
 
93
+ this->load_settings(false);
94
+
95
+ xSemaphoreGive(this->lock_);
96
+ }
97
+
98
+ void IDFUARTComponent::load_settings(bool dump_config) {
93
99
  uart_config_t uart_config = this->get_config_();
94
100
  esp_err_t err = uart_param_config(this->uart_num_, &uart_config);
95
101
  if (err != ESP_OK) {
@@ -100,6 +106,7 @@ void IDFUARTComponent::setup() {
100
106
 
101
107
  int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1;
102
108
  int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1;
109
+ int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1;
103
110
 
104
111
  uint32_t invert = 0;
105
112
  if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted())
@@ -114,13 +121,21 @@ void IDFUARTComponent::setup() {
114
121
  return;
115
122
  }
116
123
 
117
- err = uart_set_pin(this->uart_num_, tx, rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
124
+ err = uart_set_pin(this->uart_num_, tx, rx, flow_control, UART_PIN_NO_CHANGE);
118
125
  if (err != ESP_OK) {
119
126
  ESP_LOGW(TAG, "uart_set_pin failed: %s", esp_err_to_name(err));
120
127
  this->mark_failed();
121
128
  return;
122
129
  }
123
130
 
131
+ if (uart_is_driver_installed(this->uart_num_)) {
132
+ uart_driver_delete(this->uart_num_);
133
+ if (err != ESP_OK) {
134
+ ESP_LOGW(TAG, "uart_driver_delete failed: %s", esp_err_to_name(err));
135
+ this->mark_failed();
136
+ return;
137
+ }
138
+ }
124
139
  err = uart_driver_install(this->uart_num_, /* UART RX ring buffer size. */ this->rx_buffer_size_,
125
140
  /* UART TX ring buffer size. If set to zero, driver will not use TX buffer, TX function will
126
141
  block task until all data have been sent out.*/
@@ -133,17 +148,29 @@ void IDFUARTComponent::setup() {
133
148
  return;
134
149
  }
135
150
 
136
- xSemaphoreGive(this->lock_);
137
- }
151
+ err = uart_set_rx_full_threshold(this->uart_num_, this->rx_full_threshold_);
152
+ if (err != ESP_OK) {
153
+ ESP_LOGW(TAG, "uart_set_rx_full_threshold failed: %s", esp_err_to_name(err));
154
+ this->mark_failed();
155
+ return;
156
+ }
138
157
 
139
- void IDFUARTComponent::load_settings(bool dump_config) {
140
- uart_config_t uart_config = this->get_config_();
141
- esp_err_t err = uart_param_config(this->uart_num_, &uart_config);
158
+ err = uart_set_rx_timeout(this->uart_num_, this->rx_timeout_);
142
159
  if (err != ESP_OK) {
143
- ESP_LOGW(TAG, "uart_param_config failed: %s", esp_err_to_name(err));
160
+ ESP_LOGW(TAG, "uart_set_rx_timeout failed: %s", esp_err_to_name(err));
161
+ this->mark_failed();
162
+ return;
163
+ }
164
+
165
+ auto mode = this->flow_control_pin_ != nullptr ? UART_MODE_RS485_HALF_DUPLEX : UART_MODE_UART;
166
+ err = uart_set_mode(this->uart_num_, mode);
167
+ if (err != ESP_OK) {
168
+ ESP_LOGW(TAG, "uart_set_mode failed: %s", esp_err_to_name(err));
144
169
  this->mark_failed();
145
170
  return;
146
- } else if (dump_config) {
171
+ }
172
+
173
+ if (dump_config) {
147
174
  ESP_LOGCONFIG(TAG, "UART %u was reloaded.", this->uart_num_);
148
175
  this->dump_config();
149
176
  }
@@ -153,8 +180,13 @@ void IDFUARTComponent::dump_config() {
153
180
  ESP_LOGCONFIG(TAG, "UART Bus %u:", this->uart_num_);
154
181
  LOG_PIN(" TX Pin: ", tx_pin_);
155
182
  LOG_PIN(" RX Pin: ", rx_pin_);
183
+ LOG_PIN(" Flow Control Pin: ", flow_control_pin_);
156
184
  if (this->rx_pin_ != nullptr) {
157
- ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_);
185
+ ESP_LOGCONFIG(TAG,
186
+ " RX Buffer Size: %u\n"
187
+ " RX Full Threshold: %u\n"
188
+ " RX Timeout: %u",
189
+ this->rx_buffer_size_, this->rx_full_threshold_, this->rx_timeout_);
158
190
  }
159
191
  ESP_LOGCONFIG(TAG,
160
192
  " Baud Rate: %" PRIu32 " baud\n"
@@ -165,6 +197,28 @@ void IDFUARTComponent::dump_config() {
165
197
  this->check_logger_conflict();
166
198
  }
167
199
 
200
+ void IDFUARTComponent::set_rx_full_threshold(size_t rx_full_threshold) {
201
+ if (this->is_ready()) {
202
+ esp_err_t err = uart_set_rx_full_threshold(this->uart_num_, rx_full_threshold);
203
+ if (err != ESP_OK) {
204
+ ESP_LOGW(TAG, "uart_set_rx_full_threshold failed: %s", esp_err_to_name(err));
205
+ return;
206
+ }
207
+ }
208
+ this->rx_full_threshold_ = rx_full_threshold;
209
+ }
210
+
211
+ void IDFUARTComponent::set_rx_timeout(size_t rx_timeout) {
212
+ if (this->is_ready()) {
213
+ esp_err_t err = uart_set_rx_timeout(this->uart_num_, rx_timeout);
214
+ if (err != ESP_OK) {
215
+ ESP_LOGW(TAG, "uart_set_rx_timeout failed: %s", esp_err_to_name(err));
216
+ return;
217
+ }
218
+ }
219
+ this->rx_timeout_ = rx_timeout;
220
+ }
221
+
168
222
  void IDFUARTComponent::write_array(const uint8_t *data, size_t len) {
169
223
  xSemaphoreTake(this->lock_, portMAX_DELAY);
170
224
  uart_write_bytes(this->uart_num_, data, len);
@@ -1,6 +1,6 @@
1
1
  #pragma once
2
2
 
3
- #ifdef USE_ESP_IDF
3
+ #ifdef USE_ESP32
4
4
 
5
5
  #include <driver/uart.h>
6
6
  #include "esphome/core/component.h"
@@ -15,6 +15,9 @@ class IDFUARTComponent : public UARTComponent, public Component {
15
15
  void dump_config() override;
16
16
  float get_setup_priority() const override { return setup_priority::BUS; }
17
17
 
18
+ void set_rx_full_threshold(size_t rx_full_threshold) override;
19
+ void set_rx_timeout(size_t rx_timeout) override;
20
+
18
21
  void write_array(const uint8_t *data, size_t len) override;
19
22
 
20
23
  bool peek_byte(uint8_t *data) override;
@@ -55,4 +58,4 @@ class IDFUARTComponent : public UARTComponent, public Component {
55
58
  } // namespace uart
56
59
  } // namespace esphome
57
60
 
58
- #endif // USE_ESP_IDF
61
+ #endif // USE_ESP32
@@ -58,7 +58,7 @@ void UponorSmatrixClimate::control(const climate::ClimateCall &call) {
58
58
  }
59
59
 
60
60
  void UponorSmatrixClimate::on_device_data(const UponorSmatrixData *data, size_t data_len) {
61
- for (int i = 0; i < data_len; i++) {
61
+ for (size_t i = 0; i < data_len; i++) {
62
62
  switch (data[i].id) {
63
63
  case UPONOR_ID_TARGET_TEMP_MIN:
64
64
  this->min_temperature_ = raw_to_celsius(data[i].value);
@@ -18,7 +18,7 @@ void UponorSmatrixSensor::dump_config() {
18
18
  }
19
19
 
20
20
  void UponorSmatrixSensor::on_device_data(const UponorSmatrixData *data, size_t data_len) {
21
- for (int i = 0; i < data_len; i++) {
21
+ for (size_t i = 0; i < data_len; i++) {
22
22
  switch (data[i].id) {
23
23
  case UPONOR_ID_ROOM_TEMP:
24
24
  if (this->temperature_sensor_ != nullptr)