esphome 2025.5.1__py3-none-any.whl → 2025.6.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (720) hide show
  1. esphome/__main__.py +20 -14
  2. esphome/components/a4988/a4988.cpp +1 -1
  3. esphome/components/absolute_humidity/absolute_humidity.cpp +6 -4
  4. esphome/components/ac_dimmer/ac_dimmer.cpp +4 -2
  5. esphome/components/adc/adc_sensor_esp32.cpp +5 -3
  6. esphome/components/adc/adc_sensor_esp8266.cpp +5 -3
  7. esphome/components/adc/adc_sensor_libretiny.cpp +5 -3
  8. esphome/components/adc/adc_sensor_rp2040.cpp +5 -3
  9. esphome/components/adc128s102/adc128s102.cpp +1 -1
  10. esphome/components/ade7880/ade7880.cpp +28 -17
  11. esphome/components/ade7953_base/ade7953_base.cpp +12 -9
  12. esphome/components/ade7953_i2c/ade7953_i2c.cpp +1 -1
  13. esphome/components/ade7953_spi/ade7953_spi.cpp +1 -1
  14. esphome/components/ads1115/ads1115.cpp +3 -5
  15. esphome/components/ads1118/ads1118.cpp +2 -1
  16. esphome/components/ags10/ags10.cpp +3 -2
  17. esphome/components/aht10/aht10.cpp +27 -29
  18. esphome/components/aic3204/aic3204.cpp +2 -2
  19. esphome/components/alarm_control_panel/__init__.py +1 -0
  20. esphome/components/am2315c/am2315c.cpp +2 -2
  21. esphome/components/am2320/am2320.cpp +2 -2
  22. esphome/components/am43/am43_base.h +1 -1
  23. esphome/components/am43/cover/am43_cover.cpp +4 -2
  24. esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +4 -2
  25. esphome/components/apds9306/apds9306.cpp +8 -5
  26. esphome/components/apds9960/apds9960.cpp +2 -2
  27. esphome/components/api/__init__.py +5 -0
  28. esphome/components/api/api_connection.cpp +712 -358
  29. esphome/components/api/api_connection.h +343 -284
  30. esphome/components/api/api_frame_helper.cpp +349 -344
  31. esphome/components/api/api_frame_helper.h +121 -94
  32. esphome/components/api/api_pb2.cpp +2 -0
  33. esphome/components/api/api_pb2.h +637 -1
  34. esphome/components/api/api_pb2_service.cpp +12 -688
  35. esphome/components/api/api_pb2_service.h +53 -207
  36. esphome/components/api/api_server.cpp +71 -29
  37. esphome/components/api/api_server.h +9 -0
  38. esphome/components/api/client.py +5 -2
  39. esphome/components/api/homeassistant_service.h +1 -1
  40. esphome/components/api/list_entities.cpp +1 -1
  41. esphome/components/api/proto.cpp +1 -0
  42. esphome/components/api/proto.h +4 -3
  43. esphome/components/api/subscribe_state.cpp +8 -16
  44. esphome/components/as3935/as3935.cpp +3 -3
  45. esphome/components/as5600/as5600.cpp +9 -7
  46. esphome/components/as7341/as7341.cpp +7 -5
  47. esphome/components/at581x/at581x.cpp +13 -10
  48. esphome/components/atm90e26/atm90e26.cpp +2 -2
  49. esphome/components/atm90e32/atm90e32.cpp +3 -3
  50. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +5 -3
  51. esphome/components/bang_bang/bang_bang_climate.cpp +8 -5
  52. esphome/components/bedjet/bedjet_hub.cpp +6 -4
  53. esphome/components/beken_spi_led_strip/led_strip.cpp +11 -7
  54. esphome/components/bh1750/bh1750.cpp +2 -2
  55. esphome/components/binary_sensor/__init__.py +1 -0
  56. esphome/components/binary_sensor/automation.cpp +1 -2
  57. esphome/components/bl0906/bl0906.cpp +1 -1
  58. esphome/components/bl0942/bl0942.cpp +11 -8
  59. esphome/components/bl0942/sensor.py +1 -1
  60. esphome/components/ble_client/__init__.py +5 -1
  61. esphome/components/ble_client/output/ble_binary_output.cpp +6 -3
  62. esphome/components/ble_client/sensor/ble_sensor.cpp +9 -6
  63. esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +8 -5
  64. esphome/components/bluetooth_proxy/__init__.py +5 -1
  65. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +5 -5
  66. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +16 -14
  67. esphome/components/bme280_base/bme280_base.cpp +3 -3
  68. esphome/components/bme680/bme680.cpp +3 -3
  69. esphome/components/bme680/sensor.py +2 -2
  70. esphome/components/bme680_bsec/bme680_bsec.cpp +11 -7
  71. esphome/components/bme680_bsec/sensor.py +7 -3
  72. esphome/components/bme68x_bsec2/__init__.py +6 -5
  73. esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +17 -13
  74. esphome/components/bme68x_bsec2/sensor.py +4 -4
  75. esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.cpp +1 -0
  76. esphome/components/bmi160/bmi160.cpp +11 -11
  77. esphome/components/bmp085/bmp085.cpp +2 -2
  78. esphome/components/bmp280_base/bmp280_base.cpp +3 -3
  79. esphome/components/bmp3xx_base/bmp3xx_base.cpp +13 -13
  80. esphome/components/bmp581/bmp581.cpp +33 -27
  81. esphome/components/bp1658cj/bp1658cj.cpp +5 -3
  82. esphome/components/bp5758d/bp5758d.cpp +1 -1
  83. esphome/components/button/__init__.py +1 -0
  84. esphome/components/canbus/canbus.cpp +1 -1
  85. esphome/components/cap1188/cap1188.cpp +6 -4
  86. esphome/components/captive_portal/captive_portal.cpp +1 -1
  87. esphome/components/ccs811/ccs811.cpp +3 -2
  88. esphome/components/cd74hc4067/cd74hc4067.cpp +1 -1
  89. esphome/components/ch422g/ch422g.cpp +2 -2
  90. esphome/components/chsc6x/chsc6x_touchscreen.cpp +6 -4
  91. esphome/components/climate/__init__.py +1 -0
  92. esphome/components/climate/climate.cpp +12 -7
  93. esphome/components/climate/climate.h +1 -1
  94. esphome/components/climate_ir/climate_ir.cpp +7 -4
  95. esphome/components/cm1106/__init__.py +1 -0
  96. esphome/components/cm1106/cm1106.cpp +112 -0
  97. esphome/components/cm1106/cm1106.h +40 -0
  98. esphome/components/cm1106/sensor.py +72 -0
  99. esphome/components/const/__init__.py +1 -0
  100. esphome/components/cover/__init__.py +1 -0
  101. esphome/components/cs5460a/cs5460a.cpp +16 -11
  102. esphome/components/cse7761/cse7761.cpp +2 -2
  103. esphome/components/cse7766/cse7766.cpp +0 -5
  104. esphome/components/cse7766/cse7766.h +5 -1
  105. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +1 -1
  106. esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +6 -3
  107. esphome/components/current_based/current_based_cover.cpp +4 -2
  108. esphome/components/dac7678/dac7678_output.cpp +4 -4
  109. esphome/components/dallas_temp/dallas_temp.cpp +2 -3
  110. esphome/components/daly_bms/daly_bms.cpp +2 -1
  111. esphome/components/dashboard_import/__init__.py +1 -2
  112. esphome/components/datetime/__init__.py +3 -1
  113. esphome/components/debug/debug_component.cpp +1 -5
  114. esphome/components/debug/debug_component.h +1 -1
  115. esphome/components/debug/debug_esp32.cpp +4 -2
  116. esphome/components/deep_sleep/deep_sleep_component.cpp +11 -5
  117. esphome/components/deep_sleep/deep_sleep_esp32.cpp +7 -5
  118. esphome/components/demo/__init__.py +206 -0
  119. esphome/components/demo/demo_alarm_control_panel.h +65 -0
  120. esphome/components/demo/demo_button.h +15 -0
  121. esphome/components/demo/demo_date.h +34 -0
  122. esphome/components/demo/demo_datetime.h +40 -0
  123. esphome/components/demo/demo_lock.h +17 -0
  124. esphome/components/demo/demo_select.h +15 -0
  125. esphome/components/demo/demo_text.h +18 -0
  126. esphome/components/demo/demo_time.h +34 -0
  127. esphome/components/demo/demo_valve.h +54 -0
  128. esphome/components/dfrobot_sen0395/commands.cpp +3 -3
  129. esphome/components/dht/dht.cpp +29 -50
  130. esphome/components/dht12/dht12.cpp +2 -2
  131. esphome/components/display/display.h +5 -3
  132. esphome/components/dps310/dps310.cpp +7 -5
  133. esphome/components/ds1307/ds1307.cpp +2 -2
  134. esphome/components/dsmr/dsmr.cpp +5 -3
  135. esphome/components/duty_cycle/duty_cycle_sensor.cpp +2 -2
  136. esphome/components/duty_time/duty_time_sensor.cpp +5 -3
  137. esphome/components/ee895/ee895.cpp +3 -3
  138. esphome/components/ektf2232/touchscreen/ektf2232.cpp +1 -1
  139. esphome/components/emc2101/emc2101.cpp +11 -9
  140. esphome/components/ens160_base/ens160_base.cpp +2 -2
  141. esphome/components/ens210/ens210.cpp +2 -2
  142. esphome/components/es7210/es7210.cpp +6 -4
  143. esphome/components/es7243e/es7243e.cpp +1 -1
  144. esphome/components/es8156/es8156.cpp +1 -1
  145. esphome/components/es8311/es8311.cpp +8 -6
  146. esphome/components/es8388/__init__.py +0 -0
  147. esphome/components/es8388/audio_dac.py +26 -0
  148. esphome/components/es8388/es8388.cpp +289 -0
  149. esphome/components/es8388/es8388.h +81 -0
  150. esphome/components/es8388/es8388_const.h +83 -0
  151. esphome/components/es8388/select/__init__.py +47 -0
  152. esphome/components/es8388/select/adc_input_mic_select.cpp +12 -0
  153. esphome/components/es8388/select/adc_input_mic_select.h +15 -0
  154. esphome/components/es8388/select/dac_output_select.cpp +12 -0
  155. esphome/components/es8388/select/dac_output_select.h +15 -0
  156. esphome/components/esp32/__init__.py +88 -20
  157. esphome/components/esp32/boards.py +208 -125
  158. esphome/components/esp32/const.py +6 -0
  159. esphome/components/esp32/gpio.py +14 -1
  160. esphome/components/esp32/gpio_esp32_c5.py +45 -0
  161. esphome/components/esp32/gpio_esp32_p4.py +43 -0
  162. esphome/components/esp32/preferences.cpp +7 -7
  163. esphome/components/esp32_ble/__init__.py +115 -0
  164. esphome/components/esp32_ble/ble.cpp +11 -9
  165. esphome/components/esp32_ble/ble_uuid.h +1 -1
  166. esphome/components/esp32_ble_client/ble_client_base.cpp +4 -2
  167. esphome/components/esp32_ble_server/__init__.py +4 -1
  168. esphome/components/esp32_ble_server/ble_characteristic.cpp +1 -0
  169. esphome/components/esp32_ble_server/ble_server.h +0 -1
  170. esphome/components/esp32_ble_tracker/__init__.py +6 -2
  171. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +12 -9
  172. esphome/components/esp32_camera/esp32_camera.cpp +35 -27
  173. esphome/components/esp32_camera_web_server/camera_web_server.cpp +4 -2
  174. esphome/components/esp32_dac/esp32_dac.cpp +2 -2
  175. esphome/components/esp32_improv/__init__.py +5 -1
  176. esphome/components/esp32_improv/esp32_improv_component.cpp +2 -2
  177. esphome/components/esp32_rmt_led_strip/led_strip.cpp +11 -7
  178. esphome/components/esp32_rmt_led_strip/light.py +5 -1
  179. esphome/components/esp32_touch/esp32_touch.cpp +12 -8
  180. esphome/components/esp8266/gpio.cpp +10 -1
  181. esphome/components/esp8266/preferences.cpp +6 -6
  182. esphome/components/esp8266_pwm/esp8266_pwm.cpp +3 -3
  183. esphome/components/esp_ldo/__init__.py +91 -0
  184. esphome/components/esp_ldo/esp_ldo.cpp +43 -0
  185. esphome/components/esp_ldo/esp_ldo.h +43 -0
  186. esphome/components/esphome/ota/ota_esphome.cpp +15 -8
  187. esphome/components/ethernet/ethernet_component.cpp +38 -26
  188. esphome/components/ethernet/ethernet_component.h +1 -1
  189. esphome/components/event/__init__.py +1 -0
  190. esphome/components/exposure_notifications/exposure_notifications.cpp +1 -1
  191. esphome/components/ezo/ezo.cpp +1 -1
  192. esphome/components/ezo_pmp/ezo_pmp.cpp +1 -1
  193. esphome/components/factory_reset/button/factory_reset_button.cpp +1 -1
  194. esphome/components/factory_reset/switch/factory_reset_switch.cpp +1 -1
  195. esphome/components/fan/__init__.py +1 -0
  196. esphome/components/fan/fan.cpp +4 -2
  197. esphome/components/fastled_base/fastled_light.cpp +7 -5
  198. esphome/components/fingerprint_grow/fingerprint_grow.cpp +8 -6
  199. esphome/components/fs3000/fs3000.cpp +1 -1
  200. esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp +7 -4
  201. esphome/components/ft63x6/ft63x6.cpp +5 -3
  202. esphome/components/gcja5/gcja5.cpp +0 -12
  203. esphome/components/gcja5/gcja5.h +8 -3
  204. esphome/components/gdk101/gdk101.cpp +2 -2
  205. esphome/components/globals/globals_component.h +13 -10
  206. esphome/components/gp2y1010au0f/gp2y1010au0f.cpp +4 -2
  207. esphome/components/gp8403/gp8403.cpp +4 -2
  208. esphome/components/gp8403/output/gp8403_output.cpp +4 -2
  209. esphome/components/gpio/one_wire/gpio_one_wire.cpp +2 -2
  210. esphome/components/gpio/output/gpio_binary_output.cpp +1 -1
  211. esphome/components/gpio/switch/gpio_switch.cpp +1 -1
  212. esphome/components/graphical_display_menu/graphical_display_menu.cpp +12 -8
  213. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +5 -6
  214. esphome/components/grove_tb6612fng/grove_tb6612fng.cpp +1 -1
  215. esphome/components/grove_tb6612fng/grove_tb6612fng.h +1 -1
  216. esphome/components/growatt_solar/growatt_solar.cpp +6 -3
  217. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +1 -1
  218. esphome/components/haier/haier_base.cpp +2 -2
  219. esphome/components/haier/hon_climate.cpp +13 -6
  220. esphome/components/havells_solar/havells_solar.cpp +5 -2
  221. esphome/components/hbridge/switch/hbridge_switch.cpp +1 -1
  222. esphome/components/hdc1080/hdc1080.cpp +2 -2
  223. esphome/components/he60r/he60r.cpp +4 -2
  224. esphome/components/hlw8012/hlw8012.cpp +6 -4
  225. esphome/components/hm3301/hm3301.cpp +2 -2
  226. esphome/components/hmc5883l/hmc5883l.cpp +2 -2
  227. esphome/components/homeassistant/time/homeassistant_time.cpp +4 -2
  228. esphome/components/honeywell_hih_i2c/honeywell_hih.cpp +4 -4
  229. esphome/components/honeywellabp/honeywellabp.cpp +4 -2
  230. esphome/components/honeywellabp2_i2c/honeywellabp2.cpp +8 -6
  231. esphome/components/hte501/hte501.cpp +3 -2
  232. esphome/components/http_request/__init__.py +2 -2
  233. esphome/components/http_request/http_request.cpp +7 -5
  234. esphome/components/http_request/http_request_idf.cpp +4 -2
  235. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  236. esphome/components/htu21d/htu21d.cpp +2 -2
  237. esphome/components/htu31d/htu31d.cpp +2 -2
  238. esphome/components/hx711/hx711.cpp +2 -2
  239. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +5 -3
  240. esphome/components/hyt271/hyt271.cpp +2 -2
  241. esphome/components/i2c/i2c_bus_arduino.cpp +14 -11
  242. esphome/components/i2c/i2c_bus_esp_idf.cpp +13 -11
  243. esphome/components/i2s_audio/__init__.py +2 -0
  244. esphome/components/i2s_audio/i2s_audio.cpp +3 -4
  245. esphome/components/i2s_audio/i2s_audio.h +1 -1
  246. esphome/components/i2s_audio/media_player/__init__.py +1 -1
  247. esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +5 -3
  248. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +54 -64
  249. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +4 -0
  250. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  251. esphome/components/iaqcore/iaqcore.cpp +3 -3
  252. esphome/components/ili9xxx/ili9xxx_display.cpp +12 -7
  253. esphome/components/ili9xxx/ili9xxx_display.h +1 -1
  254. esphome/components/image/image.cpp +1 -0
  255. esphome/components/ina219/ina219.cpp +2 -2
  256. esphome/components/ina226/ina226.cpp +8 -5
  257. esphome/components/ina260/ina260.cpp +1 -1
  258. esphome/components/ina2xx_base/ina2xx_base.cpp +13 -9
  259. esphome/components/ina3221/ina3221.cpp +2 -2
  260. esphome/components/inkplate6/display.py +12 -2
  261. esphome/components/inkplate6/inkplate.cpp +13 -9
  262. esphome/components/inkplate6/inkplate.h +7 -6
  263. esphome/components/integration/integration_sensor.cpp +1 -1
  264. esphome/components/internal_temperature/internal_temperature.cpp +4 -4
  265. esphome/components/json/json_util.cpp +4 -5
  266. esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +1 -1
  267. esphome/components/key_collector/key_collector.cpp +4 -2
  268. esphome/components/kmeteriso/kmeteriso.cpp +2 -1
  269. esphome/components/kuntze/kuntze.cpp +4 -2
  270. esphome/components/lc709203f/__init__.py +1 -0
  271. esphome/components/lc709203f/lc709203f.cpp +299 -0
  272. esphome/components/lc709203f/lc709203f.h +55 -0
  273. esphome/components/lc709203f/sensor.py +93 -0
  274. esphome/components/lcd_base/lcd_display.cpp +2 -2
  275. esphome/components/lcd_gpio/gpio_lcd_display.cpp +5 -3
  276. esphome/components/lcd_menu/lcd_menu.cpp +6 -4
  277. esphome/components/lcd_pcf8574/pcf8574_display.cpp +6 -4
  278. esphome/components/ld2410/ld2410.cpp +6 -7
  279. esphome/components/ld2420/ld2420.cpp +9 -7
  280. esphome/components/ld2450/ld2450.cpp +6 -4
  281. esphome/components/ld2450/sensor.py +2 -2
  282. esphome/components/ledc/ledc_output.cpp +32 -28
  283. esphome/components/libretiny/const.py +1 -1
  284. esphome/components/libretiny/preferences.cpp +6 -7
  285. esphome/components/light/__init__.py +2 -1
  286. esphome/components/light/esp_hsv_color.h +1 -1
  287. esphome/components/light/light_state.cpp +9 -5
  288. esphome/components/light/light_transformer.h +1 -1
  289. esphome/components/lightwaverf/LwTx.cpp +1 -1
  290. esphome/components/lightwaverf/lightwaverf.cpp +1 -1
  291. esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp +1 -1
  292. esphome/components/lock/__init__.py +1 -0
  293. esphome/components/lock/lock.h +1 -1
  294. esphome/components/logger/__init__.py +6 -0
  295. esphome/components/logger/logger.cpp +9 -5
  296. esphome/components/logger/logger.h +4 -4
  297. esphome/components/logger/logger_esp32.cpp +5 -5
  298. esphome/components/ltr390/ltr390.cpp +8 -5
  299. esphome/components/ltr501/ltr501.cpp +19 -14
  300. esphome/components/ltr_als_ps/ltr_als_ps.cpp +20 -13
  301. esphome/components/lvgl/__init__.py +2 -2
  302. esphome/components/lvgl/automation.py +5 -4
  303. esphome/components/lvgl/defines.py +0 -2
  304. esphome/components/lvgl/lv_validation.py +1 -3
  305. esphome/components/lvgl/lvcode.py +7 -8
  306. esphome/components/lvgl/lvgl_esphome.cpp +26 -10
  307. esphome/components/lvgl/schemas.py +22 -23
  308. esphome/components/lvgl/trigger.py +8 -3
  309. esphome/components/lvgl/widgets/__init__.py +2 -2
  310. esphome/components/lvgl/widgets/canvas.py +9 -3
  311. esphome/components/lvgl/widgets/line.py +2 -1
  312. esphome/components/lvgl/widgets/tabview.py +7 -0
  313. esphome/components/m5stack_8angle/m5stack_8angle.cpp +3 -3
  314. esphome/components/matrix_keypad/matrix_keypad.cpp +2 -2
  315. esphome/components/max17043/max17043.cpp +2 -2
  316. esphome/components/max31855/max31855.cpp +2 -1
  317. esphome/components/max31856/max31856.cpp +9 -11
  318. esphome/components/max31865/max31865.cpp +6 -4
  319. esphome/components/max44009/max44009.cpp +2 -2
  320. esphome/components/max6675/max6675.cpp +1 -1
  321. esphome/components/max6956/max6956.cpp +5 -3
  322. esphome/components/max7219/max7219.cpp +8 -6
  323. esphome/components/max7219digit/automation.h +52 -0
  324. esphome/components/max7219digit/display.py +93 -1
  325. esphome/components/max7219digit/max7219digit.cpp +16 -13
  326. esphome/components/max9611/max9611.cpp +9 -6
  327. esphome/components/mcp23008/mcp23008.cpp +1 -1
  328. esphome/components/mcp23016/mcp23016.cpp +1 -1
  329. esphome/components/mcp23017/mcp23017.cpp +1 -1
  330. esphome/components/mcp23s08/mcp23s08.cpp +1 -1
  331. esphome/components/mcp23s17/mcp23s17.cpp +1 -1
  332. esphome/components/mcp3008/mcp3008.cpp +1 -1
  333. esphome/components/mcp3008/sensor/mcp3008_sensor.cpp +5 -3
  334. esphome/components/mcp3204/mcp3204.cpp +1 -1
  335. esphome/components/mcp4461/mcp4461.cpp +2 -2
  336. esphome/components/mcp4725/mcp4725.cpp +2 -2
  337. esphome/components/mcp4728/mcp4728.cpp +2 -2
  338. esphome/components/mcp9600/mcp9600.cpp +1 -1
  339. esphome/components/mcp9808/mcp9808.cpp +4 -4
  340. esphome/components/mdns/mdns_component.cpp +8 -2
  341. esphome/components/mdns/mdns_component.h +3 -1
  342. esphome/components/mdns/mdns_esp32.cpp +2 -2
  343. esphome/components/media_player/__init__.py +1 -0
  344. esphome/components/micro_wake_word/micro_wake_word.cpp +1 -1
  345. esphome/components/micro_wake_word/streaming_model.cpp +10 -6
  346. esphome/components/micronova/micronova.h +2 -2
  347. esphome/components/mics_4514/mics_4514.cpp +2 -2
  348. esphome/components/midea/air_conditioner.cpp +7 -5
  349. esphome/components/midea_ir/midea_ir.cpp +1 -1
  350. esphome/components/mipi_spi/mipi_spi.cpp +24 -15
  351. esphome/components/mixer/speaker/mixer_speaker.cpp +8 -4
  352. esphome/components/mlx90393/sensor_mlx90393.cpp +2 -2
  353. esphome/components/mlx90614/mlx90614.cpp +4 -3
  354. esphome/components/mmc5603/mmc5603.cpp +2 -2
  355. esphome/components/mmc5983/mmc5983.cpp +1 -1
  356. esphome/components/modbus/modbus.cpp +7 -5
  357. esphome/components/modbus_controller/modbus_controller.cpp +6 -4
  358. esphome/components/modbus_controller/output/modbus_output.cpp +10 -6
  359. esphome/components/modbus_controller/switch/__init__.py +6 -2
  360. esphome/components/modbus_controller/switch/modbus_switch.cpp +4 -0
  361. esphome/components/modbus_controller/switch/modbus_switch.h +3 -0
  362. esphome/components/mpl3115a2/mpl3115a2.cpp +3 -2
  363. esphome/components/mpr121/mpr121.cpp +2 -2
  364. esphome/components/mpu6050/mpu6050.cpp +6 -6
  365. esphome/components/mpu6886/mpu6886.cpp +6 -6
  366. esphome/components/mqtt/mqtt_alarm_control_panel.cpp +7 -3
  367. esphome/components/mqtt/mqtt_backend_esp32.cpp +1 -1
  368. esphome/components/mqtt/mqtt_client.cpp +31 -24
  369. esphome/components/mqtt/mqtt_component.cpp +2 -2
  370. esphome/components/mqtt/mqtt_cover.cpp +8 -4
  371. esphome/components/mqtt/mqtt_fan.cpp +12 -6
  372. esphome/components/mqtt/mqtt_valve.cpp +4 -2
  373. esphome/components/ms5611/ms5611.cpp +2 -2
  374. esphome/components/ms8607/ms8607.cpp +2 -2
  375. esphome/components/msa3xx/msa3xx.cpp +16 -12
  376. esphome/components/my9231/my9231.cpp +7 -5
  377. esphome/components/nau7802/nau7802.cpp +6 -4
  378. esphome/components/neopixelbus/neopixelbus_light.h +2 -2
  379. esphome/components/network/ip_address.h +1 -1
  380. esphome/components/network/util.cpp +13 -0
  381. esphome/components/nextion/base_component.py +2 -0
  382. esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +2 -3
  383. esphome/components/nextion/display.py +34 -22
  384. esphome/components/nextion/nextion.cpp +182 -143
  385. esphome/components/nextion/nextion.h +36 -0
  386. esphome/components/nextion/nextion_commands.cpp +3 -3
  387. esphome/components/nextion/nextion_upload_arduino.cpp +58 -61
  388. esphome/components/nextion/nextion_upload_idf.cpp +69 -72
  389. esphome/components/nextion/sensor/nextion_sensor.cpp +4 -4
  390. esphome/components/nextion/switch/nextion_switch.cpp +2 -2
  391. esphome/components/nextion/text_sensor/nextion_textsensor.cpp +2 -2
  392. esphome/components/nfc/nci_message.h +1 -1
  393. esphome/components/nfc/ndef_record.h +1 -1
  394. esphome/components/nfc/ndef_record_text.h +1 -1
  395. esphome/components/nfc/ndef_record_uri.h +1 -1
  396. esphome/components/nfc/nfc.h +1 -1
  397. esphome/components/nfc/nfc_tag.h +1 -1
  398. esphome/components/noblex/noblex.cpp +1 -1
  399. esphome/components/npi19/npi19.cpp +5 -7
  400. esphome/components/number/__init__.py +11 -0
  401. esphome/components/online_image/__init__.py +13 -1
  402. esphome/components/online_image/online_image.cpp +26 -4
  403. esphome/components/online_image/online_image.h +21 -4
  404. esphome/components/opentherm/generate.py +3 -3
  405. esphome/components/opentherm/hub.cpp +11 -7
  406. esphome/components/opentherm/number/number.cpp +5 -3
  407. esphome/components/opentherm/opentherm.h +1 -1
  408. esphome/components/opentherm/schema.py +13 -13
  409. esphome/components/opentherm/validate.py +1 -1
  410. esphome/components/openthread/__init__.py +146 -0
  411. esphome/components/openthread/const.py +10 -0
  412. esphome/components/openthread/openthread.cpp +206 -0
  413. esphome/components/openthread/openthread.h +68 -0
  414. esphome/components/openthread/openthread_esp.cpp +164 -0
  415. esphome/components/openthread/tlv.py +58 -0
  416. esphome/components/openthread_info/__init__.py +0 -0
  417. esphome/components/openthread_info/openthread_info_text_sensor.cpp +24 -0
  418. esphome/components/openthread_info/openthread_info_text_sensor.h +218 -0
  419. esphome/components/openthread_info/text_sensor.py +105 -0
  420. esphome/components/output/float_output.cpp +1 -1
  421. esphome/components/output/switch/output_switch.cpp +1 -1
  422. esphome/components/packet_transport/packet_transport.cpp +6 -4
  423. esphome/components/pca6416a/pca6416a.cpp +2 -2
  424. esphome/components/pca9554/pca9554.cpp +6 -4
  425. esphome/components/pca9685/pca9685_output.cpp +12 -8
  426. esphome/components/pcd8544/pcd_8544.cpp +1 -1
  427. esphome/components/pcf85063/pcf85063.cpp +2 -2
  428. esphome/components/pcf8563/pcf8563.cpp +2 -2
  429. esphome/components/pcf8574/pcf8574.cpp +2 -2
  430. esphome/components/pid/pid_climate.cpp +8 -5
  431. esphome/components/pid/pid_climate.h +1 -1
  432. esphome/components/pid/sensor/pid_climate_sensor.cpp +1 -1
  433. esphome/components/pipsolar/output/pipsolar_output.cpp +1 -1
  434. esphome/components/pipsolar/pipsolar.cpp +3 -3
  435. esphome/components/pm1006/pm1006.cpp +3 -7
  436. esphome/components/pm1006/pm1006.h +4 -1
  437. esphome/components/pm2005/pm2005.cpp +12 -13
  438. esphome/components/pm2005/sensor.py +1 -1
  439. esphome/components/pmsa003i/pmsa003i.cpp +2 -2
  440. esphome/components/pmsx003/pmsx003.cpp +0 -4
  441. esphome/components/pmsx003/pmsx003.h +5 -2
  442. esphome/components/pmwcs3/pmwcs3.cpp +9 -13
  443. esphome/components/pmwcs3/pmwcs3.h +0 -1
  444. esphome/components/pn532/pn532.cpp +7 -7
  445. esphome/components/pn532/pn532.h +1 -1
  446. esphome/components/pn532_spi/pn532_spi.cpp +1 -1
  447. esphome/components/pn7150/pn7150.cpp +4 -4
  448. esphome/components/pn7160/pn7160.cpp +4 -4
  449. esphome/components/power_supply/power_supply.cpp +6 -4
  450. esphome/components/power_supply/power_supply.h +1 -1
  451. esphome/components/psram/__init__.py +59 -35
  452. esphome/components/pulse_counter/pulse_counter_sensor.cpp +7 -4
  453. esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +8 -5
  454. esphome/components/pylontech/pylontech.cpp +2 -2
  455. esphome/components/pylontech/sensor/pylontech_sensor.cpp +4 -2
  456. esphome/components/pylontech/text_sensor/pylontech_text_sensor.cpp +4 -2
  457. esphome/components/pzemac/pzemac.cpp +4 -2
  458. esphome/components/pzemdc/pzemdc.cpp +4 -2
  459. esphome/components/qmc5883l/qmc5883l.cpp +2 -2
  460. esphome/components/qmp6988/qmp6988.cpp +2 -2
  461. esphome/components/qmp6988/qmp6988.h +1 -1
  462. esphome/components/qr_code/qr_code.cpp +5 -3
  463. esphome/components/qspi_dbi/qspi_dbi.cpp +1 -1
  464. esphome/components/qwiic_pir/qwiic_pir.cpp +26 -28
  465. esphome/components/rc522/rc522.cpp +5 -5
  466. esphome/components/rdm6300/rdm6300.cpp +1 -0
  467. esphome/components/remote_receiver/__init__.py +10 -2
  468. esphome/components/remote_receiver/remote_receiver_esp32.cpp +22 -12
  469. esphome/components/remote_receiver/remote_receiver_esp8266.cpp +10 -7
  470. esphome/components/remote_receiver/remote_receiver_libretiny.cpp +10 -7
  471. esphome/components/remote_transmitter/__init__.py +10 -2
  472. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +10 -6
  473. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +5 -3
  474. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +5 -3
  475. esphome/components/resistance/resistance_sensor.cpp +6 -3
  476. esphome/components/restart/button/restart_button.cpp +1 -1
  477. esphome/components/restart/switch/restart_switch.cpp +1 -1
  478. esphome/components/rotary_encoder/rotary_encoder.cpp +2 -2
  479. esphome/components/rp2040/__init__.py +7 -0
  480. esphome/components/rp2040/core.cpp +8 -1
  481. esphome/components/rp2040/gpio.cpp +26 -9
  482. esphome/components/rp2040/preferences.cpp +3 -3
  483. esphome/components/rp2040_pio_led_strip/led_strip.cpp +11 -8
  484. esphome/components/rp2040_pio_led_strip/light.py +1 -1
  485. esphome/components/rp2040_pwm/rp2040_pwm.cpp +1 -1
  486. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +1 -1
  487. esphome/components/rtttl/rtttl.cpp +11 -9
  488. esphome/components/safe_mode/button/safe_mode_button.cpp +1 -1
  489. esphome/components/safe_mode/safe_mode.cpp +9 -8
  490. esphome/components/safe_mode/switch/safe_mode_switch.cpp +1 -1
  491. esphome/components/scd30/scd30.cpp +11 -8
  492. esphome/components/scd4x/scd4x.cpp +12 -8
  493. esphome/components/sdl/display.py +40 -0
  494. esphome/components/sdl/sdl_esphome.cpp +2 -2
  495. esphome/components/sdl/sdl_esphome.h +8 -0
  496. esphome/components/sdm_meter/sdm_meter.cpp +5 -2
  497. esphome/components/sdp3x/sdp3x.cpp +11 -11
  498. esphome/components/sds011/sds011.cpp +5 -6
  499. esphome/components/sds011/sds011.h +4 -1
  500. esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +3 -2
  501. esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +1 -0
  502. esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +3 -2
  503. esphome/components/selec_meter/selec_meter.cpp +5 -2
  504. esphome/components/select/__init__.py +1 -0
  505. esphome/components/sen0321/sen0321.cpp +2 -2
  506. esphome/components/sen21231/sen21231.cpp +1 -1
  507. esphome/components/sen5x/sen5x.cpp +10 -7
  508. esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
  509. esphome/components/sensirion_common/i2c_sensirion.h +1 -0
  510. esphome/components/sensor/__init__.py +11 -1
  511. esphome/components/sensor/filter.h +1 -1
  512. esphome/components/sensor/sensor.h +9 -5
  513. esphome/components/servo/servo.cpp +12 -9
  514. esphome/components/servo/servo.h +1 -1
  515. esphome/components/sfa30/sfa30.cpp +1 -1
  516. esphome/components/sgp30/sgp30.cpp +10 -8
  517. esphome/components/sgp4x/sgp4x.cpp +49 -61
  518. esphome/components/sgp4x/sgp4x.h +0 -1
  519. esphome/components/shelly_dimmer/shelly_dimmer.cpp +11 -7
  520. esphome/components/sht3xd/sht3xd.cpp +1 -1
  521. esphome/components/sht4x/sht4x.cpp +2 -2
  522. esphome/components/shtcx/shtcx.cpp +13 -16
  523. esphome/components/shutdown/button/shutdown_button.cpp +1 -1
  524. esphome/components/shutdown/switch/shutdown_switch.cpp +1 -1
  525. esphome/components/sim800l/sim800l.cpp +2 -2
  526. esphome/components/slow_pwm/slow_pwm_output.cpp +4 -2
  527. esphome/components/sm16716/sm16716.cpp +1 -1
  528. esphome/components/sm2135/sm2135.cpp +1 -1
  529. esphome/components/sm2235/sm2235.cpp +5 -3
  530. esphome/components/sm2335/sm2335.cpp +5 -3
  531. esphome/components/sml/sml.cpp +1 -1
  532. esphome/components/sn74hc165/sn74hc165.cpp +1 -2
  533. esphome/components/sn74hc595/sn74hc595.cpp +1 -2
  534. esphome/components/sntp/sntp_component.cpp +1 -1
  535. esphome/components/socket/__init__.py +2 -0
  536. esphome/components/socket/bsd_sockets_impl.cpp +51 -7
  537. esphome/components/socket/lwip_raw_tcp_impl.cpp +5 -0
  538. esphome/components/socket/lwip_sockets_impl.cpp +51 -7
  539. esphome/components/socket/socket.cpp +31 -0
  540. esphome/components/socket/socket.h +27 -1
  541. esphome/components/sonoff_d1/sonoff_d1.cpp +7 -4
  542. esphome/components/sonoff_d1/sonoff_d1.h +2 -2
  543. esphome/components/sound_level/sound_level.cpp +4 -2
  544. esphome/components/speaker/media_player/__init__.py +3 -0
  545. esphome/components/speaker/media_player/speaker_media_player.cpp +1 -3
  546. esphome/components/speaker/media_player/speaker_media_player.h +6 -0
  547. esphome/components/spi/__init__.py +10 -2
  548. esphome/components/spi/spi.cpp +4 -4
  549. esphome/components/spi_device/spi_device.cpp +1 -2
  550. esphome/components/sprinkler/sprinkler.cpp +9 -6
  551. esphome/components/sps30/sps30.cpp +16 -15
  552. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  553. esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +11 -8
  554. esphome/components/ssd1306_spi/ssd1306_spi.cpp +10 -7
  555. esphome/components/ssd1322_base/ssd1322_base.cpp +1 -1
  556. esphome/components/ssd1322_spi/ssd1322_spi.cpp +1 -1
  557. esphome/components/ssd1325_base/ssd1325_base.cpp +1 -1
  558. esphome/components/ssd1325_spi/ssd1325_spi.cpp +1 -1
  559. esphome/components/ssd1327_base/ssd1327_base.cpp +1 -1
  560. esphome/components/ssd1327_i2c/ssd1327_i2c.cpp +2 -2
  561. esphome/components/ssd1327_spi/ssd1327_spi.cpp +1 -1
  562. esphome/components/ssd1331_base/ssd1331_base.cpp +1 -1
  563. esphome/components/ssd1331_spi/ssd1331_spi.cpp +1 -1
  564. esphome/components/ssd1351_base/ssd1351_base.cpp +1 -1
  565. esphome/components/ssd1351_spi/ssd1351_spi.cpp +1 -1
  566. esphome/components/st7567_base/st7567_base.cpp +3 -3
  567. esphome/components/st7567_i2c/st7567_i2c.cpp +7 -5
  568. esphome/components/st7567_spi/st7567_spi.cpp +1 -1
  569. esphome/components/st7701s/st7701s.cpp +4 -2
  570. esphome/components/st7735/st7735.cpp +3 -3
  571. esphome/components/st7789v/st7789v.cpp +10 -7
  572. esphome/components/st7920/st7920.cpp +6 -4
  573. esphome/components/statsd/statsd.cpp +9 -5
  574. esphome/components/status_led/light/status_led_light.cpp +1 -1
  575. esphome/components/status_led/status_led.cpp +1 -1
  576. esphome/components/stepper/stepper.h +5 -3
  577. esphome/components/sts3x/sts3x.cpp +2 -2
  578. esphome/components/switch/__init__.py +1 -0
  579. esphome/components/switch/switch.cpp +18 -12
  580. esphome/components/switch/switch.h +1 -1
  581. esphome/components/sx1509/__init__.py +53 -20
  582. esphome/components/sx1509/sx1509.cpp +29 -5
  583. esphome/components/sx1509/sx1509.h +9 -1
  584. esphome/components/t6615/t6615.cpp +1 -0
  585. esphome/components/tc74/tc74.cpp +1 -1
  586. esphome/components/tca9548a/tca9548a.cpp +1 -1
  587. esphome/components/tca9555/tca9555.cpp +2 -2
  588. esphome/components/tcs34725/tcs34725.cpp +4 -4
  589. esphome/components/tee501/tee501.cpp +3 -2
  590. esphome/components/tem3200/tem3200.cpp +5 -6
  591. esphome/components/template/alarm_control_panel/__init__.py +6 -0
  592. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +38 -12
  593. esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +3 -1
  594. esphome/components/template/cover/template_cover.cpp +1 -1
  595. esphome/components/template/select/template_select.cpp +6 -4
  596. esphome/components/template/text/template_text.cpp +2 -3
  597. esphome/components/template/valve/template_valve.cpp +5 -3
  598. esphome/components/text/__init__.py +10 -11
  599. esphome/components/text_sensor/__init__.py +1 -0
  600. esphome/components/thermostat/thermostat_climate.cpp +67 -43
  601. esphome/components/time/__init__.py +1 -2
  602. esphome/components/time_based/time_based_cover.cpp +4 -2
  603. esphome/components/tlc59208f/tlc59208f_output.cpp +8 -6
  604. esphome/components/tm1621/tm1621.cpp +3 -3
  605. esphome/components/tm1637/tm1637.cpp +9 -7
  606. esphome/components/tm1638/tm1638.cpp +7 -5
  607. esphome/components/tm1651/tm1651.cpp +2 -2
  608. esphome/components/tmp102/tmp102.cpp +1 -3
  609. esphome/components/tmp102/tmp102.h +0 -3
  610. esphome/components/tmp1075/tmp1075.cpp +12 -9
  611. esphome/components/tmp117/tmp117.cpp +2 -2
  612. esphome/components/tof10120/tof10120_sensor.cpp +2 -2
  613. esphome/components/tormatic/tormatic_cover.cpp +4 -2
  614. esphome/components/tsl2561/tsl2561.cpp +7 -5
  615. esphome/components/tsl2591/tsl2591.cpp +25 -27
  616. esphome/components/tt21100/touchscreen/tt21100.cpp +1 -1
  617. esphome/components/ttp229_bsf/ttp229_bsf.cpp +1 -1
  618. esphome/components/ttp229_lsf/ttp229_lsf.cpp +2 -2
  619. esphome/components/tuya/select/tuya_select.cpp +5 -3
  620. esphome/components/tx20/tx20.cpp +3 -3
  621. esphome/components/uart/__init__.py +4 -5
  622. esphome/components/uart/button/uart_button.cpp +1 -1
  623. esphome/components/uart/switch/uart_switch.cpp +2 -2
  624. esphome/components/uart/uart.cpp +2 -2
  625. esphome/components/uart/uart_component_esp32_arduino.cpp +8 -6
  626. esphome/components/uart/uart_component_esp8266.cpp +9 -7
  627. esphome/components/uart/uart_component_esp_idf.cpp +9 -7
  628. esphome/components/uart/uart_component_host.cpp +11 -8
  629. esphome/components/uart/uart_component_libretiny.cpp +8 -6
  630. esphome/components/uart/uart_component_rp2040.cpp +8 -6
  631. esphome/components/udp/udp_component.cpp +9 -5
  632. esphome/components/ufire_ec/ufire_ec.cpp +5 -3
  633. esphome/components/ufire_ise/ufire_ise.cpp +1 -1
  634. esphome/components/ultrasonic/ultrasonic_sensor.cpp +5 -3
  635. esphome/components/update/__init__.py +1 -0
  636. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
  637. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +4 -2
  638. esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
  639. esphome/components/usb_host/__init__.py +64 -0
  640. esphome/components/usb_host/usb_host.h +116 -0
  641. esphome/components/usb_host/usb_host_client.cpp +394 -0
  642. esphome/components/usb_host/usb_host_component.cpp +35 -0
  643. esphome/components/usb_uart/__init__.py +134 -0
  644. esphome/components/usb_uart/ch34x.cpp +80 -0
  645. esphome/components/usb_uart/cp210x.cpp +126 -0
  646. esphome/components/usb_uart/usb_uart.cpp +328 -0
  647. esphome/components/usb_uart/usb_uart.h +151 -0
  648. esphome/components/valve/__init__.py +1 -0
  649. esphome/components/veml3235/veml3235.cpp +13 -9
  650. esphome/components/veml7700/veml7700.cpp +10 -6
  651. esphome/components/voice_assistant/voice_assistant.cpp +7 -7
  652. esphome/components/wake_on_lan/wake_on_lan.cpp +1 -1
  653. esphome/components/waveshare_epaper/waveshare_epaper.cpp +1 -1
  654. esphome/components/web_server/server_index_v2.h +632 -630
  655. esphome/components/web_server/server_index_v3.h +411 -409
  656. esphome/components/web_server/web_server.cpp +5 -3
  657. esphome/components/web_server_base/web_server_base.cpp +1 -1
  658. esphome/components/web_server_idf/utils.cpp +1 -1
  659. esphome/components/web_server_idf/web_server_idf.cpp +1 -1
  660. esphome/components/weikai/__init__.py +2 -0
  661. esphome/components/weikai/weikai.cpp +23 -21
  662. esphome/components/weikai_i2c/weikai_i2c.cpp +14 -9
  663. esphome/components/weikai_spi/weikai_spi.cpp +11 -6
  664. esphome/components/wiegand/wiegand.cpp +1 -1
  665. esphome/components/wifi/wifi_component.cpp +50 -37
  666. esphome/components/wifi/wifi_component.h +7 -4
  667. esphome/components/wifi/wifi_component_esp32_arduino.cpp +2 -2
  668. esphome/components/wifi/wifi_component_esp8266.cpp +3 -3
  669. esphome/components/wifi/wifi_component_libretiny.cpp +4 -4
  670. esphome/components/wireguard/wireguard.cpp +21 -21
  671. esphome/components/wl_134/text_sensor.py +1 -2
  672. esphome/components/wled/wled_light_effect.cpp +1 -1
  673. esphome/components/x9c/x9c.cpp +5 -3
  674. esphome/components/xgzp68xx/xgzp68xx.cpp +8 -6
  675. esphome/components/xiaomi_cgd1/xiaomi_cgd1.cpp +4 -2
  676. esphome/components/xiaomi_cgdk2/xiaomi_cgdk2.cpp +4 -2
  677. esphome/components/xiaomi_cgg1/xiaomi_cgg1.cpp +4 -2
  678. esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.cpp +1 -1
  679. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.cpp +4 -2
  680. esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.cpp +4 -2
  681. esphome/components/xiaomi_mhoc401/xiaomi_mhoc401.cpp +4 -2
  682. esphome/components/xl9535/xl9535.cpp +2 -2
  683. esphome/components/xpt2046/touchscreen/xpt2046.cpp +12 -11
  684. esphome/components/xpt2046/touchscreen/xpt2046.h +2 -2
  685. esphome/config.py +3 -2
  686. esphome/config_validation.py +46 -17
  687. esphome/const.py +10 -1
  688. esphome/core/__init__.py +37 -18
  689. esphome/core/application.cpp +188 -5
  690. esphome/core/application.h +110 -0
  691. esphome/core/component.h +13 -0
  692. esphome/core/config.py +12 -0
  693. esphome/core/defines.h +10 -2
  694. esphome/core/hal.h +5 -0
  695. esphome/core/helpers.cpp +1 -1
  696. esphome/core/helpers.h +4 -4
  697. esphome/core/log.h +2 -0
  698. esphome/core/log_const_en.h +4 -0
  699. esphome/core/scheduler.cpp +2 -2
  700. esphome/coroutine.py +3 -4
  701. esphome/cpp_generator.py +32 -32
  702. esphome/dashboard/core.py +2 -2
  703. esphome/dashboard/web_server.py +2 -2
  704. esphome/git.py +4 -4
  705. esphome/helpers.py +5 -6
  706. esphome/loader.py +8 -7
  707. esphome/log.py +7 -1
  708. esphome/platformio_api.py +2 -3
  709. esphome/storage_json.py +13 -5
  710. esphome/types.py +12 -13
  711. esphome/util.py +1 -2
  712. esphome/writer.py +5 -3
  713. esphome/yaml_util.py +6 -1
  714. esphome/zeroconf.py +1 -1
  715. {esphome-2025.5.1.dist-info → esphome-2025.6.0b1.dist-info}/METADATA +12 -11
  716. {esphome-2025.5.1.dist-info → esphome-2025.6.0b1.dist-info}/RECORD +720 -667
  717. {esphome-2025.5.1.dist-info → esphome-2025.6.0b1.dist-info}/WHEEL +1 -1
  718. {esphome-2025.5.1.dist-info → esphome-2025.6.0b1.dist-info}/entry_points.txt +0 -0
  719. {esphome-2025.5.1.dist-info → esphome-2025.6.0b1.dist-info}/licenses/LICENSE +0 -0
  720. {esphome-2025.5.1.dist-info → esphome-2025.6.0b1.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,8 @@
3
3
  #include <cerrno>
4
4
  #include <cinttypes>
5
5
  #include <utility>
6
+ #include <functional>
7
+ #include <limits>
6
8
  #include "esphome/components/network/util.h"
7
9
  #include "esphome/core/application.h"
8
10
  #include "esphome/core/entity_base.h"
@@ -29,40 +31,8 @@ namespace api {
29
31
  static const char *const TAG = "api.connection";
30
32
  static const int ESP32_CAMERA_STOP_STREAM = 5000;
31
33
 
32
- // helper for allowing only unique entries in the queue
33
- void DeferredMessageQueue::dmq_push_back_with_dedup_(void *source, send_message_t send_message) {
34
- DeferredMessage item(source, send_message);
35
-
36
- auto iter = std::find_if(this->deferred_queue_.begin(), this->deferred_queue_.end(),
37
- [&item](const DeferredMessage &test) -> bool { return test == item; });
38
-
39
- if (iter != this->deferred_queue_.end()) {
40
- (*iter) = item;
41
- } else {
42
- this->deferred_queue_.push_back(item);
43
- }
44
- }
45
-
46
- void DeferredMessageQueue::process_queue() {
47
- while (!deferred_queue_.empty()) {
48
- DeferredMessage &de = deferred_queue_.front();
49
- if ((this->api_connection_->*(de.send_message_))(de.source_)) {
50
- // O(n) but memory efficiency is more important than speed here which is why std::vector was chosen
51
- deferred_queue_.erase(deferred_queue_.begin());
52
- } else {
53
- break;
54
- }
55
- }
56
- }
57
-
58
- void DeferredMessageQueue::defer(void *source, send_message_t send_message) {
59
- this->dmq_push_back_with_dedup_(source, send_message);
60
- }
61
-
62
34
  APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *parent)
63
- : parent_(parent), deferred_message_queue_(this), initial_state_iterator_(this), list_entities_iterator_(this) {
64
- this->proto_write_buffer_.reserve(64);
65
-
35
+ : parent_(parent), initial_state_iterator_(this), list_entities_iterator_(this) {
66
36
  #if defined(USE_API_PLAINTEXT) && defined(USE_API_NOISE)
67
37
  auto noise_ctx = parent->get_noise_ctx();
68
38
  if (noise_ctx->has_psk()) {
@@ -78,6 +48,9 @@ APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *pa
78
48
  #error "No frame helper defined"
79
49
  #endif
80
50
  }
51
+
52
+ uint32_t APIConnection::get_batch_delay_ms_() const { return this->parent_->get_batch_delay(); }
53
+
81
54
  void APIConnection::start() {
82
55
  this->last_traffic_ = App.get_loop_component_start_time();
83
56
 
@@ -118,7 +91,7 @@ void APIConnection::loop() {
118
91
  // when network is disconnected force disconnect immediately
119
92
  // don't wait for timeout
120
93
  this->on_fatal_error();
121
- ESP_LOGW(TAG, "%s: Network unavailable, disconnecting", this->client_combined_info_.c_str());
94
+ ESP_LOGW(TAG, "%s: Network unavailable; disconnecting", this->client_combined_info_.c_str());
122
95
  return;
123
96
  }
124
97
  if (this->next_close_) {
@@ -135,35 +108,41 @@ void APIConnection::loop() {
135
108
  api_error_to_str(err), errno);
136
109
  return;
137
110
  }
138
- ReadPacketBuffer buffer;
139
- err = this->helper_->read_packet(&buffer);
140
- if (err == APIError::WOULD_BLOCK) {
141
- // pass
142
- } else if (err != APIError::OK) {
143
- on_fatal_error();
144
- if (err == APIError::SOCKET_READ_FAILED && errno == ECONNRESET) {
145
- ESP_LOGW(TAG, "%s: Connection reset", this->client_combined_info_.c_str());
146
- } else if (err == APIError::CONNECTION_CLOSED) {
147
- ESP_LOGW(TAG, "%s: Connection closed", this->client_combined_info_.c_str());
148
- } else {
149
- ESP_LOGW(TAG, "%s: Reading failed: %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
150
- errno);
151
- }
152
- return;
153
- } else {
154
- this->last_traffic_ = App.get_loop_component_start_time();
155
- // read a packet
156
- if (buffer.data_len > 0) {
157
- this->read_message(buffer.data_len, buffer.type, &buffer.container[buffer.data_offset]);
111
+
112
+ // Check if socket has data ready before attempting to read
113
+ if (this->helper_->is_socket_ready()) {
114
+ ReadPacketBuffer buffer;
115
+ err = this->helper_->read_packet(&buffer);
116
+ if (err == APIError::WOULD_BLOCK) {
117
+ // pass
118
+ } else if (err != APIError::OK) {
119
+ on_fatal_error();
120
+ if (err == APIError::SOCKET_READ_FAILED && errno == ECONNRESET) {
121
+ ESP_LOGW(TAG, "%s: Connection reset", this->client_combined_info_.c_str());
122
+ } else if (err == APIError::CONNECTION_CLOSED) {
123
+ ESP_LOGW(TAG, "%s: Connection closed", this->client_combined_info_.c_str());
124
+ } else {
125
+ ESP_LOGW(TAG, "%s: Reading failed: %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
126
+ errno);
127
+ }
128
+ return;
158
129
  } else {
159
- this->read_message(0, buffer.type, nullptr);
130
+ this->last_traffic_ = App.get_loop_component_start_time();
131
+ // read a packet
132
+ if (buffer.data_len > 0) {
133
+ this->read_message(buffer.data_len, buffer.type, &buffer.container[buffer.data_offset]);
134
+ } else {
135
+ this->read_message(0, buffer.type, nullptr);
136
+ }
137
+ if (this->remove_)
138
+ return;
160
139
  }
161
- if (this->remove_)
162
- return;
163
140
  }
164
141
 
165
- if (!this->deferred_message_queue_.empty() && this->helper_->can_write_without_blocking()) {
166
- this->deferred_message_queue_.process_queue();
142
+ // Process deferred batch if scheduled
143
+ if (this->deferred_batch_.batch_scheduled &&
144
+ App.get_loop_component_start_time() - this->deferred_batch_.batch_start_time >= this->get_batch_delay_ms_()) {
145
+ this->process_batch_();
167
146
  }
168
147
 
169
148
  if (!this->list_entities_iterator_.completed())
@@ -178,42 +157,30 @@ void APIConnection::loop() {
178
157
  // Disconnect if not responded within 2.5*keepalive
179
158
  if (now - this->last_traffic_ > (KEEPALIVE_TIMEOUT_MS * 5) / 2) {
180
159
  on_fatal_error();
181
- ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_combined_info_.c_str());
160
+ ESP_LOGW(TAG, "%s is unresponsive; disconnecting", this->client_combined_info_.c_str());
182
161
  }
183
162
  } else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS && now > this->next_ping_retry_) {
184
- ESP_LOGVV(TAG, "Sending keepalive PING...");
185
- this->sent_ping_ = this->send_ping_request(PingRequest());
163
+ ESP_LOGVV(TAG, "Sending keepalive PING");
164
+ this->sent_ping_ = this->send_message(PingRequest());
186
165
  if (!this->sent_ping_) {
187
166
  this->next_ping_retry_ = now + ping_retry_interval;
188
167
  this->ping_retries_++;
168
+ std::string warn_str = str_sprintf("%s: Sending keepalive failed %u time(s);",
169
+ this->client_combined_info_.c_str(), this->ping_retries_);
189
170
  if (this->ping_retries_ >= max_ping_retries) {
190
171
  on_fatal_error();
191
- ESP_LOGE(TAG, "%s: Sending keepalive failed %d time(s). Disconnecting...", this->client_combined_info_.c_str(),
192
- this->ping_retries_);
172
+ ESP_LOGE(TAG, "%s disconnecting", warn_str.c_str());
193
173
  } else if (this->ping_retries_ >= 10) {
194
- ESP_LOGW(TAG, "%s: Sending keepalive failed %d time(s), will retry in %d ms",
195
- this->client_combined_info_.c_str(), this->ping_retries_, ping_retry_interval);
174
+ ESP_LOGW(TAG, "%s retrying in %u ms", warn_str.c_str(), ping_retry_interval);
196
175
  } else {
197
- ESP_LOGD(TAG, "%s: Sending keepalive failed %d time(s), will retry in %d ms",
198
- this->client_combined_info_.c_str(), this->ping_retries_, ping_retry_interval);
176
+ ESP_LOGD(TAG, "%s retrying in %u ms", warn_str.c_str(), ping_retry_interval);
199
177
  }
200
178
  }
201
179
  }
202
180
 
203
181
  #ifdef USE_ESP32_CAMERA
204
182
  if (this->image_reader_.available() && this->helper_->can_write_without_blocking()) {
205
- // Message will use 8 more bytes than the minimum size, and typical
206
- // MTU is 1500. Sometimes users will see as low as 1460 MTU.
207
- // If its IPv6 the header is 40 bytes, and if its IPv4
208
- // the header is 20 bytes. So we have 1460 - 40 = 1420 bytes
209
- // available for the payload. But we also need to add the size of
210
- // the protobuf overhead, which is 8 bytes.
211
- //
212
- // To be safe we pick 1390 bytes as the maximum size
213
- // to send in one go. This is the maximum size of a single packet
214
- // that can be sent over the network.
215
- // This is to avoid fragmentation of the packet.
216
- uint32_t to_send = std::min((size_t) 1390, this->image_reader_.available());
183
+ uint32_t to_send = std::min((size_t) MAX_PACKET_SIZE, this->image_reader_.available());
217
184
  bool done = this->image_reader_.available() == to_send;
218
185
  uint32_t msg_size = 0;
219
186
  ProtoSize::add_fixed_field<4>(msg_size, 1, true);
@@ -251,7 +218,7 @@ void APIConnection::loop() {
251
218
  resp.entity_id = it.entity_id;
252
219
  resp.attribute = it.attribute.value();
253
220
  resp.once = it.once;
254
- if (this->send_subscribe_home_assistant_state_response(resp)) {
221
+ if (this->send_message(resp)) {
255
222
  state_subs_at_++;
256
223
  }
257
224
  }
@@ -266,54 +233,84 @@ DisconnectResponse APIConnection::disconnect(const DisconnectRequest &msg) {
266
233
  // remote initiated disconnect_client
267
234
  // don't close yet, we still need to send the disconnect response
268
235
  // close will happen on next loop
269
- ESP_LOGD(TAG, "%s requested disconnected", this->client_combined_info_.c_str());
236
+ ESP_LOGD(TAG, "%s disconnected", this->client_combined_info_.c_str());
270
237
  this->next_close_ = true;
271
238
  DisconnectResponse resp;
272
239
  return resp;
273
240
  }
274
241
  void APIConnection::on_disconnect_response(const DisconnectResponse &value) {
275
- // pass
242
+ this->helper_->close();
243
+ this->remove_ = true;
244
+ }
245
+
246
+ // Encodes a message to the buffer and returns the total number of bytes used,
247
+ // including header and footer overhead. Returns 0 if the message doesn't fit.
248
+ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint16_t message_type, APIConnection *conn,
249
+ uint32_t remaining_size, bool is_single) {
250
+ // Calculate size
251
+ uint32_t size = 0;
252
+ msg.calculate_size(size);
253
+
254
+ // Calculate total size with padding for buffer allocation
255
+ uint16_t total_size =
256
+ static_cast<uint16_t>(size) + conn->helper_->frame_header_padding() + conn->helper_->frame_footer_size();
257
+
258
+ // Check if it fits
259
+ if (total_size > remaining_size) {
260
+ return 0; // Doesn't fit
261
+ }
262
+
263
+ // Allocate exact buffer space needed (just the payload, not the overhead)
264
+ ProtoWriteBuffer buffer =
265
+ is_single ? conn->allocate_single_message_buffer(size) : conn->allocate_batch_message_buffer(size);
266
+
267
+ // Encode directly into buffer
268
+ msg.encode(buffer);
269
+ return total_size;
276
270
  }
277
271
 
278
272
  #ifdef USE_BINARY_SENSOR
279
- bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor, bool state) {
280
- return this->send_state_with_value_(binary_sensor, &APIConnection::try_send_binary_sensor_state_,
281
- &APIConnection::try_send_binary_sensor_state_, state);
273
+ bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor) {
274
+ return this->schedule_message_(binary_sensor, &APIConnection::try_send_binary_sensor_state,
275
+ BinarySensorStateResponse::MESSAGE_TYPE);
282
276
  }
283
277
  void APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor) {
284
- this->send_info_(static_cast<EntityBase *>(binary_sensor),
285
- reinterpret_cast<send_message_t>(&APIConnection::try_send_binary_sensor_info_));
278
+ this->schedule_message_(binary_sensor, &APIConnection::try_send_binary_sensor_info,
279
+ ListEntitiesBinarySensorResponse::MESSAGE_TYPE);
286
280
  }
287
- bool APIConnection::try_send_binary_sensor_state_(binary_sensor::BinarySensor *binary_sensor) {
288
- return this->try_send_binary_sensor_state_(binary_sensor, binary_sensor->state);
289
- }
290
- bool APIConnection::try_send_binary_sensor_state_(binary_sensor::BinarySensor *binary_sensor, bool state) {
291
- BinarySensorStateResponse msg;
292
- msg.state = state;
293
- msg.missing_state = !binary_sensor->has_state();
294
- msg.key = binary_sensor->get_object_id_hash();
295
- return this->send_binary_sensor_state_response(msg);
281
+
282
+ uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
283
+ bool is_single) {
284
+ auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity);
285
+ BinarySensorStateResponse resp;
286
+ resp.state = binary_sensor->state;
287
+ resp.missing_state = !binary_sensor->has_state();
288
+ resp.key = binary_sensor->get_object_id_hash();
289
+ return encode_message_to_buffer(resp, BinarySensorStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
296
290
  }
297
- bool APIConnection::try_send_binary_sensor_info_(binary_sensor::BinarySensor *binary_sensor) {
291
+
292
+ uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
293
+ bool is_single) {
294
+ auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity);
298
295
  ListEntitiesBinarySensorResponse msg;
299
296
  msg.device_class = binary_sensor->get_device_class();
300
297
  msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor();
301
298
  msg.unique_id = get_default_unique_id("binary_sensor", binary_sensor);
302
- return this->try_send_entity_info_(static_cast<EntityBase *>(binary_sensor), msg,
303
- &APIConnection::send_list_entities_binary_sensor_response);
299
+ fill_entity_info_base(binary_sensor, msg);
300
+ return encode_message_to_buffer(msg, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
304
301
  }
305
302
  #endif
306
303
 
307
304
  #ifdef USE_COVER
308
305
  bool APIConnection::send_cover_state(cover::Cover *cover) {
309
- return this->send_state_(static_cast<EntityBase *>(cover),
310
- reinterpret_cast<send_message_t>(&APIConnection::try_send_cover_state_));
306
+ return this->schedule_message_(cover, &APIConnection::try_send_cover_state, CoverStateResponse::MESSAGE_TYPE);
311
307
  }
312
308
  void APIConnection::send_cover_info(cover::Cover *cover) {
313
- this->send_info_(static_cast<EntityBase *>(cover),
314
- reinterpret_cast<send_message_t>(&APIConnection::try_send_cover_info_));
309
+ this->schedule_message_(cover, &APIConnection::try_send_cover_info, ListEntitiesCoverResponse::MESSAGE_TYPE);
315
310
  }
316
- bool APIConnection::try_send_cover_state_(cover::Cover *cover) {
311
+ uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
312
+ bool is_single) {
313
+ auto *cover = static_cast<cover::Cover *>(entity);
317
314
  CoverStateResponse msg;
318
315
  auto traits = cover->get_traits();
319
316
  msg.legacy_state =
@@ -323,9 +320,11 @@ bool APIConnection::try_send_cover_state_(cover::Cover *cover) {
323
320
  msg.tilt = cover->tilt;
324
321
  msg.current_operation = static_cast<enums::CoverOperation>(cover->current_operation);
325
322
  msg.key = cover->get_object_id_hash();
326
- return this->send_cover_state_response(msg);
323
+ return encode_message_to_buffer(msg, CoverStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
327
324
  }
328
- bool APIConnection::try_send_cover_info_(cover::Cover *cover) {
325
+ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
326
+ bool is_single) {
327
+ auto *cover = static_cast<cover::Cover *>(entity);
329
328
  ListEntitiesCoverResponse msg;
330
329
  auto traits = cover->get_traits();
331
330
  msg.assumed_state = traits.get_is_assumed_state();
@@ -334,8 +333,8 @@ bool APIConnection::try_send_cover_info_(cover::Cover *cover) {
334
333
  msg.supports_stop = traits.get_supports_stop();
335
334
  msg.device_class = cover->get_device_class();
336
335
  msg.unique_id = get_default_unique_id("cover", cover);
337
- return this->try_send_entity_info_(static_cast<EntityBase *>(cover), msg,
338
- &APIConnection::send_list_entities_cover_response);
336
+ fill_entity_info_base(cover, msg);
337
+ return encode_message_to_buffer(msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
339
338
  }
340
339
  void APIConnection::cover_command(const CoverCommandRequest &msg) {
341
340
  cover::Cover *cover = App.get_cover_by_key(msg.key);
@@ -368,14 +367,14 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) {
368
367
 
369
368
  #ifdef USE_FAN
370
369
  bool APIConnection::send_fan_state(fan::Fan *fan) {
371
- return this->send_state_(static_cast<EntityBase *>(fan),
372
- reinterpret_cast<send_message_t>(&APIConnection::try_send_fan_state_));
370
+ return this->schedule_message_(fan, &APIConnection::try_send_fan_state, FanStateResponse::MESSAGE_TYPE);
373
371
  }
374
372
  void APIConnection::send_fan_info(fan::Fan *fan) {
375
- this->send_info_(static_cast<EntityBase *>(fan),
376
- reinterpret_cast<send_message_t>(&APIConnection::try_send_fan_info_));
373
+ this->schedule_message_(fan, &APIConnection::try_send_fan_info, ListEntitiesFanResponse::MESSAGE_TYPE);
377
374
  }
378
- bool APIConnection::try_send_fan_state_(fan::Fan *fan) {
375
+ uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
376
+ bool is_single) {
377
+ auto *fan = static_cast<fan::Fan *>(entity);
379
378
  FanStateResponse msg;
380
379
  auto traits = fan->get_traits();
381
380
  msg.state = fan->state;
@@ -389,9 +388,11 @@ bool APIConnection::try_send_fan_state_(fan::Fan *fan) {
389
388
  if (traits.supports_preset_modes())
390
389
  msg.preset_mode = fan->preset_mode;
391
390
  msg.key = fan->get_object_id_hash();
392
- return this->send_fan_state_response(msg);
391
+ return encode_message_to_buffer(msg, FanStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
393
392
  }
394
- bool APIConnection::try_send_fan_info_(fan::Fan *fan) {
393
+ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
394
+ bool is_single) {
395
+ auto *fan = static_cast<fan::Fan *>(entity);
395
396
  ListEntitiesFanResponse msg;
396
397
  auto traits = fan->get_traits();
397
398
  msg.supports_oscillation = traits.supports_oscillation();
@@ -401,8 +402,8 @@ bool APIConnection::try_send_fan_info_(fan::Fan *fan) {
401
402
  for (auto const &preset : traits.supported_preset_modes())
402
403
  msg.supported_preset_modes.push_back(preset);
403
404
  msg.unique_id = get_default_unique_id("fan", fan);
404
- return this->try_send_entity_info_(static_cast<EntityBase *>(fan), msg,
405
- &APIConnection::send_list_entities_fan_response);
405
+ fill_entity_info_base(fan, msg);
406
+ return encode_message_to_buffer(msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
406
407
  }
407
408
  void APIConnection::fan_command(const FanCommandRequest &msg) {
408
409
  fan::Fan *fan = App.get_fan_by_key(msg.key);
@@ -428,14 +429,14 @@ void APIConnection::fan_command(const FanCommandRequest &msg) {
428
429
 
429
430
  #ifdef USE_LIGHT
430
431
  bool APIConnection::send_light_state(light::LightState *light) {
431
- return this->send_state_(static_cast<EntityBase *>(light),
432
- reinterpret_cast<send_message_t>(&APIConnection::try_send_light_state_));
432
+ return this->schedule_message_(light, &APIConnection::try_send_light_state, LightStateResponse::MESSAGE_TYPE);
433
433
  }
434
434
  void APIConnection::send_light_info(light::LightState *light) {
435
- this->send_info_(static_cast<EntityBase *>(light),
436
- reinterpret_cast<send_message_t>(&APIConnection::try_send_light_info_));
435
+ this->schedule_message_(light, &APIConnection::try_send_light_info, ListEntitiesLightResponse::MESSAGE_TYPE);
437
436
  }
438
- bool APIConnection::try_send_light_state_(light::LightState *light) {
437
+ uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
438
+ bool is_single) {
439
+ auto *light = static_cast<light::LightState *>(entity);
439
440
  LightStateResponse resp;
440
441
  auto traits = light->get_traits();
441
442
  auto values = light->remote_values;
@@ -454,9 +455,11 @@ bool APIConnection::try_send_light_state_(light::LightState *light) {
454
455
  if (light->supports_effects())
455
456
  resp.effect = light->get_effect_name();
456
457
  resp.key = light->get_object_id_hash();
457
- return this->send_light_state_response(resp);
458
+ return encode_message_to_buffer(resp, LightStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
458
459
  }
459
- bool APIConnection::try_send_light_info_(light::LightState *light) {
460
+ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
461
+ bool is_single) {
462
+ auto *light = static_cast<light::LightState *>(entity);
460
463
  ListEntitiesLightResponse msg;
461
464
  auto traits = light->get_traits();
462
465
  for (auto mode : traits.get_supported_color_modes())
@@ -479,8 +482,8 @@ bool APIConnection::try_send_light_info_(light::LightState *light) {
479
482
  }
480
483
  }
481
484
  msg.unique_id = get_default_unique_id("light", light);
482
- return this->try_send_entity_info_(static_cast<EntityBase *>(light), msg,
483
- &APIConnection::send_list_entities_light_response);
485
+ fill_entity_info_base(light, msg);
486
+ return encode_message_to_buffer(msg, ListEntitiesLightResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
484
487
  }
485
488
  void APIConnection::light_command(const LightCommandRequest &msg) {
486
489
  light::LightState *light = App.get_light_by_key(msg.key);
@@ -520,26 +523,26 @@ void APIConnection::light_command(const LightCommandRequest &msg) {
520
523
  #endif
521
524
 
522
525
  #ifdef USE_SENSOR
523
- bool APIConnection::send_sensor_state(sensor::Sensor *sensor, float state) {
524
- return this->send_state_with_value_(sensor, &APIConnection::try_send_sensor_state_,
525
- &APIConnection::try_send_sensor_state_, state);
526
+ bool APIConnection::send_sensor_state(sensor::Sensor *sensor) {
527
+ return this->schedule_message_(sensor, &APIConnection::try_send_sensor_state, SensorStateResponse::MESSAGE_TYPE);
526
528
  }
527
529
  void APIConnection::send_sensor_info(sensor::Sensor *sensor) {
528
- this->send_info_(static_cast<EntityBase *>(sensor),
529
- reinterpret_cast<send_message_t>(&APIConnection::try_send_sensor_info_));
530
+ this->schedule_message_(sensor, &APIConnection::try_send_sensor_info, ListEntitiesSensorResponse::MESSAGE_TYPE);
530
531
  }
531
- bool APIConnection::try_send_sensor_state_(sensor::Sensor *sensor) {
532
- return this->try_send_sensor_state_(sensor, sensor->state);
533
- }
534
- bool APIConnection::try_send_sensor_state_(sensor::Sensor *sensor, float state) {
532
+
533
+ uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
534
+ bool is_single) {
535
+ auto *sensor = static_cast<sensor::Sensor *>(entity);
535
536
  SensorStateResponse resp;
536
- resp.state = state;
537
+ resp.state = sensor->state;
537
538
  resp.missing_state = !sensor->has_state();
538
-
539
539
  resp.key = sensor->get_object_id_hash();
540
- return this->send_sensor_state_response(resp);
540
+ return encode_message_to_buffer(resp, SensorStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
541
541
  }
542
- bool APIConnection::try_send_sensor_info_(sensor::Sensor *sensor) {
542
+
543
+ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
544
+ bool is_single) {
545
+ auto *sensor = static_cast<sensor::Sensor *>(entity);
543
546
  ListEntitiesSensorResponse msg;
544
547
  msg.unit_of_measurement = sensor->get_unit_of_measurement();
545
548
  msg.accuracy_decimals = sensor->get_accuracy_decimals();
@@ -549,37 +552,37 @@ bool APIConnection::try_send_sensor_info_(sensor::Sensor *sensor) {
549
552
  msg.unique_id = sensor->unique_id();
550
553
  if (msg.unique_id.empty())
551
554
  msg.unique_id = get_default_unique_id("sensor", sensor);
552
- return this->try_send_entity_info_(static_cast<EntityBase *>(sensor), msg,
553
- &APIConnection::send_list_entities_sensor_response);
555
+ fill_entity_info_base(sensor, msg);
556
+ return encode_message_to_buffer(msg, ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
554
557
  }
555
558
  #endif
556
559
 
557
560
  #ifdef USE_SWITCH
558
- bool APIConnection::send_switch_state(switch_::Switch *a_switch, bool state) {
559
- return this->send_state_with_value_(a_switch, &APIConnection::try_send_switch_state_,
560
- &APIConnection::try_send_switch_state_, state);
561
+ bool APIConnection::send_switch_state(switch_::Switch *a_switch) {
562
+ return this->schedule_message_(a_switch, &APIConnection::try_send_switch_state, SwitchStateResponse::MESSAGE_TYPE);
561
563
  }
562
564
  void APIConnection::send_switch_info(switch_::Switch *a_switch) {
563
- this->send_info_(static_cast<EntityBase *>(a_switch),
564
- reinterpret_cast<send_message_t>(&APIConnection::try_send_switch_info_));
565
+ this->schedule_message_(a_switch, &APIConnection::try_send_switch_info, ListEntitiesSwitchResponse::MESSAGE_TYPE);
565
566
  }
566
- bool APIConnection::try_send_switch_state_(switch_::Switch *a_switch) {
567
- return this->try_send_switch_state_(a_switch, a_switch->state);
568
- }
569
- bool APIConnection::try_send_switch_state_(switch_::Switch *a_switch, bool state) {
570
- SwitchStateResponse resp;
571
- resp.state = state;
572
567
 
568
+ uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
569
+ bool is_single) {
570
+ auto *a_switch = static_cast<switch_::Switch *>(entity);
571
+ SwitchStateResponse resp;
572
+ resp.state = a_switch->state;
573
573
  resp.key = a_switch->get_object_id_hash();
574
- return this->send_switch_state_response(resp);
574
+ return encode_message_to_buffer(resp, SwitchStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
575
575
  }
576
- bool APIConnection::try_send_switch_info_(switch_::Switch *a_switch) {
576
+
577
+ uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
578
+ bool is_single) {
579
+ auto *a_switch = static_cast<switch_::Switch *>(entity);
577
580
  ListEntitiesSwitchResponse msg;
578
581
  msg.assumed_state = a_switch->assumed_state();
579
582
  msg.device_class = a_switch->get_device_class();
580
583
  msg.unique_id = get_default_unique_id("switch", a_switch);
581
- return this->try_send_entity_info_(static_cast<EntityBase *>(a_switch), msg,
582
- &APIConnection::send_list_entities_switch_response);
584
+ fill_entity_info_base(a_switch, msg);
585
+ return encode_message_to_buffer(msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
583
586
  }
584
587
  void APIConnection::switch_command(const SwitchCommandRequest &msg) {
585
588
  switch_::Switch *a_switch = App.get_switch_by_key(msg.key);
@@ -595,46 +598,44 @@ void APIConnection::switch_command(const SwitchCommandRequest &msg) {
595
598
  #endif
596
599
 
597
600
  #ifdef USE_TEXT_SENSOR
598
- bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor, std::string state) {
599
- return this->send_state_with_value_(text_sensor, &APIConnection::try_send_text_sensor_state_,
600
- &APIConnection::try_send_text_sensor_state_, std::move(state));
601
+ bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor) {
602
+ return this->schedule_message_(text_sensor, &APIConnection::try_send_text_sensor_state,
603
+ TextSensorStateResponse::MESSAGE_TYPE);
601
604
  }
602
605
  void APIConnection::send_text_sensor_info(text_sensor::TextSensor *text_sensor) {
603
- this->send_info_(static_cast<EntityBase *>(text_sensor),
604
- reinterpret_cast<send_message_t>(&APIConnection::try_send_text_sensor_info_));
605
- }
606
- bool APIConnection::try_send_text_sensor_state_(text_sensor::TextSensor *text_sensor) {
607
- return this->try_send_text_sensor_state_(text_sensor, text_sensor->state);
606
+ this->schedule_message_(text_sensor, &APIConnection::try_send_text_sensor_info,
607
+ ListEntitiesTextSensorResponse::MESSAGE_TYPE);
608
608
  }
609
- bool APIConnection::try_send_text_sensor_state_(text_sensor::TextSensor *text_sensor, std::string state) {
609
+
610
+ uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
611
+ bool is_single) {
612
+ auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity);
610
613
  TextSensorStateResponse resp;
611
- resp.state = std::move(state);
614
+ resp.state = text_sensor->state;
612
615
  resp.missing_state = !text_sensor->has_state();
613
-
614
616
  resp.key = text_sensor->get_object_id_hash();
615
- return this->send_text_sensor_state_response(resp);
617
+ return encode_message_to_buffer(resp, TextSensorStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
616
618
  }
617
- bool APIConnection::try_send_text_sensor_info_(text_sensor::TextSensor *text_sensor) {
619
+ uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
620
+ bool is_single) {
621
+ auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity);
618
622
  ListEntitiesTextSensorResponse msg;
619
623
  msg.device_class = text_sensor->get_device_class();
620
624
  msg.unique_id = text_sensor->unique_id();
621
625
  if (msg.unique_id.empty())
622
626
  msg.unique_id = get_default_unique_id("text_sensor", text_sensor);
623
- return this->try_send_entity_info_(static_cast<EntityBase *>(text_sensor), msg,
624
- &APIConnection::send_list_entities_text_sensor_response);
627
+ fill_entity_info_base(text_sensor, msg);
628
+ return encode_message_to_buffer(msg, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
625
629
  }
626
630
  #endif
627
631
 
628
632
  #ifdef USE_CLIMATE
629
633
  bool APIConnection::send_climate_state(climate::Climate *climate) {
630
- return this->send_state_(static_cast<EntityBase *>(climate),
631
- reinterpret_cast<send_message_t>(&APIConnection::try_send_climate_state_));
634
+ return this->schedule_message_(climate, &APIConnection::try_send_climate_state, ClimateStateResponse::MESSAGE_TYPE);
632
635
  }
633
- void APIConnection::send_climate_info(climate::Climate *climate) {
634
- this->send_info_(static_cast<EntityBase *>(climate),
635
- reinterpret_cast<send_message_t>(&APIConnection::try_send_climate_info_));
636
- }
637
- bool APIConnection::try_send_climate_state_(climate::Climate *climate) {
636
+ uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
637
+ bool is_single) {
638
+ auto *climate = static_cast<climate::Climate *>(entity);
638
639
  ClimateStateResponse resp;
639
640
  resp.key = climate->get_object_id_hash();
640
641
  auto traits = climate->get_traits();
@@ -663,9 +664,14 @@ bool APIConnection::try_send_climate_state_(climate::Climate *climate) {
663
664
  resp.current_humidity = climate->current_humidity;
664
665
  if (traits.get_supports_target_humidity())
665
666
  resp.target_humidity = climate->target_humidity;
666
- return this->send_climate_state_response(resp);
667
+ return encode_message_to_buffer(resp, ClimateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
668
+ }
669
+ void APIConnection::send_climate_info(climate::Climate *climate) {
670
+ this->schedule_message_(climate, &APIConnection::try_send_climate_info, ListEntitiesClimateResponse::MESSAGE_TYPE);
667
671
  }
668
- bool APIConnection::try_send_climate_info_(climate::Climate *climate) {
672
+ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
673
+ bool is_single) {
674
+ auto *climate = static_cast<climate::Climate *>(entity);
669
675
  ListEntitiesClimateResponse msg;
670
676
  auto traits = climate->get_traits();
671
677
  msg.supports_current_temperature = traits.get_supports_current_temperature();
@@ -693,8 +699,8 @@ bool APIConnection::try_send_climate_info_(climate::Climate *climate) {
693
699
  for (auto swing_mode : traits.get_supported_swing_modes())
694
700
  msg.supported_swing_modes.push_back(static_cast<enums::ClimateSwingMode>(swing_mode));
695
701
  msg.unique_id = get_default_unique_id("climate", climate);
696
- return this->try_send_entity_info_(static_cast<EntityBase *>(climate), msg,
697
- &APIConnection::send_list_entities_climate_response);
702
+ fill_entity_info_base(climate, msg);
703
+ return encode_message_to_buffer(msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
698
704
  }
699
705
  void APIConnection::climate_command(const ClimateCommandRequest &msg) {
700
706
  climate::Climate *climate = App.get_climate_by_key(msg.key);
@@ -727,26 +733,26 @@ void APIConnection::climate_command(const ClimateCommandRequest &msg) {
727
733
  #endif
728
734
 
729
735
  #ifdef USE_NUMBER
730
- bool APIConnection::send_number_state(number::Number *number, float state) {
731
- return this->send_state_with_value_(number, &APIConnection::try_send_number_state_,
732
- &APIConnection::try_send_number_state_, state);
736
+ bool APIConnection::send_number_state(number::Number *number) {
737
+ return this->schedule_message_(number, &APIConnection::try_send_number_state, NumberStateResponse::MESSAGE_TYPE);
733
738
  }
734
739
  void APIConnection::send_number_info(number::Number *number) {
735
- this->send_info_(static_cast<EntityBase *>(number),
736
- reinterpret_cast<send_message_t>(&APIConnection::try_send_number_info_));
737
- }
738
- bool APIConnection::try_send_number_state_(number::Number *number) {
739
- return this->try_send_number_state_(number, number->state);
740
+ this->schedule_message_(number, &APIConnection::try_send_number_info, ListEntitiesNumberResponse::MESSAGE_TYPE);
740
741
  }
741
- bool APIConnection::try_send_number_state_(number::Number *number, float state) {
742
+
743
+ uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
744
+ bool is_single) {
745
+ auto *number = static_cast<number::Number *>(entity);
742
746
  NumberStateResponse resp;
743
- resp.state = state;
747
+ resp.state = number->state;
744
748
  resp.missing_state = !number->has_state();
745
-
746
749
  resp.key = number->get_object_id_hash();
747
- return this->send_number_state_response(resp);
750
+ return encode_message_to_buffer(resp, NumberStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
748
751
  }
749
- bool APIConnection::try_send_number_info_(number::Number *number) {
752
+
753
+ uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
754
+ bool is_single) {
755
+ auto *number = static_cast<number::Number *>(entity);
750
756
  ListEntitiesNumberResponse msg;
751
757
  msg.unit_of_measurement = number->traits.get_unit_of_measurement();
752
758
  msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode());
@@ -755,8 +761,8 @@ bool APIConnection::try_send_number_info_(number::Number *number) {
755
761
  msg.max_value = number->traits.get_max_value();
756
762
  msg.step = number->traits.get_step();
757
763
  msg.unique_id = get_default_unique_id("number", number);
758
- return this->try_send_entity_info_(static_cast<EntityBase *>(number), msg,
759
- &APIConnection::send_list_entities_number_response);
764
+ fill_entity_info_base(number, msg);
765
+ return encode_message_to_buffer(msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
760
766
  }
761
767
  void APIConnection::number_command(const NumberCommandRequest &msg) {
762
768
  number::Number *number = App.get_number_by_key(msg.key);
@@ -771,28 +777,29 @@ void APIConnection::number_command(const NumberCommandRequest &msg) {
771
777
 
772
778
  #ifdef USE_DATETIME_DATE
773
779
  bool APIConnection::send_date_state(datetime::DateEntity *date) {
774
- return this->send_state_(static_cast<EntityBase *>(date),
775
- reinterpret_cast<send_message_t>(&APIConnection::try_send_date_state_));
776
- }
777
- void APIConnection::send_date_info(datetime::DateEntity *date) {
778
- this->send_info_(static_cast<EntityBase *>(date),
779
- reinterpret_cast<send_message_t>(&APIConnection::try_send_date_info_));
780
+ return this->schedule_message_(date, &APIConnection::try_send_date_state, DateStateResponse::MESSAGE_TYPE);
780
781
  }
781
- bool APIConnection::try_send_date_state_(datetime::DateEntity *date) {
782
+ uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
783
+ bool is_single) {
784
+ auto *date = static_cast<datetime::DateEntity *>(entity);
782
785
  DateStateResponse resp;
783
786
  resp.missing_state = !date->has_state();
784
787
  resp.year = date->year;
785
788
  resp.month = date->month;
786
789
  resp.day = date->day;
787
-
788
790
  resp.key = date->get_object_id_hash();
789
- return this->send_date_state_response(resp);
791
+ return encode_message_to_buffer(resp, DateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
790
792
  }
791
- bool APIConnection::try_send_date_info_(datetime::DateEntity *date) {
793
+ void APIConnection::send_date_info(datetime::DateEntity *date) {
794
+ this->schedule_message_(date, &APIConnection::try_send_date_info, ListEntitiesDateResponse::MESSAGE_TYPE);
795
+ }
796
+ uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
797
+ bool is_single) {
798
+ auto *date = static_cast<datetime::DateEntity *>(entity);
792
799
  ListEntitiesDateResponse msg;
793
800
  msg.unique_id = get_default_unique_id("date", date);
794
- return this->try_send_entity_info_(static_cast<EntityBase *>(date), msg,
795
- &APIConnection::send_list_entities_date_response);
801
+ fill_entity_info_base(date, msg);
802
+ return encode_message_to_buffer(msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
796
803
  }
797
804
  void APIConnection::date_command(const DateCommandRequest &msg) {
798
805
  datetime::DateEntity *date = App.get_date_by_key(msg.key);
@@ -807,28 +814,29 @@ void APIConnection::date_command(const DateCommandRequest &msg) {
807
814
 
808
815
  #ifdef USE_DATETIME_TIME
809
816
  bool APIConnection::send_time_state(datetime::TimeEntity *time) {
810
- return this->send_state_(static_cast<EntityBase *>(time),
811
- reinterpret_cast<send_message_t>(&APIConnection::try_send_time_state_));
812
- }
813
- void APIConnection::send_time_info(datetime::TimeEntity *time) {
814
- this->send_info_(static_cast<EntityBase *>(time),
815
- reinterpret_cast<send_message_t>(&APIConnection::try_send_time_info_));
817
+ return this->schedule_message_(time, &APIConnection::try_send_time_state, TimeStateResponse::MESSAGE_TYPE);
816
818
  }
817
- bool APIConnection::try_send_time_state_(datetime::TimeEntity *time) {
819
+ uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
820
+ bool is_single) {
821
+ auto *time = static_cast<datetime::TimeEntity *>(entity);
818
822
  TimeStateResponse resp;
819
823
  resp.missing_state = !time->has_state();
820
824
  resp.hour = time->hour;
821
825
  resp.minute = time->minute;
822
826
  resp.second = time->second;
823
-
824
827
  resp.key = time->get_object_id_hash();
825
- return this->send_time_state_response(resp);
828
+ return encode_message_to_buffer(resp, TimeStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
829
+ }
830
+ void APIConnection::send_time_info(datetime::TimeEntity *time) {
831
+ this->schedule_message_(time, &APIConnection::try_send_time_info, ListEntitiesTimeResponse::MESSAGE_TYPE);
826
832
  }
827
- bool APIConnection::try_send_time_info_(datetime::TimeEntity *time) {
833
+ uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
834
+ bool is_single) {
835
+ auto *time = static_cast<datetime::TimeEntity *>(entity);
828
836
  ListEntitiesTimeResponse msg;
829
837
  msg.unique_id = get_default_unique_id("time", time);
830
- return this->try_send_entity_info_(static_cast<EntityBase *>(time), msg,
831
- &APIConnection::send_list_entities_time_response);
838
+ fill_entity_info_base(time, msg);
839
+ return encode_message_to_buffer(msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
832
840
  }
833
841
  void APIConnection::time_command(const TimeCommandRequest &msg) {
834
842
  datetime::TimeEntity *time = App.get_time_by_key(msg.key);
@@ -843,29 +851,31 @@ void APIConnection::time_command(const TimeCommandRequest &msg) {
843
851
 
844
852
  #ifdef USE_DATETIME_DATETIME
845
853
  bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) {
846
- return this->send_state_(static_cast<EntityBase *>(datetime),
847
- reinterpret_cast<send_message_t>(&APIConnection::try_send_datetime_state_));
854
+ return this->schedule_message_(datetime, &APIConnection::try_send_datetime_state,
855
+ DateTimeStateResponse::MESSAGE_TYPE);
848
856
  }
849
- void APIConnection::send_datetime_info(datetime::DateTimeEntity *datetime) {
850
- this->send_info_(static_cast<EntityBase *>(datetime),
851
- reinterpret_cast<send_message_t>(&APIConnection::try_send_datetime_info_));
852
- }
853
- bool APIConnection::try_send_datetime_state_(datetime::DateTimeEntity *datetime) {
857
+ uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
858
+ bool is_single) {
859
+ auto *datetime = static_cast<datetime::DateTimeEntity *>(entity);
854
860
  DateTimeStateResponse resp;
855
861
  resp.missing_state = !datetime->has_state();
856
862
  if (datetime->has_state()) {
857
863
  ESPTime state = datetime->state_as_esptime();
858
864
  resp.epoch_seconds = state.timestamp;
859
865
  }
860
-
861
866
  resp.key = datetime->get_object_id_hash();
862
- return this->send_date_time_state_response(resp);
867
+ return encode_message_to_buffer(resp, DateTimeStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
863
868
  }
864
- bool APIConnection::try_send_datetime_info_(datetime::DateTimeEntity *datetime) {
869
+ void APIConnection::send_datetime_info(datetime::DateTimeEntity *datetime) {
870
+ this->schedule_message_(datetime, &APIConnection::try_send_datetime_info, ListEntitiesDateTimeResponse::MESSAGE_TYPE);
871
+ }
872
+ uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
873
+ bool is_single) {
874
+ auto *datetime = static_cast<datetime::DateTimeEntity *>(entity);
865
875
  ListEntitiesDateTimeResponse msg;
866
876
  msg.unique_id = get_default_unique_id("datetime", datetime);
867
- return this->try_send_entity_info_(static_cast<EntityBase *>(datetime), msg,
868
- &APIConnection::send_list_entities_date_time_response);
877
+ fill_entity_info_base(datetime, msg);
878
+ return encode_message_to_buffer(msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
869
879
  }
870
880
  void APIConnection::datetime_command(const DateTimeCommandRequest &msg) {
871
881
  datetime::DateTimeEntity *datetime = App.get_datetime_by_key(msg.key);
@@ -879,32 +889,34 @@ void APIConnection::datetime_command(const DateTimeCommandRequest &msg) {
879
889
  #endif
880
890
 
881
891
  #ifdef USE_TEXT
882
- bool APIConnection::send_text_state(text::Text *text, std::string state) {
883
- return this->send_state_with_value_(text, &APIConnection::try_send_text_state_, &APIConnection::try_send_text_state_,
884
- std::move(state));
892
+ bool APIConnection::send_text_state(text::Text *text) {
893
+ return this->schedule_message_(text, &APIConnection::try_send_text_state, TextStateResponse::MESSAGE_TYPE);
885
894
  }
886
895
  void APIConnection::send_text_info(text::Text *text) {
887
- this->send_info_(static_cast<EntityBase *>(text),
888
- reinterpret_cast<send_message_t>(&APIConnection::try_send_text_info_));
896
+ this->schedule_message_(text, &APIConnection::try_send_text_info, ListEntitiesTextResponse::MESSAGE_TYPE);
889
897
  }
890
- bool APIConnection::try_send_text_state_(text::Text *text) { return this->try_send_text_state_(text, text->state); }
891
- bool APIConnection::try_send_text_state_(text::Text *text, std::string state) {
898
+
899
+ uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
900
+ bool is_single) {
901
+ auto *text = static_cast<text::Text *>(entity);
892
902
  TextStateResponse resp;
893
- resp.state = std::move(state);
903
+ resp.state = text->state;
894
904
  resp.missing_state = !text->has_state();
895
-
896
905
  resp.key = text->get_object_id_hash();
897
- return this->send_text_state_response(resp);
906
+ return encode_message_to_buffer(resp, TextStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
898
907
  }
899
- bool APIConnection::try_send_text_info_(text::Text *text) {
908
+
909
+ uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
910
+ bool is_single) {
911
+ auto *text = static_cast<text::Text *>(entity);
900
912
  ListEntitiesTextResponse msg;
901
913
  msg.mode = static_cast<enums::TextMode>(text->traits.get_mode());
902
914
  msg.min_length = text->traits.get_min_length();
903
915
  msg.max_length = text->traits.get_max_length();
904
916
  msg.pattern = text->traits.get_pattern();
905
917
  msg.unique_id = get_default_unique_id("text", text);
906
- return this->try_send_entity_info_(static_cast<EntityBase *>(text), msg,
907
- &APIConnection::send_list_entities_text_response);
918
+ fill_entity_info_base(text, msg);
919
+ return encode_message_to_buffer(msg, ListEntitiesTextResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
908
920
  }
909
921
  void APIConnection::text_command(const TextCommandRequest &msg) {
910
922
  text::Text *text = App.get_text_by_key(msg.key);
@@ -918,32 +930,32 @@ void APIConnection::text_command(const TextCommandRequest &msg) {
918
930
  #endif
919
931
 
920
932
  #ifdef USE_SELECT
921
- bool APIConnection::send_select_state(select::Select *select, std::string state) {
922
- return this->send_state_with_value_(select, &APIConnection::try_send_select_state_,
923
- &APIConnection::try_send_select_state_, std::move(state));
933
+ bool APIConnection::send_select_state(select::Select *select) {
934
+ return this->schedule_message_(select, &APIConnection::try_send_select_state, SelectStateResponse::MESSAGE_TYPE);
924
935
  }
925
936
  void APIConnection::send_select_info(select::Select *select) {
926
- this->send_info_(static_cast<EntityBase *>(select),
927
- reinterpret_cast<send_message_t>(&APIConnection::try_send_select_info_));
928
- }
929
- bool APIConnection::try_send_select_state_(select::Select *select) {
930
- return this->try_send_select_state_(select, select->state);
937
+ this->schedule_message_(select, &APIConnection::try_send_select_info, ListEntitiesSelectResponse::MESSAGE_TYPE);
931
938
  }
932
- bool APIConnection::try_send_select_state_(select::Select *select, std::string state) {
939
+
940
+ uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
941
+ bool is_single) {
942
+ auto *select = static_cast<select::Select *>(entity);
933
943
  SelectStateResponse resp;
934
- resp.state = std::move(state);
944
+ resp.state = select->state;
935
945
  resp.missing_state = !select->has_state();
936
-
937
946
  resp.key = select->get_object_id_hash();
938
- return this->send_select_state_response(resp);
947
+ return encode_message_to_buffer(resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
939
948
  }
940
- bool APIConnection::try_send_select_info_(select::Select *select) {
949
+
950
+ uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
951
+ bool is_single) {
952
+ auto *select = static_cast<select::Select *>(entity);
941
953
  ListEntitiesSelectResponse msg;
942
954
  for (const auto &option : select->traits.get_options())
943
955
  msg.options.push_back(option);
944
956
  msg.unique_id = get_default_unique_id("select", select);
945
- return this->try_send_entity_info_(static_cast<EntityBase *>(select), msg,
946
- &APIConnection::send_list_entities_select_response);
957
+ fill_entity_info_base(select, msg);
958
+ return encode_message_to_buffer(msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
947
959
  }
948
960
  void APIConnection::select_command(const SelectCommandRequest &msg) {
949
961
  select::Select *select = App.get_select_by_key(msg.key);
@@ -958,15 +970,16 @@ void APIConnection::select_command(const SelectCommandRequest &msg) {
958
970
 
959
971
  #ifdef USE_BUTTON
960
972
  void esphome::api::APIConnection::send_button_info(button::Button *button) {
961
- this->send_info_(static_cast<EntityBase *>(button),
962
- reinterpret_cast<send_message_t>(&APIConnection::try_send_button_info_));
973
+ this->schedule_message_(button, &APIConnection::try_send_button_info, ListEntitiesButtonResponse::MESSAGE_TYPE);
963
974
  }
964
- bool esphome::api::APIConnection::try_send_button_info_(button::Button *button) {
975
+ uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
976
+ bool is_single) {
977
+ auto *button = static_cast<button::Button *>(entity);
965
978
  ListEntitiesButtonResponse msg;
966
979
  msg.device_class = button->get_device_class();
967
980
  msg.unique_id = get_default_unique_id("button", button);
968
- return this->try_send_entity_info_(static_cast<EntityBase *>(button), msg,
969
- &APIConnection::send_list_entities_button_response);
981
+ fill_entity_info_base(button, msg);
982
+ return encode_message_to_buffer(msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
970
983
  }
971
984
  void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg) {
972
985
  button::Button *button = App.get_button_by_key(msg.key);
@@ -978,32 +991,32 @@ void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg
978
991
  #endif
979
992
 
980
993
  #ifdef USE_LOCK
981
- bool APIConnection::send_lock_state(lock::Lock *a_lock, lock::LockState state) {
982
- return this->send_state_with_value_(a_lock, &APIConnection::try_send_lock_state_,
983
- &APIConnection::try_send_lock_state_, state);
994
+ bool APIConnection::send_lock_state(lock::Lock *a_lock) {
995
+ return this->schedule_message_(a_lock, &APIConnection::try_send_lock_state, LockStateResponse::MESSAGE_TYPE);
984
996
  }
985
997
  void APIConnection::send_lock_info(lock::Lock *a_lock) {
986
- this->send_info_(static_cast<EntityBase *>(a_lock),
987
- reinterpret_cast<send_message_t>(&APIConnection::try_send_lock_info_));
988
- }
989
- bool APIConnection::try_send_lock_state_(lock::Lock *a_lock) {
990
- return this->try_send_lock_state_(a_lock, a_lock->state);
998
+ this->schedule_message_(a_lock, &APIConnection::try_send_lock_info, ListEntitiesLockResponse::MESSAGE_TYPE);
991
999
  }
992
- bool APIConnection::try_send_lock_state_(lock::Lock *a_lock, lock::LockState state) {
993
- LockStateResponse resp;
994
- resp.state = static_cast<enums::LockState>(state);
995
1000
 
1001
+ uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1002
+ bool is_single) {
1003
+ auto *a_lock = static_cast<lock::Lock *>(entity);
1004
+ LockStateResponse resp;
1005
+ resp.state = static_cast<enums::LockState>(a_lock->state);
996
1006
  resp.key = a_lock->get_object_id_hash();
997
- return this->send_lock_state_response(resp);
1007
+ return encode_message_to_buffer(resp, LockStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
998
1008
  }
999
- bool APIConnection::try_send_lock_info_(lock::Lock *a_lock) {
1009
+
1010
+ uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1011
+ bool is_single) {
1012
+ auto *a_lock = static_cast<lock::Lock *>(entity);
1000
1013
  ListEntitiesLockResponse msg;
1001
1014
  msg.assumed_state = a_lock->traits.get_assumed_state();
1002
1015
  msg.supports_open = a_lock->traits.get_supports_open();
1003
1016
  msg.requires_code = a_lock->traits.get_requires_code();
1004
1017
  msg.unique_id = get_default_unique_id("lock", a_lock);
1005
- return this->try_send_entity_info_(static_cast<EntityBase *>(a_lock), msg,
1006
- &APIConnection::send_list_entities_lock_response);
1018
+ fill_entity_info_base(a_lock, msg);
1019
+ return encode_message_to_buffer(msg, ListEntitiesLockResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1007
1020
  }
1008
1021
  void APIConnection::lock_command(const LockCommandRequest &msg) {
1009
1022
  lock::Lock *a_lock = App.get_lock_by_key(msg.key);
@@ -1026,22 +1039,23 @@ void APIConnection::lock_command(const LockCommandRequest &msg) {
1026
1039
 
1027
1040
  #ifdef USE_VALVE
1028
1041
  bool APIConnection::send_valve_state(valve::Valve *valve) {
1029
- return this->send_state_(static_cast<EntityBase *>(valve),
1030
- reinterpret_cast<send_message_t>(&APIConnection::try_send_valve_state_));
1031
- }
1032
- void APIConnection::send_valve_info(valve::Valve *valve) {
1033
- this->send_info_(static_cast<EntityBase *>(valve),
1034
- reinterpret_cast<send_message_t>(&APIConnection::try_send_valve_info_));
1042
+ return this->schedule_message_(valve, &APIConnection::try_send_valve_state, ValveStateResponse::MESSAGE_TYPE);
1035
1043
  }
1036
- bool APIConnection::try_send_valve_state_(valve::Valve *valve) {
1044
+ uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1045
+ bool is_single) {
1046
+ auto *valve = static_cast<valve::Valve *>(entity);
1037
1047
  ValveStateResponse resp;
1038
1048
  resp.position = valve->position;
1039
1049
  resp.current_operation = static_cast<enums::ValveOperation>(valve->current_operation);
1040
-
1041
1050
  resp.key = valve->get_object_id_hash();
1042
- return this->send_valve_state_response(resp);
1051
+ return encode_message_to_buffer(resp, ValveStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1052
+ }
1053
+ void APIConnection::send_valve_info(valve::Valve *valve) {
1054
+ this->schedule_message_(valve, &APIConnection::try_send_valve_info, ListEntitiesValveResponse::MESSAGE_TYPE);
1043
1055
  }
1044
- bool APIConnection::try_send_valve_info_(valve::Valve *valve) {
1056
+ uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1057
+ bool is_single) {
1058
+ auto *valve = static_cast<valve::Valve *>(entity);
1045
1059
  ListEntitiesValveResponse msg;
1046
1060
  auto traits = valve->get_traits();
1047
1061
  msg.device_class = valve->get_device_class();
@@ -1049,8 +1063,8 @@ bool APIConnection::try_send_valve_info_(valve::Valve *valve) {
1049
1063
  msg.supports_position = traits.get_supports_position();
1050
1064
  msg.supports_stop = traits.get_supports_stop();
1051
1065
  msg.unique_id = get_default_unique_id("valve", valve);
1052
- return this->try_send_entity_info_(static_cast<EntityBase *>(valve), msg,
1053
- &APIConnection::send_list_entities_valve_response);
1066
+ fill_entity_info_base(valve, msg);
1067
+ return encode_message_to_buffer(msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1054
1068
  }
1055
1069
  void APIConnection::valve_command(const ValveCommandRequest &msg) {
1056
1070
  valve::Valve *valve = App.get_valve_by_key(msg.key);
@@ -1068,14 +1082,12 @@ void APIConnection::valve_command(const ValveCommandRequest &msg) {
1068
1082
 
1069
1083
  #ifdef USE_MEDIA_PLAYER
1070
1084
  bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_player) {
1071
- return this->send_state_(static_cast<EntityBase *>(media_player),
1072
- reinterpret_cast<send_message_t>(&APIConnection::try_send_media_player_state_));
1085
+ return this->schedule_message_(media_player, &APIConnection::try_send_media_player_state,
1086
+ MediaPlayerStateResponse::MESSAGE_TYPE);
1073
1087
  }
1074
- void APIConnection::send_media_player_info(media_player::MediaPlayer *media_player) {
1075
- this->send_info_(static_cast<EntityBase *>(media_player),
1076
- reinterpret_cast<send_message_t>(&APIConnection::try_send_media_player_info_));
1077
- }
1078
- bool APIConnection::try_send_media_player_state_(media_player::MediaPlayer *media_player) {
1088
+ uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1089
+ bool is_single) {
1090
+ auto *media_player = static_cast<media_player::MediaPlayer *>(entity);
1079
1091
  MediaPlayerStateResponse resp;
1080
1092
  media_player::MediaPlayerState report_state = media_player->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING
1081
1093
  ? media_player::MEDIA_PLAYER_STATE_PLAYING
@@ -1083,11 +1095,16 @@ bool APIConnection::try_send_media_player_state_(media_player::MediaPlayer *medi
1083
1095
  resp.state = static_cast<enums::MediaPlayerState>(report_state);
1084
1096
  resp.volume = media_player->volume;
1085
1097
  resp.muted = media_player->is_muted();
1086
-
1087
1098
  resp.key = media_player->get_object_id_hash();
1088
- return this->send_media_player_state_response(resp);
1099
+ return encode_message_to_buffer(resp, MediaPlayerStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1100
+ }
1101
+ void APIConnection::send_media_player_info(media_player::MediaPlayer *media_player) {
1102
+ this->schedule_message_(media_player, &APIConnection::try_send_media_player_info,
1103
+ ListEntitiesMediaPlayerResponse::MESSAGE_TYPE);
1089
1104
  }
1090
- bool APIConnection::try_send_media_player_info_(media_player::MediaPlayer *media_player) {
1105
+ uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1106
+ bool is_single) {
1107
+ auto *media_player = static_cast<media_player::MediaPlayer *>(entity);
1091
1108
  ListEntitiesMediaPlayerResponse msg;
1092
1109
  auto traits = media_player->get_traits();
1093
1110
  msg.supports_pause = traits.get_supports_pause();
@@ -1101,8 +1118,8 @@ bool APIConnection::try_send_media_player_info_(media_player::MediaPlayer *media
1101
1118
  msg.supported_formats.push_back(media_format);
1102
1119
  }
1103
1120
  msg.unique_id = get_default_unique_id("media_player", media_player);
1104
- return this->try_send_entity_info_(static_cast<EntityBase *>(media_player), msg,
1105
- &APIConnection::send_list_entities_media_player_response);
1121
+ fill_entity_info_base(media_player, msg);
1122
+ return encode_message_to_buffer(msg, ListEntitiesMediaPlayerResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1106
1123
  }
1107
1124
  void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
1108
1125
  media_player::MediaPlayer *media_player = App.get_media_player_by_key(msg.key);
@@ -1137,14 +1154,15 @@ void APIConnection::set_camera_state(std::shared_ptr<esp32_camera::CameraImage>
1137
1154
  this->image_reader_.set_image(std::move(image));
1138
1155
  }
1139
1156
  void APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
1140
- this->send_info_(static_cast<EntityBase *>(camera),
1141
- reinterpret_cast<send_message_t>(&APIConnection::try_send_camera_info_));
1157
+ this->schedule_message_(camera, &APIConnection::try_send_camera_info, ListEntitiesCameraResponse::MESSAGE_TYPE);
1142
1158
  }
1143
- bool APIConnection::try_send_camera_info_(esp32_camera::ESP32Camera *camera) {
1159
+ uint16_t APIConnection::try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1160
+ bool is_single) {
1161
+ auto *camera = static_cast<esp32_camera::ESP32Camera *>(entity);
1144
1162
  ListEntitiesCameraResponse msg;
1145
1163
  msg.unique_id = get_default_unique_id("camera", camera);
1146
- return this->try_send_entity_info_(static_cast<EntityBase *>(camera), msg,
1147
- &APIConnection::send_list_entities_camera_response);
1164
+ fill_entity_info_base(camera, msg);
1165
+ return encode_message_to_buffer(msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1148
1166
  }
1149
1167
  void APIConnection::camera_image(const CameraImageRequest &msg) {
1150
1168
  if (esp32_camera::global_esp32_camera == nullptr)
@@ -1187,9 +1205,9 @@ bool APIConnection::send_bluetooth_le_advertisement(const BluetoothLEAdvertiseme
1187
1205
  manufacturer_data.legacy_data.assign(manufacturer_data.data.begin(), manufacturer_data.data.end());
1188
1206
  manufacturer_data.data.clear();
1189
1207
  }
1190
- return this->send_bluetooth_le_advertisement_response(resp);
1208
+ return this->send_message(resp);
1191
1209
  }
1192
- return this->send_bluetooth_le_advertisement_response(msg);
1210
+ return this->send_message(msg);
1193
1211
  }
1194
1212
  void APIConnection::bluetooth_device_request(const BluetoothDeviceRequest &msg) {
1195
1213
  bluetooth_proxy::global_bluetooth_proxy->bluetooth_device_request(msg);
@@ -1333,28 +1351,32 @@ void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetCon
1333
1351
 
1334
1352
  #ifdef USE_ALARM_CONTROL_PANEL
1335
1353
  bool APIConnection::send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
1336
- return this->send_state_(static_cast<EntityBase *>(a_alarm_control_panel),
1337
- reinterpret_cast<send_message_t>(&APIConnection::try_send_alarm_control_panel_state_));
1354
+ return this->schedule_message_(a_alarm_control_panel, &APIConnection::try_send_alarm_control_panel_state,
1355
+ AlarmControlPanelStateResponse::MESSAGE_TYPE);
1338
1356
  }
1339
- void APIConnection::send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
1340
- this->send_info_(static_cast<EntityBase *>(a_alarm_control_panel),
1341
- reinterpret_cast<send_message_t>(&APIConnection::try_send_alarm_control_panel_info_));
1342
- }
1343
- bool APIConnection::try_send_alarm_control_panel_state_(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
1357
+ uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn,
1358
+ uint32_t remaining_size, bool is_single) {
1359
+ auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity);
1344
1360
  AlarmControlPanelStateResponse resp;
1345
1361
  resp.state = static_cast<enums::AlarmControlPanelState>(a_alarm_control_panel->get_state());
1346
-
1347
1362
  resp.key = a_alarm_control_panel->get_object_id_hash();
1348
- return this->send_alarm_control_panel_state_response(resp);
1363
+ return encode_message_to_buffer(resp, AlarmControlPanelStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1349
1364
  }
1350
- bool APIConnection::try_send_alarm_control_panel_info_(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
1365
+ void APIConnection::send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
1366
+ this->schedule_message_(a_alarm_control_panel, &APIConnection::try_send_alarm_control_panel_info,
1367
+ ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE);
1368
+ }
1369
+ uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn,
1370
+ uint32_t remaining_size, bool is_single) {
1371
+ auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity);
1351
1372
  ListEntitiesAlarmControlPanelResponse msg;
1352
1373
  msg.supported_features = a_alarm_control_panel->get_supported_features();
1353
1374
  msg.requires_code = a_alarm_control_panel->get_requires_code();
1354
1375
  msg.requires_code_to_arm = a_alarm_control_panel->get_requires_code_to_arm();
1355
1376
  msg.unique_id = get_default_unique_id("alarm_control_panel", a_alarm_control_panel);
1356
- return this->try_send_entity_info_(static_cast<EntityBase *>(a_alarm_control_panel), msg,
1357
- &APIConnection::send_list_entities_alarm_control_panel_response);
1377
+ fill_entity_info_base(a_alarm_control_panel, msg);
1378
+ return encode_message_to_buffer(msg, ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE, conn, remaining_size,
1379
+ is_single);
1358
1380
  }
1359
1381
  void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) {
1360
1382
  alarm_control_panel::AlarmControlPanel *a_alarm_control_panel = App.get_alarm_control_panel_by_key(msg.key);
@@ -1391,45 +1413,40 @@ void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRe
1391
1413
  #endif
1392
1414
 
1393
1415
  #ifdef USE_EVENT
1394
- void APIConnection::send_event(event::Event *event, std::string event_type) {
1395
- this->send_state_with_value_(event, &APIConnection::try_send_event_, &APIConnection::try_send_event_,
1396
- std::move(event_type));
1416
+ void APIConnection::send_event(event::Event *event, const std::string &event_type) {
1417
+ this->schedule_message_(event, MessageCreator(event_type, EventResponse::MESSAGE_TYPE), EventResponse::MESSAGE_TYPE);
1397
1418
  }
1398
1419
  void APIConnection::send_event_info(event::Event *event) {
1399
- this->send_info_(static_cast<EntityBase *>(event),
1400
- reinterpret_cast<send_message_t>(&APIConnection::try_send_event_info_));
1420
+ this->schedule_message_(event, &APIConnection::try_send_event_info, ListEntitiesEventResponse::MESSAGE_TYPE);
1401
1421
  }
1402
- bool APIConnection::try_send_event_(event::Event *event) {
1403
- return this->try_send_event_(event, *(event->last_event_type));
1404
- }
1405
- bool APIConnection::try_send_event_(event::Event *event, std::string event_type) {
1422
+ uint16_t APIConnection::try_send_event_response(event::Event *event, const std::string &event_type, APIConnection *conn,
1423
+ uint32_t remaining_size, bool is_single) {
1406
1424
  EventResponse resp;
1407
- resp.event_type = std::move(event_type);
1408
-
1425
+ resp.event_type = event_type;
1409
1426
  resp.key = event->get_object_id_hash();
1410
- return this->send_event_response(resp);
1427
+ return encode_message_to_buffer(resp, EventResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1411
1428
  }
1412
- bool APIConnection::try_send_event_info_(event::Event *event) {
1429
+
1430
+ uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1431
+ bool is_single) {
1432
+ auto *event = static_cast<event::Event *>(entity);
1413
1433
  ListEntitiesEventResponse msg;
1414
1434
  msg.device_class = event->get_device_class();
1415
1435
  for (const auto &event_type : event->get_event_types())
1416
1436
  msg.event_types.push_back(event_type);
1417
1437
  msg.unique_id = get_default_unique_id("event", event);
1418
- return this->try_send_entity_info_(static_cast<EntityBase *>(event), msg,
1419
- &APIConnection::send_list_entities_event_response);
1438
+ fill_entity_info_base(event, msg);
1439
+ return encode_message_to_buffer(msg, ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1420
1440
  }
1421
1441
  #endif
1422
1442
 
1423
1443
  #ifdef USE_UPDATE
1424
1444
  bool APIConnection::send_update_state(update::UpdateEntity *update) {
1425
- return this->send_state_(static_cast<EntityBase *>(update),
1426
- reinterpret_cast<send_message_t>(&APIConnection::try_send_update_state_));
1427
- }
1428
- void APIConnection::send_update_info(update::UpdateEntity *update) {
1429
- this->send_info_(static_cast<EntityBase *>(update),
1430
- reinterpret_cast<send_message_t>(&APIConnection::try_send_update_info_));
1445
+ return this->schedule_message_(update, &APIConnection::try_send_update_state, UpdateStateResponse::MESSAGE_TYPE);
1431
1446
  }
1432
- bool APIConnection::try_send_update_state_(update::UpdateEntity *update) {
1447
+ uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1448
+ bool is_single) {
1449
+ auto *update = static_cast<update::UpdateEntity *>(entity);
1433
1450
  UpdateStateResponse resp;
1434
1451
  resp.missing_state = !update->has_state();
1435
1452
  if (update->has_state()) {
@@ -1444,16 +1461,20 @@ bool APIConnection::try_send_update_state_(update::UpdateEntity *update) {
1444
1461
  resp.release_summary = update->update_info.summary;
1445
1462
  resp.release_url = update->update_info.release_url;
1446
1463
  }
1447
-
1448
1464
  resp.key = update->get_object_id_hash();
1449
- return this->send_update_state_response(resp);
1465
+ return encode_message_to_buffer(resp, UpdateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1466
+ }
1467
+ void APIConnection::send_update_info(update::UpdateEntity *update) {
1468
+ this->schedule_message_(update, &APIConnection::try_send_update_info, ListEntitiesUpdateResponse::MESSAGE_TYPE);
1450
1469
  }
1451
- bool APIConnection::try_send_update_info_(update::UpdateEntity *update) {
1470
+ uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1471
+ bool is_single) {
1472
+ auto *update = static_cast<update::UpdateEntity *>(entity);
1452
1473
  ListEntitiesUpdateResponse msg;
1453
1474
  msg.device_class = update->get_device_class();
1454
1475
  msg.unique_id = get_default_unique_id("update", update);
1455
- return this->try_send_entity_info_(static_cast<EntityBase *>(update), msg,
1456
- &APIConnection::send_list_entities_update_response);
1476
+ fill_entity_info_base(update, msg);
1477
+ return encode_message_to_buffer(msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1457
1478
  }
1458
1479
  void APIConnection::update_command(const UpdateCommandRequest &msg) {
1459
1480
  update::UpdateEntity *update = App.get_update_by_key(msg.key);
@@ -1468,7 +1489,7 @@ void APIConnection::update_command(const UpdateCommandRequest &msg) {
1468
1489
  update->check();
1469
1490
  break;
1470
1491
  case enums::UPDATE_COMMAND_NONE:
1471
- ESP_LOGE(TAG, "UPDATE_COMMAND_NONE not handled. Check client is sending the correct command");
1492
+ ESP_LOGE(TAG, "UPDATE_COMMAND_NONE not handled; confirm command is correct");
1472
1493
  break;
1473
1494
  default:
1474
1495
  ESP_LOGW(TAG, "Unknown update command: %" PRIu32, msg.command);
@@ -1530,7 +1551,7 @@ ConnectResponse APIConnection::connect(const ConnectRequest &msg) {
1530
1551
  // bool invalid_password = 1;
1531
1552
  resp.invalid_password = !correct;
1532
1553
  if (correct) {
1533
- ESP_LOGD(TAG, "%s: Connected successfully", this->client_combined_info_.c_str());
1554
+ ESP_LOGD(TAG, "%s connected", this->client_combined_info_.c_str());
1534
1555
  this->connection_state_ = ConnectionState::AUTHENTICATED;
1535
1556
  this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->client_peername_);
1536
1557
  #ifdef USE_HOMEASSISTANT_TIME
@@ -1601,7 +1622,7 @@ void APIConnection::execute_service(const ExecuteServiceRequest &msg) {
1601
1622
  }
1602
1623
  }
1603
1624
  if (!found) {
1604
- ESP_LOGV(TAG, "Could not find matching service!");
1625
+ ESP_LOGV(TAG, "Could not find service");
1605
1626
  }
1606
1627
  }
1607
1628
  #ifdef USE_API_NOISE
@@ -1647,7 +1668,7 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) {
1647
1668
  }
1648
1669
  return false;
1649
1670
  }
1650
- bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint32_t message_type) {
1671
+ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint16_t message_type) {
1651
1672
  if (!this->try_to_clear_buffer(message_type != 29)) { // SubscribeLogsResponse
1652
1673
  return false;
1653
1674
  }
@@ -1670,17 +1691,350 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint32_t message_type)
1670
1691
  }
1671
1692
  void APIConnection::on_unauthenticated_access() {
1672
1693
  this->on_fatal_error();
1673
- ESP_LOGD(TAG, "%s: tried to access without authentication.", this->client_combined_info_.c_str());
1694
+ ESP_LOGD(TAG, "%s requested access without authentication", this->client_combined_info_.c_str());
1674
1695
  }
1675
1696
  void APIConnection::on_no_setup_connection() {
1676
1697
  this->on_fatal_error();
1677
- ESP_LOGD(TAG, "%s: tried to access without full connection.", this->client_combined_info_.c_str());
1698
+ ESP_LOGD(TAG, "%s requested access without full connection", this->client_combined_info_.c_str());
1678
1699
  }
1679
1700
  void APIConnection::on_fatal_error() {
1680
1701
  this->helper_->close();
1681
1702
  this->remove_ = true;
1682
1703
  }
1683
1704
 
1705
+ void APIConnection::DeferredBatch::add_item(EntityBase *entity, MessageCreator creator, uint16_t message_type) {
1706
+ // Check if we already have a message of this type for this entity
1707
+ // This provides deduplication per entity/message_type combination
1708
+ // O(n) but optimized for RAM and not performance.
1709
+ for (auto &item : items) {
1710
+ if (item.entity == entity && item.message_type == message_type) {
1711
+ // Update the existing item with the new creator
1712
+ item.creator = std::move(creator);
1713
+ return;
1714
+ }
1715
+ }
1716
+
1717
+ // No existing item found, add new one
1718
+ items.emplace_back(entity, std::move(creator), message_type);
1719
+ }
1720
+
1721
+ bool APIConnection::schedule_batch_() {
1722
+ if (!this->deferred_batch_.batch_scheduled) {
1723
+ this->deferred_batch_.batch_scheduled = true;
1724
+ this->deferred_batch_.batch_start_time = App.get_loop_component_start_time();
1725
+ }
1726
+ return true;
1727
+ }
1728
+
1729
+ ProtoWriteBuffer APIConnection::allocate_single_message_buffer(uint16_t size) { return this->create_buffer(size); }
1730
+
1731
+ ProtoWriteBuffer APIConnection::allocate_batch_message_buffer(uint16_t size) {
1732
+ ProtoWriteBuffer result = this->prepare_message_buffer(size, this->batch_first_message_);
1733
+ this->batch_first_message_ = false;
1734
+ return result;
1735
+ }
1736
+
1737
+ void APIConnection::process_batch_() {
1738
+ if (this->deferred_batch_.empty()) {
1739
+ this->deferred_batch_.batch_scheduled = false;
1740
+ return;
1741
+ }
1742
+
1743
+ // Try to clear buffer first
1744
+ if (!this->try_to_clear_buffer(true)) {
1745
+ // Can't write now, we'll try again later
1746
+ return;
1747
+ }
1748
+
1749
+ size_t num_items = this->deferred_batch_.items.size();
1750
+
1751
+ // Fast path for single message - allocate exact size needed
1752
+ if (num_items == 1) {
1753
+ const auto &item = this->deferred_batch_.items[0];
1754
+
1755
+ // Let the creator calculate size and encode if it fits
1756
+ uint16_t payload_size = item.creator(item.entity, this, std::numeric_limits<uint16_t>::max(), true);
1757
+
1758
+ if (payload_size > 0 &&
1759
+ this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, item.message_type)) {
1760
+ this->deferred_batch_.clear();
1761
+ } else if (payload_size == 0) {
1762
+ // Message too large
1763
+ ESP_LOGW(TAG, "Message too large to send: type=%u", item.message_type);
1764
+ this->deferred_batch_.clear();
1765
+ }
1766
+ return;
1767
+ }
1768
+
1769
+ // Pre-allocate storage for packet info
1770
+ std::vector<PacketInfo> packet_info;
1771
+ packet_info.reserve(num_items);
1772
+
1773
+ // Cache these values to avoid repeated virtual calls
1774
+ const uint8_t header_padding = this->helper_->frame_header_padding();
1775
+ const uint8_t footer_size = this->helper_->frame_footer_size();
1776
+
1777
+ // Initialize buffer and tracking variables
1778
+ this->parent_->get_shared_buffer_ref().clear();
1779
+
1780
+ // Pre-calculate exact buffer size needed based on message types
1781
+ uint32_t total_estimated_size = 0;
1782
+ for (const auto &item : this->deferred_batch_.items) {
1783
+ total_estimated_size += get_estimated_message_size(item.message_type);
1784
+ }
1785
+
1786
+ // Calculate total overhead for all messages
1787
+ uint32_t total_overhead = (header_padding + footer_size) * num_items;
1788
+
1789
+ // Reserve based on estimated size (much more accurate than 24-byte worst-case)
1790
+ this->parent_->get_shared_buffer_ref().reserve(total_estimated_size + total_overhead);
1791
+ this->batch_first_message_ = true;
1792
+
1793
+ size_t items_processed = 0;
1794
+ uint32_t remaining_size = MAX_PACKET_SIZE;
1795
+
1796
+ // Track where each message's header padding begins in the buffer
1797
+ // For plaintext: this is where the 6-byte header padding starts
1798
+ // For noise: this is where the 7-byte header padding starts
1799
+ // The actual message data follows after the header padding
1800
+ uint32_t current_offset = 0;
1801
+
1802
+ // Process items and encode directly to buffer
1803
+ for (const auto &item : this->deferred_batch_.items) {
1804
+ // Try to encode message
1805
+ // The creator will calculate overhead to determine if the message fits
1806
+ uint16_t payload_size = item.creator(item.entity, this, remaining_size, false);
1807
+
1808
+ if (payload_size == 0) {
1809
+ // Message won't fit, stop processing
1810
+ break;
1811
+ }
1812
+
1813
+ // Message was encoded successfully
1814
+ // payload_size is header_padding + actual payload size + footer_size
1815
+ uint16_t proto_payload_size = payload_size - header_padding - footer_size;
1816
+ packet_info.emplace_back(item.message_type, current_offset, proto_payload_size);
1817
+
1818
+ // Update tracking variables
1819
+ remaining_size -= payload_size;
1820
+ // Calculate where the next message's header padding will start
1821
+ // Current buffer size + footer space (that prepare_message_buffer will add for this message)
1822
+ current_offset = this->parent_->get_shared_buffer_ref().size() + footer_size;
1823
+ items_processed++;
1824
+ }
1825
+
1826
+ if (items_processed == 0) {
1827
+ this->deferred_batch_.clear();
1828
+ return;
1829
+ }
1830
+
1831
+ // Add footer space for the last message (for Noise protocol MAC)
1832
+ if (footer_size > 0) {
1833
+ auto &shared_buf = this->parent_->get_shared_buffer_ref();
1834
+ shared_buf.resize(shared_buf.size() + footer_size);
1835
+ }
1836
+
1837
+ // Send all collected packets
1838
+ APIError err =
1839
+ this->helper_->write_protobuf_packets(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, packet_info);
1840
+ if (err != APIError::OK && err != APIError::WOULD_BLOCK) {
1841
+ on_fatal_error();
1842
+ if (err == APIError::SOCKET_WRITE_FAILED && errno == ECONNRESET) {
1843
+ ESP_LOGW(TAG, "%s: Connection reset during batch write", this->client_combined_info_.c_str());
1844
+ } else {
1845
+ ESP_LOGW(TAG, "%s: Batch write failed %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
1846
+ errno);
1847
+ }
1848
+ }
1849
+
1850
+ // Handle remaining items more efficiently
1851
+ if (items_processed < this->deferred_batch_.items.size()) {
1852
+ // Remove processed items from the beginning
1853
+ this->deferred_batch_.items.erase(this->deferred_batch_.items.begin(),
1854
+ this->deferred_batch_.items.begin() + items_processed);
1855
+
1856
+ // Reschedule for remaining items
1857
+ this->schedule_batch_();
1858
+ } else {
1859
+ // All items processed
1860
+ this->deferred_batch_.clear();
1861
+ }
1862
+ }
1863
+
1864
+ uint16_t APIConnection::MessageCreator::operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1865
+ bool is_single) const {
1866
+ switch (message_type_) {
1867
+ case 0: // Function pointer
1868
+ return data_.ptr(entity, conn, remaining_size, is_single);
1869
+
1870
+ #ifdef USE_EVENT
1871
+ case EventResponse::MESSAGE_TYPE: {
1872
+ auto *e = static_cast<event::Event *>(entity);
1873
+ return APIConnection::try_send_event_response(e, *data_.string_ptr, conn, remaining_size, is_single);
1874
+ }
1875
+ #endif
1876
+
1877
+ default:
1878
+ // Should not happen, return 0 to indicate no message
1879
+ return 0;
1880
+ }
1881
+ }
1882
+
1883
+ uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1884
+ bool is_single) {
1885
+ ListEntitiesDoneResponse resp;
1886
+ return encode_message_to_buffer(resp, ListEntitiesDoneResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
1887
+ }
1888
+
1889
+ uint16_t APIConnection::try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
1890
+ bool is_single) {
1891
+ DisconnectRequest req;
1892
+ return encode_message_to_buffer(req, DisconnectRequest::MESSAGE_TYPE, conn, remaining_size, is_single);
1893
+ }
1894
+
1895
+ uint16_t APIConnection::get_estimated_message_size(uint16_t message_type) {
1896
+ // Use generated ESTIMATED_SIZE constants from each message type
1897
+ switch (message_type) {
1898
+ #ifdef USE_BINARY_SENSOR
1899
+ case BinarySensorStateResponse::MESSAGE_TYPE:
1900
+ return BinarySensorStateResponse::ESTIMATED_SIZE;
1901
+ case ListEntitiesBinarySensorResponse::MESSAGE_TYPE:
1902
+ return ListEntitiesBinarySensorResponse::ESTIMATED_SIZE;
1903
+ #endif
1904
+ #ifdef USE_SENSOR
1905
+ case SensorStateResponse::MESSAGE_TYPE:
1906
+ return SensorStateResponse::ESTIMATED_SIZE;
1907
+ case ListEntitiesSensorResponse::MESSAGE_TYPE:
1908
+ return ListEntitiesSensorResponse::ESTIMATED_SIZE;
1909
+ #endif
1910
+ #ifdef USE_SWITCH
1911
+ case SwitchStateResponse::MESSAGE_TYPE:
1912
+ return SwitchStateResponse::ESTIMATED_SIZE;
1913
+ case ListEntitiesSwitchResponse::MESSAGE_TYPE:
1914
+ return ListEntitiesSwitchResponse::ESTIMATED_SIZE;
1915
+ #endif
1916
+ #ifdef USE_TEXT_SENSOR
1917
+ case TextSensorStateResponse::MESSAGE_TYPE:
1918
+ return TextSensorStateResponse::ESTIMATED_SIZE;
1919
+ case ListEntitiesTextSensorResponse::MESSAGE_TYPE:
1920
+ return ListEntitiesTextSensorResponse::ESTIMATED_SIZE;
1921
+ #endif
1922
+ #ifdef USE_NUMBER
1923
+ case NumberStateResponse::MESSAGE_TYPE:
1924
+ return NumberStateResponse::ESTIMATED_SIZE;
1925
+ case ListEntitiesNumberResponse::MESSAGE_TYPE:
1926
+ return ListEntitiesNumberResponse::ESTIMATED_SIZE;
1927
+ #endif
1928
+ #ifdef USE_TEXT
1929
+ case TextStateResponse::MESSAGE_TYPE:
1930
+ return TextStateResponse::ESTIMATED_SIZE;
1931
+ case ListEntitiesTextResponse::MESSAGE_TYPE:
1932
+ return ListEntitiesTextResponse::ESTIMATED_SIZE;
1933
+ #endif
1934
+ #ifdef USE_SELECT
1935
+ case SelectStateResponse::MESSAGE_TYPE:
1936
+ return SelectStateResponse::ESTIMATED_SIZE;
1937
+ case ListEntitiesSelectResponse::MESSAGE_TYPE:
1938
+ return ListEntitiesSelectResponse::ESTIMATED_SIZE;
1939
+ #endif
1940
+ #ifdef USE_LOCK
1941
+ case LockStateResponse::MESSAGE_TYPE:
1942
+ return LockStateResponse::ESTIMATED_SIZE;
1943
+ case ListEntitiesLockResponse::MESSAGE_TYPE:
1944
+ return ListEntitiesLockResponse::ESTIMATED_SIZE;
1945
+ #endif
1946
+ #ifdef USE_EVENT
1947
+ case EventResponse::MESSAGE_TYPE:
1948
+ return EventResponse::ESTIMATED_SIZE;
1949
+ case ListEntitiesEventResponse::MESSAGE_TYPE:
1950
+ return ListEntitiesEventResponse::ESTIMATED_SIZE;
1951
+ #endif
1952
+ #ifdef USE_COVER
1953
+ case CoverStateResponse::MESSAGE_TYPE:
1954
+ return CoverStateResponse::ESTIMATED_SIZE;
1955
+ case ListEntitiesCoverResponse::MESSAGE_TYPE:
1956
+ return ListEntitiesCoverResponse::ESTIMATED_SIZE;
1957
+ #endif
1958
+ #ifdef USE_FAN
1959
+ case FanStateResponse::MESSAGE_TYPE:
1960
+ return FanStateResponse::ESTIMATED_SIZE;
1961
+ case ListEntitiesFanResponse::MESSAGE_TYPE:
1962
+ return ListEntitiesFanResponse::ESTIMATED_SIZE;
1963
+ #endif
1964
+ #ifdef USE_LIGHT
1965
+ case LightStateResponse::MESSAGE_TYPE:
1966
+ return LightStateResponse::ESTIMATED_SIZE;
1967
+ case ListEntitiesLightResponse::MESSAGE_TYPE:
1968
+ return ListEntitiesLightResponse::ESTIMATED_SIZE;
1969
+ #endif
1970
+ #ifdef USE_CLIMATE
1971
+ case ClimateStateResponse::MESSAGE_TYPE:
1972
+ return ClimateStateResponse::ESTIMATED_SIZE;
1973
+ case ListEntitiesClimateResponse::MESSAGE_TYPE:
1974
+ return ListEntitiesClimateResponse::ESTIMATED_SIZE;
1975
+ #endif
1976
+ #ifdef USE_ESP32_CAMERA
1977
+ case ListEntitiesCameraResponse::MESSAGE_TYPE:
1978
+ return ListEntitiesCameraResponse::ESTIMATED_SIZE;
1979
+ #endif
1980
+ #ifdef USE_BUTTON
1981
+ case ListEntitiesButtonResponse::MESSAGE_TYPE:
1982
+ return ListEntitiesButtonResponse::ESTIMATED_SIZE;
1983
+ #endif
1984
+ #ifdef USE_MEDIA_PLAYER
1985
+ case MediaPlayerStateResponse::MESSAGE_TYPE:
1986
+ return MediaPlayerStateResponse::ESTIMATED_SIZE;
1987
+ case ListEntitiesMediaPlayerResponse::MESSAGE_TYPE:
1988
+ return ListEntitiesMediaPlayerResponse::ESTIMATED_SIZE;
1989
+ #endif
1990
+ #ifdef USE_ALARM_CONTROL_PANEL
1991
+ case AlarmControlPanelStateResponse::MESSAGE_TYPE:
1992
+ return AlarmControlPanelStateResponse::ESTIMATED_SIZE;
1993
+ case ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE:
1994
+ return ListEntitiesAlarmControlPanelResponse::ESTIMATED_SIZE;
1995
+ #endif
1996
+ #ifdef USE_DATETIME_DATE
1997
+ case DateStateResponse::MESSAGE_TYPE:
1998
+ return DateStateResponse::ESTIMATED_SIZE;
1999
+ case ListEntitiesDateResponse::MESSAGE_TYPE:
2000
+ return ListEntitiesDateResponse::ESTIMATED_SIZE;
2001
+ #endif
2002
+ #ifdef USE_DATETIME_TIME
2003
+ case TimeStateResponse::MESSAGE_TYPE:
2004
+ return TimeStateResponse::ESTIMATED_SIZE;
2005
+ case ListEntitiesTimeResponse::MESSAGE_TYPE:
2006
+ return ListEntitiesTimeResponse::ESTIMATED_SIZE;
2007
+ #endif
2008
+ #ifdef USE_DATETIME_DATETIME
2009
+ case DateTimeStateResponse::MESSAGE_TYPE:
2010
+ return DateTimeStateResponse::ESTIMATED_SIZE;
2011
+ case ListEntitiesDateTimeResponse::MESSAGE_TYPE:
2012
+ return ListEntitiesDateTimeResponse::ESTIMATED_SIZE;
2013
+ #endif
2014
+ #ifdef USE_VALVE
2015
+ case ValveStateResponse::MESSAGE_TYPE:
2016
+ return ValveStateResponse::ESTIMATED_SIZE;
2017
+ case ListEntitiesValveResponse::MESSAGE_TYPE:
2018
+ return ListEntitiesValveResponse::ESTIMATED_SIZE;
2019
+ #endif
2020
+ #ifdef USE_UPDATE
2021
+ case UpdateStateResponse::MESSAGE_TYPE:
2022
+ return UpdateStateResponse::ESTIMATED_SIZE;
2023
+ case ListEntitiesUpdateResponse::MESSAGE_TYPE:
2024
+ return ListEntitiesUpdateResponse::ESTIMATED_SIZE;
2025
+ #endif
2026
+ case ListEntitiesServicesResponse::MESSAGE_TYPE:
2027
+ return ListEntitiesServicesResponse::ESTIMATED_SIZE;
2028
+ case ListEntitiesDoneResponse::MESSAGE_TYPE:
2029
+ return ListEntitiesDoneResponse::ESTIMATED_SIZE;
2030
+ case DisconnectRequest::MESSAGE_TYPE:
2031
+ return DisconnectRequest::ESTIMATED_SIZE;
2032
+ default:
2033
+ // Fallback for unknown message types
2034
+ return 24;
2035
+ }
2036
+ }
2037
+
1684
2038
  } // namespace api
1685
2039
  } // namespace esphome
1686
2040
  #endif