esphome 2025.4.2__py3-none-any.whl → 2025.5.0b3__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 (440) hide show
  1. esphome/__main__.py +16 -14
  2. esphome/components/ac_dimmer/ac_dimmer.cpp +3 -2
  3. esphome/components/adc/__init__.py +51 -34
  4. esphome/components/airthings_wave_base/__init__.py +1 -1
  5. esphome/components/alarm_control_panel/__init__.py +37 -2
  6. esphome/components/am43/cover/__init__.py +4 -5
  7. esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +6 -4
  8. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +4 -5
  9. esphome/components/analog_threshold/binary_sensor.py +10 -8
  10. esphome/components/anova/climate.py +4 -5
  11. esphome/components/api/__init__.py +25 -8
  12. esphome/components/api/api_connection.cpp +81 -13
  13. esphome/components/api/api_connection.h +13 -1
  14. esphome/components/api/api_frame_helper.cpp +232 -177
  15. esphome/components/api/api_frame_helper.h +61 -8
  16. esphome/components/api/api_noise_context.h +13 -4
  17. esphome/components/api/api_pb2.cpp +1422 -1
  18. esphome/components/api/api_pb2.h +255 -1
  19. esphome/components/api/api_pb2_service.cpp +162 -49
  20. esphome/components/api/api_pb2_service.h +90 -51
  21. esphome/components/api/api_pb2_size.h +361 -0
  22. esphome/components/api/api_server.cpp +110 -34
  23. esphome/components/api/api_server.h +8 -0
  24. esphome/components/api/proto.h +86 -17
  25. esphome/components/as7341/as7341.h +1 -1
  26. esphome/components/atm90e32/__init__.py +1 -0
  27. esphome/components/atm90e32/atm90e32.cpp +576 -199
  28. esphome/components/atm90e32/atm90e32.h +128 -31
  29. esphome/components/atm90e32/atm90e32_reg.h +4 -2
  30. esphome/components/atm90e32/button/__init__.py +62 -10
  31. esphome/components/atm90e32/button/atm90e32_button.cpp +63 -4
  32. esphome/components/atm90e32/button/atm90e32_button.h +36 -4
  33. esphome/components/atm90e32/number/__init__.py +130 -0
  34. esphome/components/atm90e32/number/atm90e32_number.h +16 -0
  35. esphome/components/atm90e32/sensor.py +21 -4
  36. esphome/components/atm90e32/text_sensor/__init__.py +48 -0
  37. esphome/components/audio/__init__.py +96 -49
  38. esphome/components/audio/audio.h +48 -0
  39. esphome/components/audio/audio_decoder.cpp +1 -1
  40. esphome/components/audio/audio_resampler.cpp +2 -0
  41. esphome/components/audio/audio_resampler.h +1 -0
  42. esphome/components/ballu/climate.py +2 -9
  43. esphome/components/bang_bang/climate.py +5 -6
  44. esphome/components/bedjet/bedjet_hub.cpp +1 -0
  45. esphome/components/bedjet/climate/__init__.py +3 -8
  46. esphome/components/bedjet/fan/__init__.py +2 -11
  47. esphome/components/binary/fan/__init__.py +13 -16
  48. esphome/components/binary_sensor/__init__.py +13 -10
  49. esphome/components/bl0906/constants.h +16 -16
  50. esphome/components/ble_client/text_sensor/__init__.py +3 -5
  51. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
  52. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +136 -21
  53. esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
  54. esphome/components/button/__init__.py +11 -8
  55. esphome/components/canbus/canbus.cpp +3 -0
  56. esphome/components/canbus/canbus.h +16 -0
  57. esphome/components/ccs811/sensor.py +9 -6
  58. esphome/components/climate/__init__.py +35 -2
  59. esphome/components/climate/climate_mode.h +1 -1
  60. esphome/components/climate/climate_traits.h +63 -57
  61. esphome/components/climate_ir/__init__.py +57 -17
  62. esphome/components/climate_ir_lg/climate.py +2 -5
  63. esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
  64. esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
  65. esphome/components/color/__init__.py +2 -0
  66. esphome/components/const/__init__.py +5 -0
  67. esphome/components/coolix/climate.py +2 -9
  68. esphome/components/copy/cover/__init__.py +10 -9
  69. esphome/components/copy/fan/__init__.py +11 -9
  70. esphome/components/copy/lock/__init__.py +11 -9
  71. esphome/components/copy/text/__init__.py +9 -6
  72. esphome/components/cover/__init__.py +37 -2
  73. esphome/components/cse7766/cse7766.cpp +2 -1
  74. esphome/components/cst226/binary_sensor/__init__.py +28 -0
  75. esphome/components/cst226/binary_sensor/cs226_button.h +22 -0
  76. esphome/components/cst226/binary_sensor/cstt6_button.cpp +19 -0
  77. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +27 -5
  78. esphome/components/cst226/touchscreen/cst226_touchscreen.h +10 -10
  79. esphome/components/current_based/cover.py +37 -36
  80. esphome/components/current_based/current_based_cover.cpp +2 -1
  81. esphome/components/daikin/climate.py +2 -9
  82. esphome/components/daikin/daikin.cpp +15 -9
  83. esphome/components/daikin/daikin.h +5 -5
  84. esphome/components/daikin_arc/climate.py +2 -7
  85. esphome/components/daikin_brc/climate.py +3 -5
  86. esphome/components/dallas_temp/dallas_temp.cpp +17 -24
  87. esphome/components/dallas_temp/dallas_temp.h +0 -1
  88. esphome/components/daly_bms/daly_bms.cpp +2 -1
  89. esphome/components/debug/debug_component.cpp +6 -1
  90. esphome/components/debug/debug_component.h +6 -0
  91. esphome/components/debug/debug_esp32.cpp +109 -254
  92. esphome/components/debug/sensor.py +14 -0
  93. esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
  94. esphome/components/delonghi/climate.py +2 -9
  95. esphome/components/demo/__init__.py +18 -20
  96. esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
  97. esphome/components/dps310/sensor.py +6 -6
  98. esphome/components/ee895/sensor.py +9 -9
  99. esphome/components/emmeti/climate.py +2 -9
  100. esphome/components/endstop/cover.py +17 -16
  101. esphome/components/endstop/endstop_cover.cpp +2 -1
  102. esphome/components/ens160_base/__init__.py +12 -9
  103. esphome/components/esp32/__init__.py +60 -3
  104. esphome/components/esp32/core.cpp +11 -5
  105. esphome/components/esp32/gpio.cpp +86 -24
  106. esphome/components/esp32/gpio.py +15 -16
  107. esphome/components/esp32/gpio_esp32.py +1 -2
  108. esphome/components/esp32/gpio_esp32_c2.py +1 -1
  109. esphome/components/esp32/gpio_esp32_c3.py +1 -1
  110. esphome/components/esp32/gpio_esp32_c6.py +1 -1
  111. esphome/components/esp32/gpio_esp32_h2.py +1 -1
  112. esphome/components/esp32_ble/ble.cpp +1 -0
  113. esphome/components/esp32_ble/ble.h +5 -3
  114. esphome/components/esp32_ble/ble_advertising.cpp +2 -1
  115. esphome/components/esp32_ble/ble_advertising.h +1 -0
  116. esphome/components/esp32_ble_server/__init__.py +3 -0
  117. esphome/components/esp32_ble_tracker/__init__.py +7 -1
  118. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
  119. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
  120. esphome/components/esp32_camera/esp32_camera.cpp +2 -1
  121. esphome/components/esp32_camera/esp32_camera.h +1 -1
  122. esphome/components/esp32_can/esp32_can.cpp +1 -1
  123. esphome/components/esp32_improv/esp32_improv_component.cpp +1 -1
  124. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  125. esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
  126. esphome/components/esp32_rmt_led_strip/light.py +9 -1
  127. esphome/components/esp32_touch/esp32_touch.cpp +1 -1
  128. esphome/components/esp8266/gpio.cpp +69 -8
  129. esphome/components/ethernet/ethernet_component.cpp +1 -1
  130. esphome/components/event/__init__.py +13 -10
  131. esphome/components/factory_reset/switch/__init__.py +7 -21
  132. esphome/components/fan/__init__.py +52 -5
  133. esphome/components/fastled_base/__init__.py +1 -4
  134. esphome/components/fastled_base/fastled_light.cpp +1 -1
  135. esphome/components/feedback/cover.py +38 -33
  136. esphome/components/feedback/feedback_cover.cpp +2 -1
  137. esphome/components/fujitsu_general/climate.py +2 -9
  138. esphome/components/gcja5/gcja5.cpp +2 -1
  139. esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
  140. esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
  141. esphome/components/gpio_expander/cached_gpio.h +22 -7
  142. esphome/components/gps/__init__.py +47 -17
  143. esphome/components/gps/gps.cpp +42 -23
  144. esphome/components/gps/gps.h +17 -13
  145. esphome/components/graph/__init__.py +1 -2
  146. esphome/components/gree/climate.py +4 -6
  147. esphome/components/gree/gree.cpp +16 -2
  148. esphome/components/gree/gree.h +2 -2
  149. esphome/components/growatt_solar/growatt_solar.cpp +2 -1
  150. esphome/components/haier/climate.py +37 -34
  151. esphome/components/hbridge/fan/__init__.py +19 -17
  152. esphome/components/he60r/cover.py +4 -5
  153. esphome/components/heatpumpir/climate.py +3 -6
  154. esphome/components/hitachi_ac344/climate.py +2 -9
  155. esphome/components/hitachi_ac424/climate.py +2 -9
  156. esphome/components/hm3301/hm3301.h +1 -1
  157. esphome/components/hte501/sensor.py +6 -6
  158. esphome/components/http_request/__init__.py +39 -6
  159. esphome/components/http_request/http_request.cpp +20 -0
  160. esphome/components/http_request/http_request.h +57 -15
  161. esphome/components/http_request/http_request_arduino.cpp +22 -6
  162. esphome/components/http_request/http_request_arduino.h +4 -3
  163. esphome/components/http_request/http_request_host.cpp +141 -0
  164. esphome/components/http_request/http_request_host.h +37 -0
  165. esphome/components/http_request/http_request_idf.cpp +35 -3
  166. esphome/components/http_request/http_request_idf.h +10 -3
  167. esphome/components/http_request/httplib.h +9691 -0
  168. esphome/components/http_request/update/__init__.py +11 -8
  169. esphome/components/hyt271/sensor.py +6 -6
  170. esphome/components/i2c/i2c.h +4 -0
  171. esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
  172. esphome/components/i2s_audio/__init__.py +131 -22
  173. esphome/components/i2s_audio/i2s_audio.h +44 -4
  174. esphome/components/i2s_audio/media_player/__init__.py +19 -9
  175. esphome/components/i2s_audio/microphone/__init__.py +63 -5
  176. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
  177. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
  178. esphome/components/i2s_audio/speaker/__init__.py +31 -5
  179. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
  180. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
  181. esphome/components/ili9xxx/ili9xxx_init.h +1 -1
  182. esphome/components/image/__init__.py +37 -17
  183. esphome/components/image/image.cpp +25 -8
  184. esphome/components/internal_temperature/internal_temperature.cpp +6 -4
  185. esphome/components/key_collector/__init__.py +35 -0
  186. esphome/components/key_collector/key_collector.cpp +8 -0
  187. esphome/components/key_collector/key_collector.h +10 -0
  188. esphome/components/kuntze/kuntze.cpp +2 -1
  189. esphome/components/ld2410/ld2410.h +1 -1
  190. esphome/components/ld2450/ld2450.h +1 -1
  191. esphome/components/light/__init__.py +57 -0
  192. esphome/components/lock/__init__.py +51 -4
  193. esphome/components/lock/automation.h +2 -13
  194. esphome/components/logger/__init__.py +22 -0
  195. esphome/components/logger/logger.cpp +154 -103
  196. esphome/components/logger/logger.h +211 -36
  197. esphome/components/logger/task_log_buffer.cpp +138 -0
  198. esphome/components/logger/task_log_buffer.h +69 -0
  199. esphome/components/lvgl/__init__.py +13 -5
  200. esphome/components/lvgl/automation.py +50 -1
  201. esphome/components/lvgl/defines.py +0 -1
  202. esphome/components/lvgl/lvgl_esphome.cpp +5 -1
  203. esphome/components/lvgl/text/__init__.py +1 -2
  204. esphome/components/mapping/__init__.py +134 -0
  205. esphome/components/matrix_keypad/matrix_keypad.cpp +2 -1
  206. esphome/components/max7219digit/max7219digit.cpp +28 -27
  207. esphome/components/mdns/__init__.py +11 -5
  208. esphome/components/mdns/mdns_component.cpp +11 -5
  209. esphome/components/mdns/mdns_component.h +3 -2
  210. esphome/components/mdns/mdns_esp32.cpp +4 -3
  211. esphome/components/mdns/mdns_esp8266.cpp +4 -2
  212. esphome/components/mdns/mdns_libretiny.cpp +4 -2
  213. esphome/components/mdns/mdns_rp2040.cpp +4 -2
  214. esphome/components/media_player/__init__.py +33 -1
  215. esphome/components/mhz19/sensor.py +11 -7
  216. esphome/components/micro_wake_word/__init__.py +99 -31
  217. esphome/components/micro_wake_word/automation.h +54 -0
  218. esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
  219. esphome/components/micro_wake_word/micro_wake_word.h +58 -105
  220. esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
  221. esphome/components/micro_wake_word/streaming_model.cpp +158 -41
  222. esphome/components/micro_wake_word/streaming_model.h +85 -13
  223. esphome/components/microphone/__init__.py +139 -9
  224. esphome/components/microphone/automation.h +14 -2
  225. esphome/components/microphone/microphone.cpp +21 -0
  226. esphome/components/microphone/microphone.h +14 -5
  227. esphome/components/microphone/microphone_source.cpp +95 -0
  228. esphome/components/microphone/microphone_source.h +80 -0
  229. esphome/components/mics_4514/sensor.py +25 -14
  230. esphome/components/midea/climate.py +3 -4
  231. esphome/components/midea_ir/climate.py +3 -5
  232. esphome/components/mipi_spi/__init__.py +15 -0
  233. esphome/components/mipi_spi/display.py +474 -0
  234. esphome/components/mipi_spi/mipi_spi.cpp +481 -0
  235. esphome/components/mipi_spi/mipi_spi.h +171 -0
  236. esphome/components/mipi_spi/models/__init__.py +65 -0
  237. esphome/components/mipi_spi/models/amoled.py +72 -0
  238. esphome/components/mipi_spi/models/commands.py +82 -0
  239. esphome/components/mipi_spi/models/cyd.py +10 -0
  240. esphome/components/mipi_spi/models/ili.py +749 -0
  241. esphome/components/mipi_spi/models/jc.py +260 -0
  242. esphome/components/mipi_spi/models/lanbon.py +15 -0
  243. esphome/components/mipi_spi/models/lilygo.py +60 -0
  244. esphome/components/mipi_spi/models/waveshare.py +139 -0
  245. esphome/components/mitsubishi/climate.py +2 -5
  246. esphome/components/mitsubishi/mitsubishi.cpp +9 -9
  247. esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
  248. esphome/components/mixer/speaker/mixer_speaker.h +1 -3
  249. esphome/components/mlx90393/sensor.py +5 -0
  250. esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
  251. esphome/components/mlx90393/sensor_mlx90393.h +21 -4
  252. esphome/components/modbus/modbus.cpp +2 -1
  253. esphome/components/mqtt/__init__.py +1 -1
  254. esphome/components/mqtt/mqtt_client.cpp +6 -2
  255. esphome/components/mqtt/mqtt_const.h +4 -0
  256. esphome/components/mqtt/mqtt_fan.cpp +39 -0
  257. esphome/components/mqtt/mqtt_fan.h +2 -0
  258. esphome/components/ms5611/sensor.py +6 -6
  259. esphome/components/ms8607/sensor.py +3 -3
  260. esphome/components/network/__init__.py +1 -1
  261. esphome/components/nextion/base_component.py +17 -16
  262. esphome/components/nextion/display.py +11 -2
  263. esphome/components/nextion/nextion.cpp +39 -1
  264. esphome/components/nextion/nextion.h +50 -0
  265. esphome/components/noblex/climate.py +2 -9
  266. esphome/components/number/__init__.py +12 -9
  267. esphome/components/one_wire/one_wire_bus.cpp +14 -10
  268. esphome/components/one_wire/one_wire_bus.h +14 -8
  269. esphome/components/online_image/bmp_image.cpp +48 -11
  270. esphome/components/online_image/bmp_image.h +2 -0
  271. esphome/components/opentherm/binary_sensor/__init__.py +2 -4
  272. esphome/components/opentherm/number/__init__.py +11 -20
  273. esphome/components/opentherm/sensor/__init__.py +3 -3
  274. esphome/components/opentherm/switch/__init__.py +3 -5
  275. esphome/components/output/lock/__init__.py +11 -9
  276. esphome/components/packages/__init__.py +33 -31
  277. esphome/components/packet_transport/__init__.py +201 -0
  278. esphome/components/packet_transport/binary_sensor.py +19 -0
  279. esphome/components/packet_transport/packet_transport.cpp +534 -0
  280. esphome/components/packet_transport/packet_transport.h +154 -0
  281. esphome/components/packet_transport/sensor.py +19 -0
  282. esphome/components/pca9685/pca9685_output.cpp +2 -1
  283. esphome/components/pid/climate.py +2 -4
  284. esphome/components/pm2005/__init__.py +1 -0
  285. esphome/components/pm2005/pm2005.cpp +123 -0
  286. esphome/components/pm2005/pm2005.h +46 -0
  287. esphome/components/pm2005/sensor.py +86 -0
  288. esphome/components/pmsa003i/pmsa003i.cpp +43 -16
  289. esphome/components/pmsa003i/pmsa003i.h +25 -25
  290. esphome/components/pmsx003/pmsx003.cpp +195 -230
  291. esphome/components/pmsx003/pmsx003.h +51 -33
  292. esphome/components/pmsx003/sensor.py +21 -11
  293. esphome/components/pn7150/pn7150.h +2 -2
  294. esphome/components/pn7160/pn7160.h +2 -2
  295. esphome/components/prometheus/prometheus_handler.cpp +174 -0
  296. esphome/components/prometheus/prometheus_handler.h +17 -0
  297. esphome/components/psram/__init__.py +7 -5
  298. esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
  299. esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
  300. esphome/components/pzem004t/pzem004t.cpp +2 -1
  301. esphome/components/qspi_dbi/__init__.py +0 -1
  302. esphome/components/qspi_dbi/display.py +2 -1
  303. esphome/components/qspi_dbi/models.py +1 -2
  304. esphome/components/remote_base/__init__.py +91 -0
  305. esphome/components/remote_base/beo4_protocol.cpp +153 -0
  306. esphome/components/remote_base/beo4_protocol.h +43 -0
  307. esphome/components/remote_base/gobox_protocol.cpp +131 -0
  308. esphome/components/remote_base/gobox_protocol.h +54 -0
  309. esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
  310. esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
  311. esphome/components/resampler/speaker/resampler_speaker.h +1 -1
  312. esphome/components/rf_bridge/rf_bridge.cpp +2 -1
  313. esphome/components/scd30/sensor.py +2 -3
  314. esphome/components/scd4x/sensor.py +4 -5
  315. esphome/components/sdp3x/sensor.py +2 -1
  316. esphome/components/sds011/sds011.cpp +2 -1
  317. esphome/components/select/__init__.py +19 -20
  318. esphome/components/sen5x/sen5x.cpp +55 -36
  319. esphome/components/sen5x/sensor.py +1 -1
  320. esphome/components/senseair/sensor.py +3 -3
  321. esphome/components/sensor/__init__.py +158 -14
  322. esphome/components/sensor/filter.cpp +23 -0
  323. esphome/components/sensor/filter.h +22 -0
  324. esphome/components/sgp30/sensor.py +14 -16
  325. esphome/components/sgp4x/sensor.py +1 -1
  326. esphome/components/sht4x/sht4x.cpp +43 -22
  327. esphome/components/sht4x/sht4x.h +1 -1
  328. esphome/components/shtcx/sensor.py +6 -6
  329. esphome/components/slow_pwm/slow_pwm_output.cpp +2 -1
  330. esphome/components/sml/text_sensor/__init__.py +4 -6
  331. esphome/components/sound_level/__init__.py +0 -0
  332. esphome/components/sound_level/sensor.py +97 -0
  333. esphome/components/sound_level/sound_level.cpp +194 -0
  334. esphome/components/sound_level/sound_level.h +73 -0
  335. esphome/components/speaker/media_player/__init__.py +4 -8
  336. esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
  337. esphome/components/speaker/media_player/speaker_media_player.h +0 -11
  338. esphome/components/speaker/speaker.h +4 -7
  339. esphome/components/speed/fan/__init__.py +17 -16
  340. esphome/components/spi/spi.h +11 -1
  341. esphome/components/sprinkler/__init__.py +18 -19
  342. esphome/components/sprinkler/sprinkler.cpp +6 -5
  343. esphome/components/switch/__init__.py +32 -42
  344. esphome/components/syslog/__init__.py +41 -0
  345. esphome/components/syslog/esphome_syslog.cpp +49 -0
  346. esphome/components/syslog/esphome_syslog.h +27 -0
  347. esphome/components/t6615/sensor.py +3 -3
  348. esphome/components/t6615/t6615.cpp +2 -1
  349. esphome/components/tca9555/tca9555.cpp +11 -6
  350. esphome/components/tcl112/climate.py +2 -9
  351. esphome/components/template/alarm_control_panel/__init__.py +7 -6
  352. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
  353. esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
  354. esphome/components/template/cover/__init__.py +27 -21
  355. esphome/components/template/fan/__init__.py +14 -12
  356. esphome/components/template/lock/__init__.py +20 -25
  357. esphome/components/template/lock/automation.h +18 -0
  358. esphome/components/template/text/__init__.py +4 -3
  359. esphome/components/template/valve/__init__.py +32 -21
  360. esphome/components/template/valve/automation.h +24 -0
  361. esphome/components/text/__init__.py +32 -1
  362. esphome/components/text_sensor/__init__.py +24 -29
  363. esphome/components/thermostat/climate.py +5 -5
  364. esphome/components/time_based/cover.py +17 -16
  365. esphome/components/time_based/time_based_cover.cpp +2 -1
  366. esphome/components/tm1638/switch/__init__.py +10 -7
  367. esphome/components/tormatic/cover.py +4 -5
  368. esphome/components/toshiba/climate.py +3 -5
  369. esphome/components/touchscreen/touchscreen.cpp +3 -1
  370. esphome/components/tuya/climate/__init__.py +5 -6
  371. esphome/components/tuya/cover/__init__.py +6 -11
  372. esphome/components/tuya/select/__init__.py +15 -5
  373. esphome/components/tuya/select/tuya_select.cpp +6 -1
  374. esphome/components/tuya/select/tuya_select.h +5 -1
  375. esphome/components/uart/packet_transport/__init__.py +20 -0
  376. esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
  377. esphome/components/uart/packet_transport/uart_transport.h +41 -0
  378. esphome/components/uart/switch/uart_switch.cpp +2 -1
  379. esphome/components/udp/__init__.py +126 -128
  380. esphome/components/udp/automation.h +40 -0
  381. esphome/components/udp/binary_sensor.py +3 -25
  382. esphome/components/udp/packet_transport/__init__.py +29 -0
  383. esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
  384. esphome/components/udp/packet_transport/udp_transport.h +28 -0
  385. esphome/components/udp/sensor.py +3 -25
  386. esphome/components/udp/udp_component.cpp +26 -470
  387. esphome/components/udp/udp_component.h +21 -128
  388. esphome/components/update/__init__.py +31 -1
  389. esphome/components/uponor_smatrix/climate/__init__.py +4 -9
  390. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +2 -1
  391. esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
  392. esphome/components/uptime/text_sensor/__init__.py +47 -7
  393. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
  394. esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
  395. esphome/components/valve/__init__.py +34 -3
  396. esphome/components/valve/automation.h +1 -19
  397. esphome/components/vl53l0x/sensor.py +11 -0
  398. esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
  399. esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
  400. esphome/components/voice_assistant/__init__.py +36 -10
  401. esphome/components/voice_assistant/voice_assistant.cpp +170 -144
  402. esphome/components/voice_assistant/voice_assistant.h +26 -25
  403. esphome/components/waveshare_epaper/display.py +6 -0
  404. esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
  405. esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
  406. esphome/components/whirlpool/climate.py +3 -5
  407. esphome/components/whynter/climate.py +3 -5
  408. esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
  409. esphome/components/yashima/climate.py +6 -6
  410. esphome/components/zhlt01/climate.py +2 -7
  411. esphome/config.py +13 -13
  412. esphome/config_validation.py +38 -58
  413. esphome/const.py +15 -1
  414. esphome/core/__init__.py +2 -0
  415. esphome/core/application.cpp +23 -10
  416. esphome/core/application.h +9 -1
  417. esphome/core/automation.h +4 -3
  418. esphome/core/component.cpp +28 -7
  419. esphome/core/component.h +10 -1
  420. esphome/core/defines.h +23 -17
  421. esphome/core/macros.h +4 -0
  422. esphome/core/scheduler.cpp +7 -1
  423. esphome/cpp_generator.py +6 -2
  424. esphome/dashboard/web_server.py +3 -3
  425. esphome/helpers.py +39 -0
  426. esphome/loader.py +4 -0
  427. esphome/log.py +15 -19
  428. esphome/mqtt.py +23 -10
  429. esphome/platformio_api.py +1 -1
  430. esphome/schema_extractors.py +0 -1
  431. esphome/voluptuous_schema.py +3 -1
  432. esphome/vscode.py +15 -0
  433. esphome/wizard.py +47 -37
  434. esphome/zeroconf.py +7 -3
  435. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/METADATA +10 -11
  436. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/RECORD +440 -380
  437. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/WHEEL +1 -1
  438. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/entry_points.txt +0 -0
  439. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/licenses/LICENSE +0 -0
  440. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,36 @@
1
+ #include "esphome/core/log.h"
2
+ #include "esphome/core/application.h"
3
+ #include "esphome/components/network/util.h"
4
+ #include "udp_transport.h"
5
+
6
+ namespace esphome {
7
+ namespace udp {
8
+
9
+ static const char *const TAG = "udp_transport";
10
+
11
+ bool UDPTransport::should_send() { return this->should_broadcast_ && network::is_connected(); }
12
+ void UDPTransport::setup() {
13
+ PacketTransport::setup();
14
+ this->should_broadcast_ = this->ping_pong_enable_;
15
+ #ifdef USE_SENSOR
16
+ this->should_broadcast_ |= !this->sensors_.empty();
17
+ #endif
18
+ #ifdef USE_BINARY_SENSOR
19
+ this->should_broadcast_ |= !this->binary_sensors_.empty();
20
+ #endif
21
+ if (this->should_broadcast_)
22
+ this->parent_->set_should_broadcast();
23
+ if (!this->providers_.empty() || this->is_encrypted_()) {
24
+ this->parent_->add_listener([this](std::vector<uint8_t> &buf) { this->process_(buf); });
25
+ }
26
+ }
27
+
28
+ void UDPTransport::update() {
29
+ PacketTransport::update();
30
+ this->updated_ = true;
31
+ this->resend_data_ = this->should_broadcast_;
32
+ }
33
+
34
+ void UDPTransport::send_packet(const std::vector<uint8_t> &buf) const { this->parent_->send_packet(buf); }
35
+ } // namespace udp
36
+ } // namespace esphome
@@ -0,0 +1,28 @@
1
+ #pragma once
2
+
3
+ #include "../udp_component.h"
4
+ #ifdef USE_NETWORK
5
+ #include "esphome/core/component.h"
6
+ #include "esphome/components/packet_transport/packet_transport.h"
7
+ #include <vector>
8
+
9
+ namespace esphome {
10
+ namespace udp {
11
+
12
+ class UDPTransport : public packet_transport::PacketTransport, public Parented<UDPComponent> {
13
+ public:
14
+ void setup() override;
15
+ void update() override;
16
+
17
+ float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
18
+
19
+ protected:
20
+ void send_packet(const std::vector<uint8_t> &buf) const override;
21
+ bool should_send() override;
22
+ bool should_broadcast_{false};
23
+ size_t get_max_packet_size() override { return MAX_PACKET_SIZE; }
24
+ };
25
+
26
+ } // namespace udp
27
+ } // namespace esphome
28
+ #endif
@@ -1,27 +1,5 @@
1
- import esphome.codegen as cg
2
- from esphome.components.sensor import new_sensor, sensor_schema
3
- from esphome.config_validation import All, has_at_least_one_key
4
- from esphome.const import CONF_ID
1
+ import esphome.config_validation as cv
5
2
 
6
- from . import (
7
- CONF_PROVIDER,
8
- CONF_REMOTE_ID,
9
- CONF_UDP_ID,
10
- SENSOR_SCHEMA,
11
- require_internal_with_name,
3
+ CONFIG_SCHEMA = cv.invalid(
4
+ "The 'udp.sensor' component has been migrated to the 'packet_transport.sensor' component."
12
5
  )
13
-
14
- DEPENDENCIES = ["udp"]
15
-
16
- CONFIG_SCHEMA = All(
17
- sensor_schema().extend(SENSOR_SCHEMA),
18
- has_at_least_one_key(CONF_ID, CONF_REMOTE_ID),
19
- require_internal_with_name,
20
- )
21
-
22
-
23
- async def to_code(config):
24
- var = await new_sensor(config)
25
- comp = await cg.get_variable(config[CONF_UDP_ID])
26
- remote_id = str(config.get(CONF_REMOTE_ID) or config.get(CONF_ID))
27
- cg.add(comp.add_remote_sensor(config[CONF_PROVIDER], remote_id, var))
@@ -1,164 +1,24 @@
1
+ #include "esphome/core/defines.h"
2
+ #ifdef USE_NETWORK
1
3
  #include "esphome/core/log.h"
2
4
  #include "esphome/core/application.h"
3
5
  #include "esphome/components/network/util.h"
4
6
  #include "udp_component.h"
5
7
 
6
- #include "esphome/components/xxtea/xxtea.h"
7
-
8
8
  namespace esphome {
9
9
  namespace udp {
10
10
 
11
- /**
12
- * Structure of a data packet; everything is little-endian
13
- *
14
- * --- In clear text ---
15
- * MAGIC_NUMBER: 16 bits
16
- * host name length: 1 byte
17
- * host name: (length) bytes
18
- * padding: 0 or more null bytes to a 4 byte boundary
19
- *
20
- * --- Encrypted (if key set) ----
21
- * DATA_KEY: 1 byte: OR ROLLING_CODE_KEY:
22
- * Rolling code (if enabled): 8 bytes
23
- * Ping keys: if any
24
- * repeat:
25
- * PING_KEY: 1 byte
26
- * ping code: 4 bytes
27
- * Sensors:
28
- * repeat:
29
- * SENSOR_KEY: 1 byte
30
- * float value: 4 bytes
31
- * name length: 1 byte
32
- * name
33
- * Binary Sensors:
34
- * repeat:
35
- * BINARY_SENSOR_KEY: 1 byte
36
- * bool value: 1 bytes
37
- * name length: 1 byte
38
- * name
39
- *
40
- * Padded to a 4 byte boundary with nulls
41
- *
42
- * Structure of a ping request packet:
43
- * --- In clear text ---
44
- * MAGIC_PING: 16 bits
45
- * host name length: 1 byte
46
- * host name: (length) bytes
47
- * Ping key (4 bytes)
48
- *
49
- */
50
11
  static const char *const TAG = "udp";
51
12
 
52
- static size_t round4(size_t value) { return (value + 3) & ~3; }
53
-
54
- union FuData {
55
- uint32_t u32;
56
- float f32;
57
- };
58
-
59
- static const size_t MAX_PACKET_SIZE = 508;
60
- static const uint16_t MAGIC_NUMBER = 0x4553;
61
- static const uint16_t MAGIC_PING = 0x5048;
62
- static const uint32_t PREF_HASH = 0x45535043;
63
- enum DataKey {
64
- ZERO_FILL_KEY,
65
- DATA_KEY,
66
- SENSOR_KEY,
67
- BINARY_SENSOR_KEY,
68
- PING_KEY,
69
- ROLLING_CODE_KEY,
70
- };
71
-
72
- static const size_t MAX_PING_KEYS = 4;
73
-
74
- static inline void add(std::vector<uint8_t> &vec, uint32_t data) {
75
- vec.push_back(data & 0xFF);
76
- vec.push_back((data >> 8) & 0xFF);
77
- vec.push_back((data >> 16) & 0xFF);
78
- vec.push_back((data >> 24) & 0xFF);
79
- }
80
-
81
- static inline uint32_t get_uint32(uint8_t *&buf) {
82
- uint32_t data = *buf++;
83
- data += *buf++ << 8;
84
- data += *buf++ << 16;
85
- data += *buf++ << 24;
86
- return data;
87
- }
88
-
89
- static inline uint16_t get_uint16(uint8_t *&buf) {
90
- uint16_t data = *buf++;
91
- data += *buf++ << 8;
92
- return data;
93
- }
94
-
95
- static inline void add(std::vector<uint8_t> &vec, uint8_t data) { vec.push_back(data); }
96
- static inline void add(std::vector<uint8_t> &vec, uint16_t data) {
97
- vec.push_back((uint8_t) data);
98
- vec.push_back((uint8_t) (data >> 8));
99
- }
100
- static inline void add(std::vector<uint8_t> &vec, DataKey data) { vec.push_back(data); }
101
- static void add(std::vector<uint8_t> &vec, const char *str) {
102
- auto len = strlen(str);
103
- vec.push_back(len);
104
- for (size_t i = 0; i != len; i++) {
105
- vec.push_back(*str++);
106
- }
107
- }
108
-
109
13
  void UDPComponent::setup() {
110
- this->name_ = App.get_name().c_str();
111
- if (strlen(this->name_) > 255) {
112
- this->mark_failed();
113
- this->status_set_error("Device name exceeds 255 chars");
114
- return;
115
- }
116
- this->resend_ping_key_ = this->ping_pong_enable_;
117
- // restore the upper 32 bits of the rolling code, increment and save.
118
- this->pref_ = global_preferences->make_preference<uint32_t>(PREF_HASH, true);
119
- this->pref_.load(&this->rolling_code_[1]);
120
- this->rolling_code_[1]++;
121
- this->pref_.save(&this->rolling_code_[1]);
122
- this->ping_key_ = random_uint32();
123
- ESP_LOGV(TAG, "Rolling code incremented, upper part now %u", (unsigned) this->rolling_code_[1]);
124
- #ifdef USE_SENSOR
125
- for (auto &sensor : this->sensors_) {
126
- sensor.sensor->add_on_state_callback([this, &sensor](float x) {
127
- this->updated_ = true;
128
- sensor.updated = true;
129
- });
130
- }
131
- #endif
132
- #ifdef USE_BINARY_SENSOR
133
- for (auto &sensor : this->binary_sensors_) {
134
- sensor.sensor->add_on_state_callback([this, &sensor](bool value) {
135
- this->updated_ = true;
136
- sensor.updated = true;
137
- });
138
- }
139
- #endif
140
- this->should_send_ = this->ping_pong_enable_;
141
- #ifdef USE_SENSOR
142
- this->should_send_ |= !this->sensors_.empty();
143
- #endif
144
- #ifdef USE_BINARY_SENSOR
145
- this->should_send_ |= !this->binary_sensors_.empty();
146
- #endif
147
- this->should_listen_ = !this->providers_.empty() || this->is_encrypted_();
148
- // initialise the header. This is invariant.
149
- add(this->header_, MAGIC_NUMBER);
150
- add(this->header_, this->name_);
151
- // pad to a multiple of 4 bytes
152
- while (this->header_.size() & 0x3)
153
- this->header_.push_back(0);
154
14
  #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
155
15
  for (const auto &address : this->addresses_) {
156
16
  struct sockaddr saddr {};
157
- socket::set_sockaddr(&saddr, sizeof(saddr), address, this->port_);
17
+ socket::set_sockaddr(&saddr, sizeof(saddr), address, this->broadcast_port_);
158
18
  this->sockaddrs_.push_back(saddr);
159
19
  }
160
20
  // set up broadcast socket
161
- if (this->should_send_) {
21
+ if (this->should_broadcast_) {
162
22
  this->broadcast_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
163
23
  if (this->broadcast_socket_ == nullptr) {
164
24
  this->mark_failed();
@@ -202,14 +62,14 @@ void UDPComponent::setup() {
202
62
 
203
63
  server.sin_family = AF_INET;
204
64
  server.sin_addr.s_addr = ESPHOME_INADDR_ANY;
205
- server.sin_port = htons(this->port_);
65
+ server.sin_port = htons(this->listen_port_);
206
66
 
207
67
  if (this->listen_address_.has_value()) {
208
68
  struct ip_mreq imreq = {};
209
69
  imreq.imr_interface.s_addr = ESPHOME_INADDR_ANY;
210
70
  inet_aton(this->listen_address_.value().str().c_str(), &imreq.imr_multiaddr);
211
71
  server.sin_addr.s_addr = imreq.imr_multiaddr.s_addr;
212
- ESP_LOGV(TAG, "Join multicast %s", this->listen_address_.value().str().c_str());
72
+ ESP_LOGD(TAG, "Join multicast %s", this->listen_address_.value().str().c_str());
213
73
  err = this->listen_socket_->setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, &imreq, sizeof(imreq));
214
74
  if (err < 0) {
215
75
  ESP_LOGE(TAG, "Failed to set IP_ADD_MEMBERSHIP. Error %d", errno);
@@ -236,341 +96,48 @@ void UDPComponent::setup() {
236
96
  this->ipaddrs_.push_back(ipaddr);
237
97
  }
238
98
  if (this->should_listen_)
239
- this->udp_client_.begin(this->port_);
99
+ this->udp_client_.begin(this->listen_port_);
240
100
  #endif
241
101
  }
242
102
 
243
- void UDPComponent::init_data_() {
244
- this->data_.clear();
245
- if (this->rolling_code_enable_) {
246
- add(this->data_, ROLLING_CODE_KEY);
247
- add(this->data_, this->rolling_code_[0]);
248
- add(this->data_, this->rolling_code_[1]);
249
- this->increment_code_();
250
- } else {
251
- add(this->data_, DATA_KEY);
252
- }
253
- for (auto pkey : this->ping_keys_) {
254
- add(this->data_, PING_KEY);
255
- add(this->data_, pkey.second);
256
- }
257
- }
258
-
259
- void UDPComponent::flush_() {
260
- if (!network::is_connected() || this->data_.empty())
261
- return;
262
- uint32_t buffer[MAX_PACKET_SIZE / 4];
263
- memset(buffer, 0, sizeof buffer);
264
- // len must be a multiple of 4
265
- auto header_len = round4(this->header_.size()) / 4;
266
- auto len = round4(data_.size()) / 4;
267
- memcpy(buffer, this->header_.data(), this->header_.size());
268
- memcpy(buffer + header_len, this->data_.data(), this->data_.size());
269
- if (this->is_encrypted_()) {
270
- xxtea::encrypt(buffer + header_len, len, (uint32_t *) this->encryption_key_.data());
271
- }
272
- auto total_len = (header_len + len) * 4;
273
- this->send_packet_(buffer, total_len);
274
- }
275
-
276
- void UDPComponent::add_binary_data_(uint8_t key, const char *id, bool data) {
277
- auto len = 1 + 1 + 1 + strlen(id);
278
- if (len + this->header_.size() + this->data_.size() > MAX_PACKET_SIZE) {
279
- this->flush_();
280
- }
281
- add(this->data_, key);
282
- add(this->data_, (uint8_t) data);
283
- add(this->data_, id);
284
- }
285
- void UDPComponent::add_data_(uint8_t key, const char *id, float data) {
286
- FuData udata{.f32 = data};
287
- this->add_data_(key, id, udata.u32);
288
- }
289
-
290
- void UDPComponent::add_data_(uint8_t key, const char *id, uint32_t data) {
291
- auto len = 4 + 1 + 1 + strlen(id);
292
- if (len + this->header_.size() + this->data_.size() > MAX_PACKET_SIZE) {
293
- this->flush_();
294
- }
295
- add(this->data_, key);
296
- add(this->data_, data);
297
- add(this->data_, id);
298
- }
299
- void UDPComponent::send_data_(bool all) {
300
- if (!this->should_send_ || !network::is_connected())
301
- return;
302
- this->init_data_();
303
- #ifdef USE_SENSOR
304
- for (auto &sensor : this->sensors_) {
305
- if (all || sensor.updated) {
306
- sensor.updated = false;
307
- this->add_data_(SENSOR_KEY, sensor.id, sensor.sensor->get_state());
308
- }
309
- }
310
- #endif
311
- #ifdef USE_BINARY_SENSOR
312
- for (auto &sensor : this->binary_sensors_) {
313
- if (all || sensor.updated) {
314
- sensor.updated = false;
315
- this->add_binary_data_(BINARY_SENSOR_KEY, sensor.id, sensor.sensor->state);
316
- }
317
- }
318
- #endif
319
- this->flush_();
320
- this->updated_ = false;
321
- this->resend_data_ = false;
322
- }
323
-
324
- void UDPComponent::update() {
325
- this->updated_ = true;
326
- this->resend_data_ = this->should_send_;
327
- auto now = millis() / 1000;
328
- if (this->last_key_time_ + this->ping_pong_recyle_time_ < now) {
329
- this->resend_ping_key_ = this->ping_pong_enable_;
330
- this->last_key_time_ = now;
331
- }
332
- }
333
-
334
103
  void UDPComponent::loop() {
335
- uint8_t buf[MAX_PACKET_SIZE];
104
+ auto buf = std::vector<uint8_t>(MAX_PACKET_SIZE);
336
105
  if (this->should_listen_) {
337
106
  for (;;) {
338
107
  #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
339
- auto len = this->listen_socket_->read(buf, sizeof(buf));
108
+ auto len = this->listen_socket_->read(buf.data(), buf.size());
340
109
  #endif
341
110
  #ifdef USE_SOCKET_IMPL_LWIP_TCP
342
111
  auto len = this->udp_client_.parsePacket();
343
112
  if (len > 0)
344
- len = this->udp_client_.read(buf, sizeof(buf));
345
- #endif
346
- if (len > 0) {
347
- this->process_(buf, len);
348
- continue;
349
- }
350
- break;
351
- }
352
- }
353
- if (this->resend_ping_key_)
354
- this->send_ping_pong_request_();
355
- if (this->updated_) {
356
- this->send_data_(this->resend_data_);
357
- }
358
- }
359
-
360
- void UDPComponent::add_key_(const char *name, uint32_t key) {
361
- if (!this->is_encrypted_())
362
- return;
363
- if (this->ping_keys_.count(name) == 0 && this->ping_keys_.size() == MAX_PING_KEYS) {
364
- ESP_LOGW(TAG, "Ping key from %s discarded", name);
365
- return;
366
- }
367
- this->ping_keys_[name] = key;
368
- this->resend_data_ = true;
369
- ESP_LOGV(TAG, "Ping key from %s now %X", name, (unsigned) key);
370
- }
371
-
372
- void UDPComponent::process_ping_request_(const char *name, uint8_t *ptr, size_t len) {
373
- if (len != 4) {
374
- ESP_LOGW(TAG, "Bad ping request");
375
- return;
376
- }
377
- auto key = get_uint32(ptr);
378
- this->add_key_(name, key);
379
- ESP_LOGV(TAG, "Updated ping key for %s to %08X", name, (unsigned) key);
380
- }
381
-
382
- static bool process_rolling_code(Provider &provider, uint8_t *&buf, const uint8_t *end) {
383
- if (end - buf < 8)
384
- return false;
385
- auto code0 = get_uint32(buf);
386
- auto code1 = get_uint32(buf);
387
- if (code1 < provider.last_code[1] || (code1 == provider.last_code[1] && code0 <= provider.last_code[0])) {
388
- ESP_LOGW(TAG, "Rolling code for %s %08lX:%08lX is old", provider.name, (unsigned long) code1,
389
- (unsigned long) code0);
390
- return false;
391
- }
392
- provider.last_code[0] = code0;
393
- provider.last_code[1] = code1;
394
- return true;
395
- }
396
-
397
- /**
398
- * Process a received packet
399
- */
400
- void UDPComponent::process_(uint8_t *buf, const size_t len) {
401
- auto ping_key_seen = !this->ping_pong_enable_;
402
- if (len < 8) {
403
- ESP_LOGV(TAG, "Bad length %zu", len);
404
- return;
405
- }
406
- char namebuf[256]{};
407
- uint8_t byte;
408
- uint8_t *start_ptr = buf;
409
- const uint8_t *end = buf + len;
410
- FuData rdata{};
411
- auto magic = get_uint16(buf);
412
- if (magic != MAGIC_NUMBER && magic != MAGIC_PING) {
413
- ESP_LOGV(TAG, "Bad magic %X", magic);
414
- return;
415
- }
416
-
417
- auto hlen = *buf++;
418
- if (hlen > len - 3) {
419
- ESP_LOGV(TAG, "Bad hostname length %u > %zu", hlen, len - 3);
420
- return;
421
- }
422
- memcpy(namebuf, buf, hlen);
423
- if (strcmp(this->name_, namebuf) == 0) {
424
- ESP_LOGV(TAG, "Ignoring our own data");
425
- return;
426
- }
427
- buf += hlen;
428
- if (magic == MAGIC_PING) {
429
- this->process_ping_request_(namebuf, buf, end - buf);
430
- return;
431
- }
432
- if (round4(len) != len) {
433
- ESP_LOGW(TAG, "Bad length %zu", len);
434
- return;
435
- }
436
- hlen = round4(hlen + 3);
437
- buf = start_ptr + hlen;
438
- if (buf == end) {
439
- ESP_LOGV(TAG, "No data after header");
440
- return;
441
- }
442
-
443
- if (this->providers_.count(namebuf) == 0) {
444
- ESP_LOGVV(TAG, "Unknown hostname %s", namebuf);
445
- return;
446
- }
447
- auto &provider = this->providers_[namebuf];
448
- // if encryption not used with this host, ping check is pointless since it would be easily spoofed.
449
- if (provider.encryption_key.empty())
450
- ping_key_seen = true;
451
-
452
- ESP_LOGV(TAG, "Found hostname %s", namebuf);
453
- #ifdef USE_SENSOR
454
- auto &sensors = this->remote_sensors_[namebuf];
455
- #endif
456
- #ifdef USE_BINARY_SENSOR
457
- auto &binary_sensors = this->remote_binary_sensors_[namebuf];
113
+ len = this->udp_client_.read(buf.data(), buf.size());
458
114
  #endif
459
-
460
- if (!provider.encryption_key.empty()) {
461
- xxtea::decrypt((uint32_t *) buf, (end - buf) / 4, (uint32_t *) provider.encryption_key.data());
462
- }
463
- byte = *buf++;
464
- if (byte == ROLLING_CODE_KEY) {
465
- if (!process_rolling_code(provider, buf, end))
466
- return;
467
- } else if (byte != DATA_KEY) {
468
- ESP_LOGV(TAG, "Expected rolling_key or data_key, got %X", byte);
469
- return;
470
- }
471
- while (buf < end) {
472
- byte = *buf++;
473
- if (byte == ZERO_FILL_KEY)
474
- continue;
475
- if (byte == PING_KEY) {
476
- if (end - buf < 4) {
477
- ESP_LOGV(TAG, "PING_KEY requires 4 more bytes");
478
- return;
479
- }
480
- auto key = get_uint32(buf);
481
- if (key == this->ping_key_) {
482
- ping_key_seen = true;
483
- ESP_LOGV(TAG, "Found good ping key %X", (unsigned) key);
484
- } else {
485
- ESP_LOGV(TAG, "Unknown ping key %X", (unsigned) key);
486
- }
487
- continue;
488
- }
489
- if (!ping_key_seen) {
490
- ESP_LOGW(TAG, "Ping key not seen");
491
- this->resend_ping_key_ = true;
492
- break;
115
+ if (len <= 0)
116
+ break;
117
+ buf.resize(len);
118
+ ESP_LOGV(TAG, "Received packet of length %zu", len);
119
+ this->packet_listeners_.call(buf);
493
120
  }
494
- if (byte == BINARY_SENSOR_KEY) {
495
- if (end - buf < 3) {
496
- ESP_LOGV(TAG, "Binary sensor key requires at least 3 more bytes");
497
- return;
498
- }
499
- rdata.u32 = *buf++;
500
- } else if (byte == SENSOR_KEY) {
501
- if (end - buf < 6) {
502
- ESP_LOGV(TAG, "Sensor key requires at least 6 more bytes");
503
- return;
504
- }
505
- rdata.u32 = get_uint32(buf);
506
- } else {
507
- ESP_LOGW(TAG, "Unknown key byte %X", byte);
508
- return;
509
- }
510
-
511
- hlen = *buf++;
512
- if (end - buf < hlen) {
513
- ESP_LOGV(TAG, "Name length of %u not available", hlen);
514
- return;
515
- }
516
- memset(namebuf, 0, sizeof namebuf);
517
- memcpy(namebuf, buf, hlen);
518
- ESP_LOGV(TAG, "Found sensor key %d, id %s, data %lX", byte, namebuf, (unsigned long) rdata.u32);
519
- buf += hlen;
520
- #ifdef USE_SENSOR
521
- if (byte == SENSOR_KEY && sensors.count(namebuf) != 0)
522
- sensors[namebuf]->publish_state(rdata.f32);
523
- #endif
524
- #ifdef USE_BINARY_SENSOR
525
- if (byte == BINARY_SENSOR_KEY && binary_sensors.count(namebuf) != 0)
526
- binary_sensors[namebuf]->publish_state(rdata.u32 != 0);
527
- #endif
528
121
  }
529
122
  }
530
123
 
531
124
  void UDPComponent::dump_config() {
532
125
  ESP_LOGCONFIG(TAG, "UDP:");
533
- ESP_LOGCONFIG(TAG, " Port: %u", this->port_);
534
- ESP_LOGCONFIG(TAG, " Encrypted: %s", YESNO(this->is_encrypted_()));
535
- ESP_LOGCONFIG(TAG, " Ping-pong: %s", YESNO(this->ping_pong_enable_));
126
+ ESP_LOGCONFIG(TAG, " Listen Port: %u", this->listen_port_);
127
+ ESP_LOGCONFIG(TAG, " Broadcast Port: %u", this->broadcast_port_);
536
128
  for (const auto &address : this->addresses_)
537
129
  ESP_LOGCONFIG(TAG, " Address: %s", address.c_str());
538
130
  if (this->listen_address_.has_value()) {
539
131
  ESP_LOGCONFIG(TAG, " Listen address: %s", this->listen_address_.value().str().c_str());
540
132
  }
541
- #ifdef USE_SENSOR
542
- for (auto sensor : this->sensors_)
543
- ESP_LOGCONFIG(TAG, " Sensor: %s", sensor.id);
544
- #endif
545
- #ifdef USE_BINARY_SENSOR
546
- for (auto sensor : this->binary_sensors_)
547
- ESP_LOGCONFIG(TAG, " Binary Sensor: %s", sensor.id);
548
- #endif
549
- for (const auto &host : this->providers_) {
550
- ESP_LOGCONFIG(TAG, " Remote host: %s", host.first.c_str());
551
- ESP_LOGCONFIG(TAG, " Encrypted: %s", YESNO(!host.second.encryption_key.empty()));
552
- #ifdef USE_SENSOR
553
- for (const auto &sensor : this->remote_sensors_[host.first.c_str()])
554
- ESP_LOGCONFIG(TAG, " Sensor: %s", sensor.first.c_str());
555
- #endif
556
- #ifdef USE_BINARY_SENSOR
557
- for (const auto &sensor : this->remote_binary_sensors_[host.first.c_str()])
558
- ESP_LOGCONFIG(TAG, " Binary Sensor: %s", sensor.first.c_str());
559
- #endif
560
- }
133
+ ESP_LOGCONFIG(TAG, " Broadcasting: %s", YESNO(this->should_broadcast_));
134
+ ESP_LOGCONFIG(TAG, " Listening: %s", YESNO(this->should_listen_));
561
135
  }
562
- void UDPComponent::increment_code_() {
563
- if (this->rolling_code_enable_) {
564
- if (++this->rolling_code_[0] == 0) {
565
- this->rolling_code_[1]++;
566
- this->pref_.save(&this->rolling_code_[1]);
567
- }
568
- }
569
- }
570
- void UDPComponent::send_packet_(void *data, size_t len) {
136
+
137
+ void UDPComponent::send_packet(const uint8_t *data, size_t size) {
571
138
  #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
572
139
  for (const auto &saddr : this->sockaddrs_) {
573
- auto result = this->broadcast_socket_->sendto(data, len, 0, &saddr, sizeof(saddr));
140
+ auto result = this->broadcast_socket_->sendto(data, size, 0, &saddr, sizeof(saddr));
574
141
  if (result < 0)
575
142
  ESP_LOGW(TAG, "sendto() error %d", errno);
576
143
  }
@@ -578,8 +145,8 @@ void UDPComponent::send_packet_(void *data, size_t len) {
578
145
  #ifdef USE_SOCKET_IMPL_LWIP_TCP
579
146
  auto iface = IPAddress(0, 0, 0, 0);
580
147
  for (const auto &saddr : this->ipaddrs_) {
581
- if (this->udp_client_.beginPacketMulticast(saddr, this->port_, iface, 128) != 0) {
582
- this->udp_client_.write((const uint8_t *) data, len);
148
+ if (this->udp_client_.beginPacketMulticast(saddr, this->broadcast_port_, iface, 128) != 0) {
149
+ this->udp_client_.write(data, size);
583
150
  auto result = this->udp_client_.endPacket();
584
151
  if (result == 0)
585
152
  ESP_LOGW(TAG, "udp.write() error");
@@ -587,18 +154,7 @@ void UDPComponent::send_packet_(void *data, size_t len) {
587
154
  }
588
155
  #endif
589
156
  }
590
-
591
- void UDPComponent::send_ping_pong_request_() {
592
- if (!this->ping_pong_enable_ || !network::is_connected())
593
- return;
594
- this->ping_key_ = random_uint32();
595
- this->ping_header_.clear();
596
- add(this->ping_header_, MAGIC_PING);
597
- add(this->ping_header_, this->name_);
598
- add(this->ping_header_, this->ping_key_);
599
- this->send_packet_(this->ping_header_.data(), this->ping_header_.size());
600
- this->resend_ping_key_ = false;
601
- ESP_LOGV(TAG, "Sent new ping request %08X", (unsigned) this->ping_key_);
602
- }
603
157
  } // namespace udp
604
158
  } // namespace esphome
159
+
160
+ #endif