esphome 2025.6.3__py3-none-any.whl → 2025.7.0b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (606) hide show
  1. esphome/__main__.py +1 -3
  2. esphome/codegen.py +2 -0
  3. esphome/components/ac_dimmer/ac_dimmer.cpp +6 -6
  4. esphome/components/adc/__init__.py +25 -1
  5. esphome/components/adc/adc_sensor.h +11 -11
  6. esphome/components/adc/adc_sensor_common.cpp +1 -1
  7. esphome/components/adc/adc_sensor_esp32.cpp +16 -8
  8. esphome/components/ade7880/ade7880.h +0 -2
  9. esphome/components/ads1115/ads1115.h +0 -1
  10. esphome/components/ads1118/ads1118.h +0 -1
  11. esphome/components/ags10/ags10.h +0 -2
  12. esphome/components/aic3204/aic3204.h +0 -1
  13. esphome/components/alarm_control_panel/__init__.py +5 -2
  14. esphome/components/alpha3/alpha3.h +0 -1
  15. esphome/components/am43/cover/am43_cover.h +0 -1
  16. esphome/components/am43/sensor/am43_sensor.h +0 -1
  17. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +0 -2
  18. esphome/components/anova/anova.cpp +5 -1
  19. esphome/components/anova/anova.h +0 -1
  20. esphome/components/apds9960/apds9960.cpp +1 -1
  21. esphome/components/api/__init__.py +57 -21
  22. esphome/components/api/api_connection.cpp +344 -539
  23. esphome/components/api/api_connection.h +224 -141
  24. esphome/components/api/api_frame_helper.cpp +91 -127
  25. esphome/components/api/api_frame_helper.h +64 -54
  26. esphome/components/api/api_pb2.cpp +1837 -9044
  27. esphome/components/api/api_pb2.h +532 -685
  28. esphome/components/api/api_pb2_dump.cpp +4432 -0
  29. esphome/components/api/api_pb2_service.cpp +184 -425
  30. esphome/components/api/api_pb2_service.h +13 -6
  31. esphome/components/api/api_server.cpp +131 -167
  32. esphome/components/api/api_server.h +38 -10
  33. esphome/components/api/client.py +8 -2
  34. esphome/components/api/custom_api_device.h +8 -0
  35. esphome/components/api/list_entities.cpp +37 -104
  36. esphome/components/api/list_entities.h +33 -23
  37. esphome/components/api/proto.h +532 -26
  38. esphome/components/api/subscribe_state.cpp +23 -29
  39. esphome/components/api/subscribe_state.h +26 -19
  40. esphome/components/api/user_services.h +2 -0
  41. esphome/components/as5600/as5600.h +0 -1
  42. esphome/components/async_tcp/__init__.py +14 -5
  43. esphome/components/atc_mithermometer/atc_mithermometer.h +0 -1
  44. esphome/components/atm90e32/atm90e32.cpp +2 -1
  45. esphome/components/audio/audio_decoder.cpp +1 -1
  46. esphome/components/audio/audio_transfer_buffer.cpp +2 -2
  47. esphome/components/b_parasite/b_parasite.h +0 -1
  48. esphome/components/bedjet/bedjet_hub.cpp +5 -1
  49. esphome/components/bedjet/climate/bedjet_climate.cpp +5 -1
  50. esphome/components/beken_spi_led_strip/led_strip.cpp +4 -2
  51. esphome/components/bh1750/bh1750.cpp +5 -5
  52. esphome/components/binary_sensor/__init__.py +82 -5
  53. esphome/components/binary_sensor/automation.h +19 -1
  54. esphome/components/binary_sensor/binary_sensor.cpp +12 -30
  55. esphome/components/binary_sensor/binary_sensor.h +11 -25
  56. esphome/components/binary_sensor/filter.cpp +29 -24
  57. esphome/components/binary_sensor/filter.h +20 -10
  58. esphome/components/ble_client/output/ble_binary_output.h +0 -1
  59. esphome/components/ble_client/sensor/ble_rssi_sensor.cpp +5 -1
  60. esphome/components/ble_client/sensor/ble_rssi_sensor.h +0 -1
  61. esphome/components/ble_client/sensor/ble_sensor.cpp +5 -1
  62. esphome/components/ble_client/sensor/ble_sensor.h +0 -1
  63. esphome/components/ble_client/switch/ble_switch.h +0 -1
  64. esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +5 -1
  65. esphome/components/ble_client/text_sensor/ble_text_sensor.h +0 -1
  66. esphome/components/ble_presence/ble_presence_device.h +0 -1
  67. esphome/components/ble_rssi/ble_rssi_sensor.h +0 -1
  68. esphome/components/ble_scanner/ble_scanner.h +0 -1
  69. esphome/components/bluetooth_proxy/bluetooth_connection.h +9 -2
  70. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +16 -6
  71. esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -2
  72. esphome/components/bme680/sensor.py +1 -1
  73. esphome/components/bmp581/bmp581.h +0 -2
  74. esphome/components/button/__init__.py +5 -2
  75. esphome/components/camera/__init__.py +1 -0
  76. esphome/components/camera/camera.cpp +22 -0
  77. esphome/components/camera/camera.h +80 -0
  78. esphome/components/canbus/__init__.py +1 -0
  79. esphome/components/cap1188/cap1188.h +0 -1
  80. esphome/components/captive_portal/__init__.py +12 -2
  81. esphome/components/captive_portal/captive_portal.cpp +12 -2
  82. esphome/components/captive_portal/captive_portal.h +5 -2
  83. esphome/components/ccs811/ccs811.h +0 -2
  84. esphome/components/climate/__init__.py +5 -2
  85. esphome/components/cm1106/sensor.py +2 -2
  86. esphome/components/const/__init__.py +2 -0
  87. esphome/components/copy/binary_sensor/copy_binary_sensor.h +0 -1
  88. esphome/components/copy/button/copy_button.h +0 -1
  89. esphome/components/copy/cover/copy_cover.h +0 -1
  90. esphome/components/copy/fan/copy_fan.h +0 -1
  91. esphome/components/copy/lock/copy_lock.h +0 -1
  92. esphome/components/copy/number/copy_number.h +0 -1
  93. esphome/components/copy/select/copy_select.h +0 -1
  94. esphome/components/copy/sensor/copy_sensor.h +0 -1
  95. esphome/components/copy/switch/copy_switch.h +0 -1
  96. esphome/components/copy/text/copy_text.h +0 -1
  97. esphome/components/copy/text_sensor/copy_text_sensor.h +0 -1
  98. esphome/components/cover/__init__.py +5 -2
  99. esphome/components/cs5460a/cs5460a.h +0 -1
  100. esphome/components/datetime/__init__.py +4 -2
  101. esphome/components/debug/__init__.py +20 -0
  102. esphome/components/debug/debug_esp32.cpp +2 -0
  103. esphome/components/deep_sleep/__init__.py +43 -9
  104. esphome/components/demo/__init__.py +2 -2
  105. esphome/components/display/display.cpp +4 -3
  106. esphome/components/display/display.h +0 -2
  107. esphome/components/display/display_buffer.cpp +1 -1
  108. esphome/components/ds2484/__init__.py +1 -0
  109. esphome/components/ds2484/ds2484.cpp +209 -0
  110. esphome/components/ds2484/ds2484.h +43 -0
  111. esphome/components/ds2484/one_wire.py +37 -0
  112. esphome/components/duty_time/duty_time_sensor.h +0 -1
  113. esphome/components/ens160_base/ens160_base.h +0 -1
  114. esphome/components/es7210/es7210.h +0 -1
  115. esphome/components/es7243e/es7243e.h +0 -1
  116. esphome/components/es8156/es8156.h +0 -1
  117. esphome/components/es8311/es8311.h +0 -1
  118. esphome/components/es8388/es8388.h +0 -1
  119. esphome/components/esp32/__init__.py +103 -135
  120. esphome/components/esp32/core.cpp +0 -4
  121. esphome/components/esp32/gpio.h +1 -1
  122. esphome/components/esp32/helpers.cpp +69 -0
  123. esphome/components/esp32_ble/ble.cpp +5 -6
  124. esphome/components/esp32_ble/ble.h +29 -14
  125. esphome/components/esp32_ble/ble_event.h +6 -6
  126. esphome/components/esp32_ble_client/ble_client_base.cpp +21 -6
  127. esphome/components/esp32_ble_client/ble_client_base.h +24 -9
  128. esphome/components/esp32_ble_tracker/__init__.py +2 -8
  129. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +5 -5
  130. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +11 -7
  131. esphome/components/esp32_camera/__init__.py +112 -98
  132. esphome/components/esp32_camera/esp32_camera.cpp +41 -31
  133. esphome/components/esp32_camera/esp32_camera.h +35 -30
  134. esphome/components/esp32_camera_web_server/__init__.py +2 -1
  135. esphome/components/esp32_camera_web_server/camera_web_server.cpp +8 -8
  136. esphome/components/esp32_camera_web_server/camera_web_server.h +3 -3
  137. esphome/components/esp32_hall/sensor.py +2 -21
  138. esphome/components/esp32_hosted/__init__.py +101 -0
  139. esphome/components/esp32_hosted/esp32_hosted.py.script +12 -0
  140. esphome/components/esp32_improv/esp32_improv_component.cpp +3 -0
  141. esphome/components/esp32_rmt/__init__.py +0 -58
  142. esphome/components/esp32_rmt_led_strip/led_strip.cpp +77 -63
  143. esphome/components/esp32_rmt_led_strip/led_strip.h +11 -17
  144. esphome/components/esp32_rmt_led_strip/light.py +14 -76
  145. esphome/components/esp32_touch/esp32_touch.h +174 -28
  146. esphome/components/esp32_touch/esp32_touch_common.cpp +162 -0
  147. esphome/components/esp32_touch/esp32_touch_v1.cpp +240 -0
  148. esphome/components/esp32_touch/esp32_touch_v2.cpp +397 -0
  149. esphome/components/esp8266/__init__.py +2 -0
  150. esphome/components/esp8266/gpio.cpp +10 -10
  151. esphome/components/esp8266/helpers.cpp +31 -0
  152. esphome/components/esphome/ota/__init__.py +1 -0
  153. esphome/components/esphome/ota/ota_esphome.cpp +24 -19
  154. esphome/components/ethernet/__init__.py +42 -23
  155. esphome/components/ethernet/esp_eth_phy_jl1101.c +0 -16
  156. esphome/components/ethernet/ethernet_component.cpp +69 -29
  157. esphome/components/ethernet/ethernet_component.h +18 -10
  158. esphome/components/event/__init__.py +5 -2
  159. esphome/components/ezo/ezo.h +0 -1
  160. esphome/components/ezo_pmp/ezo_pmp.h +0 -1
  161. esphome/components/fan/__init__.py +5 -2
  162. esphome/components/feedback/feedback_cover.h +0 -1
  163. esphome/components/font/__init__.py +92 -82
  164. esphome/components/font/font.cpp +9 -2
  165. esphome/components/font/font.h +20 -5
  166. esphome/components/fs3000/fs3000.h +0 -1
  167. esphome/components/gcja5/gcja5.h +0 -1
  168. esphome/components/gl_r01_i2c/__init__.py +0 -0
  169. esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +68 -0
  170. esphome/components/gl_r01_i2c/gl_r01_i2c.h +22 -0
  171. esphome/components/gl_r01_i2c/sensor.py +36 -0
  172. esphome/components/gp8403/gp8403.h +0 -1
  173. esphome/components/gpio/binary_sensor/__init__.py +17 -0
  174. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +77 -3
  175. esphome/components/gpio/binary_sensor/gpio_binary_sensor.h +40 -0
  176. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +0 -2
  177. esphome/components/he60r/he60r.h +0 -1
  178. esphome/components/heatpumpir/climate.py +2 -1
  179. esphome/components/heatpumpir/heatpumpir.cpp +1 -0
  180. esphome/components/heatpumpir/heatpumpir.h +1 -0
  181. esphome/components/honeywellabp2_i2c/honeywellabp2.h +0 -1
  182. esphome/components/host/__init__.py +3 -1
  183. esphome/components/host/helpers.cpp +57 -0
  184. esphome/components/http_request/__init__.py +19 -1
  185. esphome/components/http_request/http_request.h +1 -1
  186. esphome/components/http_request/http_request_arduino.h +1 -0
  187. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  188. esphome/components/http_request/update/http_request_update.cpp +28 -9
  189. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +3 -9
  190. esphome/components/hydreon_rgxx/sensor.py +1 -1
  191. esphome/components/i2c/__init__.py +23 -11
  192. esphome/components/i2c/i2c_bus.h +8 -1
  193. esphome/components/i2c/i2c_bus_arduino.cpp +4 -3
  194. esphome/components/i2c/i2c_bus_arduino.h +6 -3
  195. esphome/components/i2c/i2c_bus_esp_idf.h +5 -3
  196. esphome/components/i2c_device/i2c_device.h +0 -1
  197. esphome/components/i2s_audio/__init__.py +2 -10
  198. esphome/components/i2s_audio/i2s_audio.cpp +1 -5
  199. esphome/components/i2s_audio/media_player/__init__.py +2 -2
  200. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +2 -2
  201. esphome/components/iaqcore/iaqcore.h +0 -2
  202. esphome/components/image/__init__.py +123 -24
  203. esphome/components/improv_serial/improv_serial_component.cpp +0 -4
  204. esphome/components/ina219/ina219.cpp +7 -0
  205. esphome/components/ina219/ina219.h +1 -0
  206. esphome/components/ina260/ina260.h +0 -2
  207. esphome/components/inkbird_ibsth1_mini/inkbird_ibsth1_mini.h +0 -1
  208. esphome/components/inkplate6/display.py +15 -0
  209. esphome/components/inkplate6/inkplate.cpp +2 -2
  210. esphome/components/integration/integration_sensor.h +0 -1
  211. esphome/components/internal_temperature/internal_temperature.cpp +8 -27
  212. esphome/components/internal_temperature/sensor.py +0 -26
  213. esphome/components/interval/interval.h +0 -2
  214. esphome/components/ld2410/button/__init__.py +3 -3
  215. esphome/components/ld2410/button/factory_reset_button.cpp +9 -0
  216. esphome/components/ld2410/button/{reset_button.h → factory_reset_button.h} +2 -2
  217. esphome/components/ld2410/ld2410.cpp +421 -268
  218. esphome/components/ld2410/ld2410.h +44 -146
  219. esphome/components/ld2410/number/__init__.py +2 -2
  220. esphome/components/ld2410/sensor.py +1 -1
  221. esphome/components/ld2410/switch/__init__.py +1 -1
  222. esphome/components/ld2420/ld2420.cpp +196 -100
  223. esphome/components/ld2420/ld2420.h +46 -118
  224. esphome/components/ld2420/number/__init__.py +2 -2
  225. esphome/components/ld2420/sensor/__init__.py +6 -2
  226. esphome/components/ld2420/sensor/ld2420_sensor.h +1 -1
  227. esphome/components/ld2450/button/__init__.py +3 -3
  228. esphome/components/ld2450/button/factory_reset_button.cpp +9 -0
  229. esphome/components/ld2450/button/{reset_button.h → factory_reset_button.h} +2 -2
  230. esphome/components/ld2450/ld2450.cpp +384 -232
  231. esphome/components/ld2450/ld2450.h +60 -69
  232. esphome/components/ld2450/switch/__init__.py +1 -1
  233. esphome/components/ledc/ledc_output.cpp +1 -63
  234. esphome/components/libretiny/__init__.py +5 -3
  235. esphome/components/libretiny/const.py +5 -0
  236. esphome/components/libretiny/generate_components.py +1 -0
  237. esphome/components/libretiny/helpers.cpp +35 -0
  238. esphome/components/libretiny/lt_component.cpp +5 -3
  239. esphome/components/light/__init__.py +4 -2
  240. esphome/components/light/addressable_light.h +3 -3
  241. esphome/components/light/light_call.cpp +180 -243
  242. esphome/components/light/light_call.h +72 -20
  243. esphome/components/light/light_color_values.h +14 -14
  244. esphome/components/light/light_state.h +15 -13
  245. esphome/components/light/transformers.h +2 -2
  246. esphome/components/ln882x/__init__.py +52 -0
  247. esphome/components/ln882x/boards.py +285 -0
  248. esphome/components/lock/__init__.py +5 -2
  249. esphome/components/logger/__init__.py +40 -3
  250. esphome/components/logger/logger.cpp +47 -12
  251. esphome/components/logger/logger.h +80 -49
  252. esphome/components/logger/logger_esp32.cpp +3 -3
  253. esphome/components/lps22/__init__.py +0 -0
  254. esphome/components/lps22/lps22.cpp +75 -0
  255. esphome/components/lps22/lps22.h +27 -0
  256. esphome/components/lps22/sensor.py +58 -0
  257. esphome/components/ltr390/ltr390.h +0 -1
  258. esphome/components/ltr501/ltr501.h +0 -1
  259. esphome/components/ltr_als_ps/ltr_als_ps.h +0 -1
  260. esphome/components/lvgl/__init__.py +1 -1
  261. esphome/components/lvgl/schemas.py +66 -6
  262. esphome/components/lvgl/styles.py +24 -16
  263. esphome/components/lvgl/widgets/__init__.py +12 -2
  264. esphome/components/lvgl/widgets/lv_bar.py +40 -19
  265. esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +1 -1
  266. esphome/components/max9611/max9611.h +0 -1
  267. esphome/components/mcp23016/__init__.py +1 -1
  268. esphome/components/mcp23xxx_base/__init__.py +1 -1
  269. esphome/components/mcp4461/__init__.py +1 -1
  270. esphome/components/mcp4461/output/__init__.py +3 -2
  271. esphome/components/mcp9600/mcp9600.h +0 -2
  272. esphome/components/md5/md5.cpp +3 -3
  273. esphome/components/md5/md5.h +1 -6
  274. esphome/components/mdns/__init__.py +22 -11
  275. esphome/components/media_player/__init__.py +4 -3
  276. esphome/components/micro_wake_word/__init__.py +1 -5
  277. esphome/components/micro_wake_word/streaming_model.cpp +2 -2
  278. esphome/components/microphone/microphone.cpp +7 -9
  279. esphome/components/microphone/microphone.h +0 -2
  280. esphome/components/mipi_spi/display.py +1 -0
  281. esphome/components/mmc5603/mmc5603.cpp +1 -1
  282. esphome/components/modbus/modbus.cpp +33 -15
  283. esphome/components/modbus/modbus.h +9 -0
  284. esphome/components/modbus_controller/__init__.py +42 -10
  285. esphome/components/modbus_controller/modbus_controller.cpp +92 -11
  286. esphome/components/modbus_controller/modbus_controller.h +61 -7
  287. esphome/components/mopeka_pro_check/mopeka_pro_check.h +0 -1
  288. esphome/components/mopeka_std_check/mopeka_std_check.h +0 -1
  289. esphome/components/mpl3115a2/mpl3115a2.h +0 -2
  290. esphome/components/mqtt/__init__.py +16 -0
  291. esphome/components/mqtt/mqtt_backend.h +2 -1
  292. esphome/components/mqtt/mqtt_backend_esp32.cpp +132 -47
  293. esphome/components/mqtt/mqtt_backend_esp32.h +106 -4
  294. esphome/components/mqtt/mqtt_client.cpp +15 -9
  295. esphome/components/mqtt/mqtt_client.h +8 -3
  296. esphome/components/ms8607/ms8607.h +0 -1
  297. esphome/components/neopixelbus/light.py +4 -1
  298. esphome/components/neopixelbus/neopixelbus_light.h +1 -1
  299. esphome/components/network/__init__.py +4 -1
  300. esphome/components/network/ip_address.h +1 -0
  301. esphome/components/nextion/__init__.py +16 -0
  302. esphome/components/nextion/base_component.py +1 -0
  303. esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +1 -1
  304. esphome/components/nextion/display.py +14 -4
  305. esphome/components/nextion/nextion.cpp +166 -101
  306. esphome/components/nextion/nextion.h +84 -53
  307. esphome/components/nextion/nextion_commands.cpp +11 -10
  308. esphome/components/nextion/nextion_component.cpp +28 -28
  309. esphome/components/nextion/nextion_component.h +53 -18
  310. esphome/components/nextion/nextion_component_base.h +3 -0
  311. esphome/components/nextion/nextion_upload.cpp +36 -0
  312. esphome/components/nextion/nextion_upload_arduino.cpp +10 -35
  313. esphome/components/nextion/nextion_upload_idf.cpp +9 -33
  314. esphome/components/nextion/sensor/nextion_sensor.cpp +1 -1
  315. esphome/components/nextion/switch/nextion_switch.cpp +1 -1
  316. esphome/components/nextion/text_sensor/nextion_textsensor.cpp +1 -1
  317. esphome/components/nfc/nfc.cpp +3 -22
  318. esphome/components/nfc/nfc.h +3 -3
  319. esphome/components/number/__init__.py +5 -2
  320. esphome/components/online_image/__init__.py +5 -0
  321. esphome/components/online_image/online_image.cpp +6 -2
  322. esphome/components/online_image/online_image.h +4 -1
  323. esphome/components/opentherm/opentherm.cpp +7 -12
  324. esphome/components/openthread/__init__.py +47 -40
  325. esphome/components/openthread/const.py +1 -0
  326. esphome/components/openthread/openthread_esp.cpp +27 -5
  327. esphome/components/opt3001/__init__.py +0 -0
  328. esphome/components/opt3001/opt3001.cpp +122 -0
  329. esphome/components/opt3001/opt3001.h +27 -0
  330. esphome/components/opt3001/sensor.py +35 -0
  331. esphome/components/ota/__init__.py +17 -0
  332. esphome/components/ota/ota_backend.h +27 -1
  333. esphome/components/ota/ota_backend_arduino_esp32.cpp +12 -2
  334. esphome/components/ota/ota_backend_arduino_esp32.h +3 -0
  335. esphome/components/ota/ota_backend_arduino_esp8266.cpp +18 -4
  336. esphome/components/ota/ota_backend_arduino_esp8266.h +3 -0
  337. esphome/components/ota/ota_backend_arduino_libretiny.cpp +12 -2
  338. esphome/components/ota/ota_backend_arduino_libretiny.h +3 -0
  339. esphome/components/ota/ota_backend_arduino_rp2040.cpp +9 -2
  340. esphome/components/ota/ota_backend_arduino_rp2040.h +3 -0
  341. esphome/components/ota/ota_backend_esp_idf.cpp +10 -16
  342. esphome/components/ota/ota_backend_esp_idf.h +1 -0
  343. esphome/components/packages/__init__.py +5 -2
  344. esphome/components/packet_transport/binary_sensor.py +61 -4
  345. esphome/components/packet_transport/packet_transport.cpp +34 -1
  346. esphome/components/packet_transport/packet_transport.h +11 -5
  347. esphome/components/pcf8574/__init__.py +1 -1
  348. esphome/components/pi4ioe5v6408/__init__.py +84 -0
  349. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +171 -0
  350. esphome/components/pi4ioe5v6408/pi4ioe5v6408.h +70 -0
  351. esphome/components/pmsa003i/pmsa003i.h +0 -1
  352. esphome/components/pmsx003/pmsx003.h +0 -1
  353. esphome/components/pn7150/pn7150.cpp +7 -7
  354. esphome/components/pn7150/pn7150.h +0 -1
  355. esphome/components/pn7160/pn7160.cpp +7 -7
  356. esphome/components/pn7160/pn7160.h +0 -1
  357. esphome/components/preferences/syncer.h +2 -0
  358. esphome/components/prometheus/prometheus_handler.h +1 -1
  359. esphome/components/psram/psram.cpp +0 -20
  360. esphome/components/pulse_counter/pulse_counter_sensor.h +0 -1
  361. esphome/components/pulse_meter/pulse_meter_sensor.cpp +8 -4
  362. esphome/components/pulse_width/pulse_width.h +0 -1
  363. esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +0 -4
  364. esphome/components/pvvx_mithermometer/display/pvvx_display.h +0 -2
  365. esphome/components/pvvx_mithermometer/pvvx_mithermometer.h +0 -1
  366. esphome/components/qr_code/__init__.py +13 -10
  367. esphome/components/qwiic_pir/qwiic_pir.h +0 -1
  368. esphome/components/radon_eye_ble/radon_eye_listener.cpp +1 -1
  369. esphome/components/rc522/rc522.h +0 -1
  370. esphome/components/rdm6300/rdm6300.h +0 -2
  371. esphome/components/remote_base/__init__.py +7 -5
  372. esphome/components/remote_base/remote_base.cpp +24 -21
  373. esphome/components/remote_base/remote_base.h +3 -26
  374. esphome/components/remote_receiver/__init__.py +40 -46
  375. esphome/components/remote_receiver/remote_receiver.h +4 -18
  376. esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -87
  377. esphome/components/remote_receiver/remote_receiver_esp8266.cpp +1 -1
  378. esphome/components/remote_transmitter/__init__.py +42 -43
  379. esphome/components/remote_transmitter/remote_transmitter.h +2 -14
  380. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -77
  381. esphome/components/resistance/resistance_sensor.h +0 -1
  382. esphome/components/rp2040/__init__.py +2 -0
  383. esphome/components/rp2040/helpers.cpp +55 -0
  384. esphome/components/rp2040_pio_led_strip/led_strip.cpp +2 -2
  385. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -4
  386. esphome/components/rtttl/__init__.py +4 -4
  387. esphome/components/rtttl/rtttl.cpp +10 -1
  388. esphome/components/ruuvitag/ruuvitag.h +0 -1
  389. esphome/components/safe_mode/safe_mode.cpp +2 -0
  390. esphome/components/safe_mode/safe_mode.h +4 -1
  391. esphome/components/scd30/scd30.h +0 -1
  392. esphome/components/scd30/sensor.py +2 -2
  393. esphome/components/scd4x/scd4x.cpp +61 -54
  394. esphome/components/scd4x/scd4x.h +17 -15
  395. esphome/components/scd4x/sensor.py +4 -4
  396. esphome/components/script/script.h +0 -2
  397. esphome/components/sdp3x/sensor.py +1 -1
  398. esphome/components/select/__init__.py +5 -2
  399. esphome/components/sen5x/sen5x.h +0 -1
  400. esphome/components/senseair/senseair.h +0 -1
  401. esphome/components/sensor/__init__.py +4 -2
  402. esphome/components/sensor/filter.cpp +1 -1
  403. esphome/components/sensor/sensor.cpp +12 -6
  404. esphome/components/sensor/sensor.h +13 -5
  405. esphome/components/servo/servo.h +0 -1
  406. esphome/components/sfa30/sfa30.h +0 -1
  407. esphome/components/sgp30/sgp30.h +0 -1
  408. esphome/components/sgp4x/sgp4x.h +0 -1
  409. esphome/components/shelly_dimmer/stm32flash.cpp +1 -2
  410. esphome/components/sht4x/sht4x.h +0 -1
  411. esphome/components/sm300d2/sm300d2.h +0 -2
  412. esphome/components/smt100/sensor.py +8 -4
  413. esphome/components/smt100/smt100.cpp +5 -5
  414. esphome/components/smt100/smt100.h +3 -3
  415. esphome/components/sn74hc595/__init__.py +1 -1
  416. esphome/components/sn74hc595/sn74hc595.cpp +5 -4
  417. esphome/components/sntp/sntp_component.cpp +9 -3
  418. esphome/components/sntp/time.py +2 -0
  419. esphome/components/socket/__init__.py +17 -0
  420. esphome/components/spi/__init__.py +27 -6
  421. esphome/components/spi/spi.cpp +3 -2
  422. esphome/components/spi/spi.h +9 -3
  423. esphome/components/spi/spi_arduino.cpp +3 -5
  424. esphome/components/spi/spi_esp_idf.cpp +40 -21
  425. esphome/components/spi_led_strip/spi_led_strip.cpp +1 -1
  426. esphome/components/sps30/sps30.h +0 -1
  427. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  428. esphome/components/st7701s/st7701s.cpp +0 -4
  429. esphome/components/status/status_binary_sensor.h +0 -2
  430. esphome/components/substitutions/__init__.py +76 -19
  431. esphome/components/substitutions/jinja.py +99 -0
  432. esphome/components/sun/sun.cpp +3 -4
  433. esphome/components/switch/__init__.py +5 -2
  434. esphome/components/switch/binary_sensor/switch_binary_sensor.h +0 -1
  435. esphome/components/sx126x/__init__.py +317 -0
  436. esphome/components/sx126x/automation.h +62 -0
  437. esphome/components/sx126x/packet_transport/__init__.py +26 -0
  438. esphome/components/sx126x/packet_transport/sx126x_transport.cpp +26 -0
  439. esphome/components/sx126x/packet_transport/sx126x_transport.h +25 -0
  440. esphome/components/sx126x/sx126x.cpp +523 -0
  441. esphome/components/sx126x/sx126x.h +140 -0
  442. esphome/components/sx126x/sx126x_reg.h +163 -0
  443. esphome/components/sx127x/__init__.py +325 -0
  444. esphome/components/sx127x/automation.h +62 -0
  445. esphome/components/sx127x/packet_transport/__init__.py +26 -0
  446. esphome/components/sx127x/packet_transport/sx127x_transport.cpp +26 -0
  447. esphome/components/sx127x/packet_transport/sx127x_transport.h +25 -0
  448. esphome/components/sx127x/sx127x.cpp +498 -0
  449. esphome/components/sx127x/sx127x.h +128 -0
  450. esphome/components/sx127x/sx127x_reg.h +295 -0
  451. esphome/components/syslog/esphome_syslog.cpp +5 -3
  452. esphome/components/syslog/esphome_syslog.h +1 -1
  453. esphome/components/tca9555/__init__.py +1 -1
  454. esphome/components/template/binary_sensor/template_binary_sensor.cpp +1 -9
  455. esphome/components/text/__init__.py +5 -2
  456. esphome/components/text_sensor/__init__.py +5 -2
  457. esphome/components/thermostat/thermostat_climate.cpp +34 -31
  458. esphome/components/thermostat/thermostat_climate.h +43 -39
  459. esphome/components/time/__init__.py +16 -2
  460. esphome/components/time/real_time_clock.cpp +4 -0
  461. esphome/components/time/real_time_clock.h +5 -1
  462. esphome/components/tlc5971/tlc5971.cpp +4 -1
  463. esphome/components/tmp1075/tmp1075.h +0 -2
  464. esphome/components/tof10120/tof10120_sensor.h +0 -1
  465. esphome/components/tormatic/tormatic_cover.h +0 -1
  466. esphome/components/total_daily_energy/total_daily_energy.h +0 -1
  467. esphome/components/tsl2591/tsl2591.cpp +1 -1
  468. esphome/components/ttp229_bsf/ttp229_bsf.h +0 -1
  469. esphome/components/ttp229_lsf/ttp229_lsf.h +0 -1
  470. esphome/components/tx20/tx20.cpp +2 -2
  471. esphome/components/uart/__init__.py +18 -0
  472. esphome/components/uart/uart_component_esp_idf.cpp +0 -4
  473. esphome/components/update/__init__.py +5 -2
  474. esphome/components/update/update_entity.h +8 -0
  475. esphome/components/usb_host/__init__.py +5 -2
  476. esphome/components/usb_host/usb_host_client.cpp +10 -10
  477. esphome/components/usb_uart/cp210x.cpp +1 -1
  478. esphome/components/usb_uart/usb_uart.cpp +41 -44
  479. esphome/components/usb_uart/usb_uart.h +4 -3
  480. esphome/components/valve/__init__.py +5 -2
  481. esphome/components/vbus/vbus.h +0 -1
  482. esphome/components/veml3235/veml3235.h +0 -1
  483. esphome/components/veml7700/veml7700.h +0 -1
  484. esphome/components/vl53l0x/vl53l0x_sensor.h +0 -1
  485. esphome/components/voice_assistant/voice_assistant.cpp +4 -4
  486. esphome/components/watchdog/watchdog.cpp +0 -4
  487. esphome/components/waveshare_epaper/waveshare_epaper.cpp +6 -6
  488. esphome/components/web_server/__init__.py +34 -19
  489. esphome/components/web_server/ota/__init__.py +32 -0
  490. esphome/components/web_server/ota/ota_web_server.cpp +210 -0
  491. esphome/components/web_server/ota/ota_web_server.h +26 -0
  492. esphome/components/web_server/web_server.cpp +305 -427
  493. esphome/components/web_server/web_server.h +33 -23
  494. esphome/components/web_server/web_server_v1.cpp +4 -5
  495. esphome/components/web_server_base/__init__.py +5 -2
  496. esphome/components/web_server_base/web_server_base.cpp +2 -94
  497. esphome/components/web_server_base/web_server_base.h +5 -25
  498. esphome/components/web_server_idf/multipart.cpp +254 -0
  499. esphome/components/web_server_idf/multipart.h +86 -0
  500. esphome/components/web_server_idf/utils.cpp +32 -0
  501. esphome/components/web_server_idf/utils.h +10 -0
  502. esphome/components/web_server_idf/web_server_idf.cpp +162 -16
  503. esphome/components/web_server_idf/web_server_idf.h +11 -10
  504. esphome/components/wiegand/wiegand.cpp +2 -2
  505. esphome/components/wifi/__init__.py +18 -0
  506. esphome/components/wifi/wifi_component.cpp +17 -22
  507. esphome/components/wifi/wifi_component.h +27 -23
  508. esphome/components/wifi/wifi_component_esp32_arduino.cpp +52 -59
  509. esphome/components/wifi/wifi_component_esp8266.cpp +46 -46
  510. esphome/components/wifi/wifi_component_esp_idf.cpp +35 -36
  511. esphome/components/wifi/wifi_component_libretiny.cpp +26 -27
  512. esphome/components/wifi/wifi_component_pico_w.cpp +3 -3
  513. esphome/components/wifi_info/wifi_info_text_sensor.cpp +6 -6
  514. esphome/components/wireguard/__init__.py +2 -11
  515. esphome/components/xiaomi_ble/xiaomi_ble.cpp +13 -1
  516. esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
  517. esphome/components/xiaomi_cgd1/xiaomi_cgd1.h +0 -1
  518. esphome/components/xiaomi_cgdk2/xiaomi_cgdk2.h +0 -1
  519. esphome/components/xiaomi_cgg1/xiaomi_cgg1.h +0 -1
  520. esphome/components/xiaomi_cgpr1/xiaomi_cgpr1.h +0 -1
  521. esphome/components/xiaomi_gcls002/xiaomi_gcls002.h +0 -1
  522. esphome/components/xiaomi_hhccjcy01/xiaomi_hhccjcy01.h +0 -1
  523. esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h +0 -1
  524. esphome/components/xiaomi_hhccpot002/xiaomi_hhccpot002.h +0 -1
  525. esphome/components/xiaomi_jqjcy01ym/xiaomi_jqjcy01ym.h +0 -1
  526. esphome/components/xiaomi_lywsd02/xiaomi_lywsd02.h +0 -1
  527. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +0 -1
  528. esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.h +0 -1
  529. esphome/components/xiaomi_lywsdcgq/xiaomi_lywsdcgq.h +0 -1
  530. esphome/components/xiaomi_mhoc303/xiaomi_mhoc303.h +0 -1
  531. esphome/components/xiaomi_mhoc401/xiaomi_mhoc401.h +0 -1
  532. esphome/components/xiaomi_miscale/xiaomi_miscale.h +0 -1
  533. esphome/components/xiaomi_mjyd02yla/xiaomi_mjyd02yla.h +0 -1
  534. esphome/components/xiaomi_mue4094rt/xiaomi_mue4094rt.h +0 -1
  535. esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.h +0 -1
  536. esphome/components/xiaomi_wx08zm/xiaomi_wx08zm.h +0 -1
  537. esphome/components/xiaomi_xmwsdj04mmc/__init__.py +0 -0
  538. esphome/components/xiaomi_xmwsdj04mmc/sensor.py +77 -0
  539. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp +77 -0
  540. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.h +36 -0
  541. esphome/components/zio_ultrasonic/zio_ultrasonic.h +0 -2
  542. esphome/components/zyaura/zyaura.h +0 -1
  543. esphome/config.py +88 -22
  544. esphome/config_helpers.py +74 -1
  545. esphome/config_validation.py +12 -1
  546. esphome/const.py +65 -10
  547. esphome/core/__init__.py +18 -2
  548. esphome/core/application.cpp +163 -10
  549. esphome/core/application.h +145 -165
  550. esphome/core/area.h +19 -0
  551. esphome/core/automation.h +58 -9
  552. esphome/core/color.cpp +3 -5
  553. esphome/core/color.h +16 -16
  554. esphome/core/component.cpp +151 -18
  555. esphome/core/component.h +98 -4
  556. esphome/core/component_iterator.cpp +11 -9
  557. esphome/core/component_iterator.h +12 -10
  558. esphome/core/config.py +155 -6
  559. esphome/core/controller.cpp +4 -2
  560. esphome/core/controller.h +1 -1
  561. esphome/core/datatypes.h +2 -2
  562. esphome/core/defines.h +17 -2
  563. esphome/core/device.h +20 -0
  564. esphome/core/entity_base.cpp +20 -15
  565. esphome/core/entity_base.h +76 -0
  566. esphome/core/entity_helpers.py +168 -1
  567. esphome/core/event_pool.h +81 -0
  568. esphome/core/helpers.cpp +75 -230
  569. esphome/core/helpers.h +164 -104
  570. esphome/core/lock_free_queue.h +151 -0
  571. esphome/core/log.cpp +2 -2
  572. esphome/core/log.h +2 -0
  573. esphome/core/optional.h +5 -0
  574. esphome/core/ring_buffer.cpp +2 -2
  575. esphome/core/scheduler.cpp +275 -103
  576. esphome/core/scheduler.h +154 -17
  577. esphome/core/time.cpp +5 -5
  578. esphome/core/time.h +5 -5
  579. esphome/cpp_generator.py +17 -0
  580. esphome/cpp_helpers.py +0 -22
  581. esphome/cpp_types.py +3 -1
  582. esphome/dashboard/entries.py +1 -1
  583. esphome/dashboard/util/text.py +5 -21
  584. esphome/dashboard/web_server.py +9 -1
  585. esphome/helpers.py +47 -0
  586. esphome/loader.py +15 -1
  587. esphome/pins.py +14 -8
  588. esphome/wizard.py +17 -4
  589. esphome/writer.py +21 -3
  590. esphome/yaml_util.py +0 -2
  591. {esphome-2025.6.3.dist-info → esphome-2025.7.0b2.dist-info}/METADATA +10 -9
  592. {esphome-2025.6.3.dist-info → esphome-2025.7.0b2.dist-info}/RECORD +597 -538
  593. esphome/components/api/api_pb2_size.h +0 -361
  594. esphome/components/esp32_ble/ble_event_pool.h +0 -72
  595. esphome/components/esp32_ble/queue.h +0 -85
  596. esphome/components/esp32_hall/esp32_hall.cpp +0 -25
  597. esphome/components/esp32_hall/esp32_hall.h +0 -23
  598. esphome/components/esp32_touch/esp32_touch.cpp +0 -355
  599. esphome/components/ld2410/button/reset_button.cpp +0 -9
  600. esphome/components/ld2450/button/reset_button.cpp +0 -9
  601. esphome/components/openthread/tlv.py +0 -65
  602. /esphome/{dashboard/enum.py → enum.py} +0 -0
  603. {esphome-2025.6.3.dist-info → esphome-2025.7.0b2.dist-info}/WHEEL +0 -0
  604. {esphome-2025.6.3.dist-info → esphome-2025.7.0b2.dist-info}/entry_points.txt +0 -0
  605. {esphome-2025.6.3.dist-info → esphome-2025.7.0b2.dist-info}/licenses/LICENSE +0 -0
  606. {esphome-2025.6.3.dist-info → esphome-2025.7.0b2.dist-info}/top_level.txt +0 -0
@@ -33,8 +33,6 @@ class Microphone {
33
33
  audio::AudioStreamInfo get_audio_stream_info() { return this->audio_stream_info_; }
34
34
 
35
35
  protected:
36
- std::vector<uint8_t> silence_audio_(std::vector<uint8_t> data);
37
-
38
36
  State state_{STATE_STOPPED};
39
37
  bool mute_state_{false};
40
38
 
@@ -472,3 +472,4 @@ async def to_code(config):
472
472
  cg.add(var.set_writer(lambda_))
473
473
  await display.register_display(var, config)
474
474
  await spi.register_spi_device(var, config)
475
+ cg.add(var.set_write_only(True))
@@ -39,7 +39,7 @@ void MMC5603Component::setup() {
39
39
  return;
40
40
  }
41
41
 
42
- if (id != MMC56X3_CHIP_ID) {
42
+ if (id != 0 && id != MMC56X3_CHIP_ID) { // ID is not reported correctly by all chips, 0 on some chips
43
43
  ESP_LOGCONFIG(TAG, "Chip Wrong");
44
44
  this->error_code_ = ID_REGISTERS;
45
45
  this->mark_failed();
@@ -90,15 +90,24 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) {
90
90
 
91
91
  } else {
92
92
  // data starts at 2 and length is 4 for read registers commands
93
- if (this->role == ModbusRole::SERVER && (function_code == 0x1 || function_code == 0x3 || function_code == 0x4)) {
94
- data_offset = 2;
95
- data_len = 4;
96
- }
97
-
98
- // the response for write command mirrors the requests and data starts at offset 2 instead of 3 for read commands
99
- if (function_code == 0x5 || function_code == 0x06 || function_code == 0xF || function_code == 0x10) {
100
- data_offset = 2;
101
- data_len = 4;
93
+ if (this->role == ModbusRole::SERVER) {
94
+ if (function_code == 0x1 || function_code == 0x3 || function_code == 0x4 || function_code == 0x6) {
95
+ data_offset = 2;
96
+ data_len = 4;
97
+ } else if (function_code == 0x10) {
98
+ if (at < 6) {
99
+ return true;
100
+ }
101
+ data_offset = 2;
102
+ // starting address (2 bytes) + quantity of registers (2 bytes) + byte count itself (1 byte) + actual byte count
103
+ data_len = 2 + 2 + 1 + raw[6];
104
+ }
105
+ } else {
106
+ // the response for write command mirrors the requests and data starts at offset 2 instead of 3 for read commands
107
+ if (function_code == 0x5 || function_code == 0x06 || function_code == 0xF || function_code == 0x10) {
108
+ data_offset = 2;
109
+ data_len = 4;
110
+ }
102
111
  }
103
112
 
104
113
  // Error ( msb indicates error )
@@ -132,6 +141,7 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) {
132
141
  bool found = false;
133
142
  for (auto *device : this->devices_) {
134
143
  if (device->address_ == address) {
144
+ found = true;
135
145
  // Is it an error response?
136
146
  if ((function_code & 0x80) == 0x80) {
137
147
  ESP_LOGD(TAG, "Modbus error function code: 0x%X exception: %d", function_code, raw[2]);
@@ -141,13 +151,21 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) {
141
151
  // Ignore modbus exception not related to a pending command
142
152
  ESP_LOGD(TAG, "Ignoring Modbus error - not expecting a response");
143
153
  }
144
- } else if (this->role == ModbusRole::SERVER && (function_code == 0x3 || function_code == 0x4)) {
145
- device->on_modbus_read_registers(function_code, uint16_t(data[1]) | (uint16_t(data[0]) << 8),
146
- uint16_t(data[3]) | (uint16_t(data[2]) << 8));
147
- } else {
148
- device->on_modbus_data(data);
154
+ continue;
149
155
  }
150
- found = true;
156
+ if (this->role == ModbusRole::SERVER) {
157
+ if (function_code == 0x3 || function_code == 0x4) {
158
+ device->on_modbus_read_registers(function_code, uint16_t(data[1]) | (uint16_t(data[0]) << 8),
159
+ uint16_t(data[3]) | (uint16_t(data[2]) << 8));
160
+ continue;
161
+ }
162
+ if (function_code == 0x6 || function_code == 0x10) {
163
+ device->on_modbus_write_registers(function_code, data);
164
+ continue;
165
+ }
166
+ }
167
+ // fallthrough for other function codes
168
+ device->on_modbus_data(data);
151
169
  }
152
170
  }
153
171
  waiting_for_response = 0;
@@ -59,11 +59,20 @@ class ModbusDevice {
59
59
  virtual void on_modbus_data(const std::vector<uint8_t> &data) = 0;
60
60
  virtual void on_modbus_error(uint8_t function_code, uint8_t exception_code) {}
61
61
  virtual void on_modbus_read_registers(uint8_t function_code, uint16_t start_address, uint16_t number_of_registers){};
62
+ virtual void on_modbus_write_registers(uint8_t function_code, const std::vector<uint8_t> &data){};
62
63
  void send(uint8_t function, uint16_t start_address, uint16_t number_of_entities, uint8_t payload_len = 0,
63
64
  const uint8_t *payload = nullptr) {
64
65
  this->parent_->send(this->address_, function, start_address, number_of_entities, payload_len, payload);
65
66
  }
66
67
  void send_raw(const std::vector<uint8_t> &payload) { this->parent_->send_raw(payload); }
68
+ void send_error(uint8_t function_code, uint8_t exception_code) {
69
+ std::vector<uint8_t> error_response;
70
+ error_response.reserve(3);
71
+ error_response.push_back(this->address_);
72
+ error_response.push_back(function_code | 0x80);
73
+ error_response.push_back(exception_code);
74
+ this->send_raw(error_response);
75
+ }
67
76
  // If more than one device is connected block sending a new command before a response is received
68
77
  bool waiting_for_response() { return parent_->waiting_for_response != 0; }
69
78
 
@@ -39,6 +39,7 @@ CODEOWNERS = ["@martgras"]
39
39
  AUTO_LOAD = ["modbus"]
40
40
 
41
41
  CONF_READ_LAMBDA = "read_lambda"
42
+ CONF_WRITE_LAMBDA = "write_lambda"
42
43
  CONF_SERVER_REGISTERS = "server_registers"
43
44
  MULTI_CONF = True
44
45
 
@@ -112,6 +113,22 @@ TYPE_REGISTER_MAP = {
112
113
  "FP32_R": 2,
113
114
  }
114
115
 
116
+ CPP_TYPE_REGISTER_MAP = {
117
+ "RAW": cg.uint16,
118
+ "U_WORD": cg.uint16,
119
+ "S_WORD": cg.int16,
120
+ "U_DWORD": cg.uint32,
121
+ "U_DWORD_R": cg.uint32,
122
+ "S_DWORD": cg.int32,
123
+ "S_DWORD_R": cg.int32,
124
+ "U_QWORD": cg.uint64,
125
+ "U_QWORD_R": cg.uint64,
126
+ "S_QWORD": cg.int64,
127
+ "S_QWORD_R": cg.int64,
128
+ "FP32": cg.float_,
129
+ "FP32_R": cg.float_,
130
+ }
131
+
115
132
  ModbusCommandSentTrigger = modbus_controller_ns.class_(
116
133
  "ModbusCommandSentTrigger", automation.Trigger.template(cg.int_, cg.int_)
117
134
  )
@@ -132,6 +149,7 @@ ModbusServerRegisterSchema = cv.Schema(
132
149
  cv.Required(CONF_ADDRESS): cv.positive_int,
133
150
  cv.Optional(CONF_VALUE_TYPE, default="U_WORD"): cv.enum(SENSOR_VALUE_TYPE),
134
151
  cv.Required(CONF_READ_LAMBDA): cv.returning_lambda,
152
+ cv.Optional(CONF_WRITE_LAMBDA): cv.returning_lambda,
135
153
  }
136
154
  )
137
155
 
@@ -285,21 +303,35 @@ async def to_code(config):
285
303
  cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES]))
286
304
  if CONF_SERVER_REGISTERS in config:
287
305
  for server_register in config[CONF_SERVER_REGISTERS]:
306
+ server_register_var = cg.new_Pvariable(
307
+ server_register[CONF_ID],
308
+ server_register[CONF_ADDRESS],
309
+ server_register[CONF_VALUE_TYPE],
310
+ TYPE_REGISTER_MAP[server_register[CONF_VALUE_TYPE]],
311
+ )
312
+ cpp_type = CPP_TYPE_REGISTER_MAP[server_register[CONF_VALUE_TYPE]]
288
313
  cg.add(
289
- var.add_server_register(
290
- cg.new_Pvariable(
291
- server_register[CONF_ID],
292
- server_register[CONF_ADDRESS],
293
- server_register[CONF_VALUE_TYPE],
294
- TYPE_REGISTER_MAP[server_register[CONF_VALUE_TYPE]],
314
+ server_register_var.set_read_lambda(
315
+ cg.TemplateArguments(cpp_type),
316
+ await cg.process_lambda(
317
+ server_register[CONF_READ_LAMBDA],
318
+ [(cg.uint16, "address")],
319
+ return_type=cpp_type,
320
+ ),
321
+ )
322
+ )
323
+ if CONF_WRITE_LAMBDA in server_register:
324
+ cg.add(
325
+ server_register_var.set_write_lambda(
326
+ cg.TemplateArguments(cpp_type),
295
327
  await cg.process_lambda(
296
- server_register[CONF_READ_LAMBDA],
297
- [],
298
- return_type=cg.float_,
328
+ server_register[CONF_WRITE_LAMBDA],
329
+ parameters=[(cg.uint16, "address"), (cpp_type, "x")],
330
+ return_type=cg.bool_,
299
331
  ),
300
332
  )
301
333
  )
302
- )
334
+ cg.add(var.add_server_register(server_register_var))
303
335
  await register_modbus_device(var, config)
304
336
  for conf in config.get(CONF_ON_COMMAND_SENT, []):
305
337
  trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
@@ -117,12 +117,17 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t
117
117
  bool found = false;
118
118
  for (auto *server_register : this->server_registers_) {
119
119
  if (server_register->address == current_address) {
120
- float value = server_register->read_lambda();
121
-
122
- ESP_LOGD(TAG, "Matched register. Address: 0x%02X. Value type: %zu. Register count: %u. Value: %0.1f.",
123
- server_register->address, static_cast<uint8_t>(server_register->value_type),
124
- server_register->register_count, value);
125
- std::vector<uint16_t> payload = float_to_payload(value, server_register->value_type);
120
+ if (!server_register->read_lambda) {
121
+ break;
122
+ }
123
+ int64_t value = server_register->read_lambda();
124
+ ESP_LOGD(TAG, "Matched register. Address: 0x%02X. Value type: %zu. Register count: %u. Value: %s.",
125
+ server_register->address, static_cast<size_t>(server_register->value_type),
126
+ server_register->register_count, server_register->format_value(value).c_str());
127
+
128
+ std::vector<uint16_t> payload;
129
+ payload.reserve(server_register->register_count * 2);
130
+ number_to_payload(payload, value, server_register->value_type);
126
131
  sixteen_bit_response.insert(sixteen_bit_response.end(), payload.cbegin(), payload.cend());
127
132
  current_address += server_register->register_count;
128
133
  found = true;
@@ -132,11 +137,7 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t
132
137
 
133
138
  if (!found) {
134
139
  ESP_LOGW(TAG, "Could not match any register to address %02X. Sending exception response.", current_address);
135
- std::vector<uint8_t> error_response;
136
- error_response.push_back(this->address_);
137
- error_response.push_back(0x81);
138
- error_response.push_back(0x02);
139
- this->send_raw(error_response);
140
+ send_error(function_code, 0x02);
140
141
  return;
141
142
  }
142
143
  }
@@ -151,6 +152,86 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t
151
152
  this->send(function_code, start_address, number_of_registers, response.size(), response.data());
152
153
  }
153
154
 
155
+ void ModbusController::on_modbus_write_registers(uint8_t function_code, const std::vector<uint8_t> &data) {
156
+ uint16_t number_of_registers;
157
+ uint16_t payload_offset;
158
+
159
+ if (function_code == 0x10) {
160
+ number_of_registers = uint16_t(data[3]) | (uint16_t(data[2]) << 8);
161
+ if (number_of_registers == 0 || number_of_registers > 0x7B) {
162
+ ESP_LOGW(TAG, "Invalid number of registers %d. Sending exception response.", number_of_registers);
163
+ send_error(function_code, 3);
164
+ return;
165
+ }
166
+ uint16_t payload_size = data[4];
167
+ if (payload_size != number_of_registers * 2) {
168
+ ESP_LOGW(TAG, "Payload size of %d bytes is not 2 times the number of registers (%d). Sending exception response.",
169
+ payload_size, number_of_registers);
170
+ send_error(function_code, 3);
171
+ return;
172
+ }
173
+ payload_offset = 5;
174
+ } else if (function_code == 0x06) {
175
+ number_of_registers = 1;
176
+ payload_offset = 2;
177
+ } else {
178
+ ESP_LOGW(TAG, "Invalid function code 0x%X. Sending exception response.", function_code);
179
+ send_error(function_code, 1);
180
+ return;
181
+ }
182
+
183
+ uint16_t start_address = uint16_t(data[1]) | (uint16_t(data[0]) << 8);
184
+ ESP_LOGD(TAG,
185
+ "Received write holding registers for device 0x%X. FC: 0x%X. Start address: 0x%X. Number of registers: "
186
+ "0x%X.",
187
+ this->address_, function_code, start_address, number_of_registers);
188
+
189
+ auto for_each_register = [this, start_address, number_of_registers, payload_offset](
190
+ const std::function<bool(ServerRegister *, uint16_t offset)> &callback) -> bool {
191
+ uint16_t offset = payload_offset;
192
+ for (uint16_t current_address = start_address; current_address < start_address + number_of_registers;) {
193
+ bool ok = false;
194
+ for (auto *server_register : this->server_registers_) {
195
+ if (server_register->address == current_address) {
196
+ ok = callback(server_register, offset);
197
+ current_address += server_register->register_count;
198
+ offset += server_register->register_count * sizeof(uint16_t);
199
+ break;
200
+ }
201
+ }
202
+
203
+ if (!ok) {
204
+ return false;
205
+ }
206
+ }
207
+ return true;
208
+ };
209
+
210
+ // check all registers are writable before writing to any of them:
211
+ if (!for_each_register([](ServerRegister *server_register, uint16_t offset) -> bool {
212
+ return server_register->write_lambda != nullptr;
213
+ })) {
214
+ send_error(function_code, 1);
215
+ return;
216
+ }
217
+
218
+ // Actually write to the registers:
219
+ if (!for_each_register([&data](ServerRegister *server_register, uint16_t offset) {
220
+ int64_t number = payload_to_number(data, server_register->value_type, offset, 0xFFFFFFFF);
221
+ return server_register->write_lambda(number);
222
+ })) {
223
+ send_error(function_code, 4);
224
+ return;
225
+ }
226
+
227
+ std::vector<uint8_t> response;
228
+ response.reserve(6);
229
+ response.push_back(this->address_);
230
+ response.push_back(function_code);
231
+ response.insert(response.end(), data.begin(), data.begin() + 4);
232
+ this->send_raw(response);
233
+ }
234
+
154
235
  SensorSet ModbusController::find_sensors_(ModbusRegisterType register_type, uint16_t start_address) const {
155
236
  auto reg_it = std::find_if(
156
237
  std::begin(this->register_ranges_), std::end(this->register_ranges_),
@@ -63,6 +63,10 @@ enum class SensorValueType : uint8_t {
63
63
  FP32_R = 0xD
64
64
  };
65
65
 
66
+ inline bool value_type_is_float(SensorValueType v) {
67
+ return v == SensorValueType::FP32 || v == SensorValueType::FP32_R;
68
+ }
69
+
66
70
  inline ModbusFunctionCode modbus_register_read_function(ModbusRegisterType reg_type) {
67
71
  switch (reg_type) {
68
72
  case ModbusRegisterType::COIL:
@@ -253,18 +257,66 @@ class SensorItem {
253
257
  };
254
258
 
255
259
  class ServerRegister {
260
+ using ReadLambda = std::function<int64_t()>;
261
+ using WriteLambda = std::function<bool(int64_t value)>;
262
+
256
263
  public:
257
- ServerRegister(uint16_t address, SensorValueType value_type, uint8_t register_count,
258
- std::function<float()> read_lambda) {
264
+ ServerRegister(uint16_t address, SensorValueType value_type, uint8_t register_count) {
259
265
  this->address = address;
260
266
  this->value_type = value_type;
261
267
  this->register_count = register_count;
262
- this->read_lambda = std::move(read_lambda);
263
268
  }
269
+
270
+ template<typename T> void set_read_lambda(const std::function<T(uint16_t address)> &&user_read_lambda) {
271
+ this->read_lambda = [this, user_read_lambda]() -> int64_t {
272
+ T user_value = user_read_lambda(this->address);
273
+ if constexpr (std::is_same_v<T, float>) {
274
+ return bit_cast<uint32_t>(user_value);
275
+ } else {
276
+ return static_cast<int64_t>(user_value);
277
+ }
278
+ };
279
+ }
280
+
281
+ template<typename T>
282
+ void set_write_lambda(const std::function<bool(uint16_t address, const T v)> &&user_write_lambda) {
283
+ this->write_lambda = [this, user_write_lambda](int64_t number) {
284
+ if constexpr (std::is_same_v<T, float>) {
285
+ float float_value = bit_cast<float>(static_cast<uint32_t>(number));
286
+ return user_write_lambda(this->address, float_value);
287
+ }
288
+ return user_write_lambda(this->address, static_cast<T>(number));
289
+ };
290
+ }
291
+
292
+ // Formats a raw value into a string representation based on the value type for debugging
293
+ std::string format_value(int64_t value) const {
294
+ switch (this->value_type) {
295
+ case SensorValueType::U_WORD:
296
+ case SensorValueType::U_DWORD:
297
+ case SensorValueType::U_DWORD_R:
298
+ case SensorValueType::U_QWORD:
299
+ case SensorValueType::U_QWORD_R:
300
+ return std::to_string(static_cast<uint64_t>(value));
301
+ case SensorValueType::S_WORD:
302
+ case SensorValueType::S_DWORD:
303
+ case SensorValueType::S_DWORD_R:
304
+ case SensorValueType::S_QWORD:
305
+ case SensorValueType::S_QWORD_R:
306
+ return std::to_string(value);
307
+ case SensorValueType::FP32_R:
308
+ case SensorValueType::FP32:
309
+ return str_sprintf("%.1f", bit_cast<float>(static_cast<uint32_t>(value)));
310
+ default:
311
+ return std::to_string(value);
312
+ }
313
+ }
314
+
264
315
  uint16_t address{0};
265
316
  SensorValueType value_type{SensorValueType::RAW};
266
317
  uint8_t register_count{0};
267
- std::function<float()> read_lambda;
318
+ ReadLambda read_lambda;
319
+ WriteLambda write_lambda;
268
320
  };
269
321
 
270
322
  // ModbusController::create_register_ranges_ tries to optimize register range
@@ -444,8 +496,10 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice {
444
496
  void on_modbus_data(const std::vector<uint8_t> &data) override;
445
497
  /// called when a modbus error response was received
446
498
  void on_modbus_error(uint8_t function_code, uint8_t exception_code) override;
447
- /// called when a modbus request (function code 3 or 4) was parsed without errors
499
+ /// called when a modbus request (function code 0x03 or 0x04) was parsed without errors
448
500
  void on_modbus_read_registers(uint8_t function_code, uint16_t start_address, uint16_t number_of_registers) final;
501
+ /// called when a modbus request (function code 0x06 or 0x10) was parsed without errors
502
+ void on_modbus_write_registers(uint8_t function_code, const std::vector<uint8_t> &data) final;
449
503
  /// default delegate called by process_modbus_data when a response has retrieved from the incoming queue
450
504
  void on_register_data(ModbusRegisterType register_type, uint16_t start_address, const std::vector<uint8_t> &data);
451
505
  /// default delegate called by process_modbus_data when a response for a write response has retrieved from the
@@ -529,7 +583,7 @@ inline float payload_to_float(const std::vector<uint8_t> &data, const SensorItem
529
583
  int64_t number = payload_to_number(data, item.sensor_value_type, item.offset, item.bitmask);
530
584
 
531
585
  float float_value;
532
- if (item.sensor_value_type == SensorValueType::FP32 || item.sensor_value_type == SensorValueType::FP32_R) {
586
+ if (value_type_is_float(item.sensor_value_type)) {
533
587
  float_value = bit_cast<float>(static_cast<uint32_t>(number));
534
588
  } else {
535
589
  float_value = static_cast<float>(number);
@@ -541,7 +595,7 @@ inline float payload_to_float(const std::vector<uint8_t> &data, const SensorItem
541
595
  inline std::vector<uint16_t> float_to_payload(float value, SensorValueType value_type) {
542
596
  int64_t val;
543
597
 
544
- if (value_type == SensorValueType::FP32 || value_type == SensorValueType::FP32_R) {
598
+ if (value_type_is_float(value_type)) {
545
599
  val = bit_cast<uint32_t>(value);
546
600
  } else {
547
601
  val = llroundf(value);
@@ -34,7 +34,6 @@ class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceLi
34
34
 
35
35
  bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
36
36
  void dump_config() override;
37
- float get_setup_priority() const override { return setup_priority::DATA; }
38
37
  void set_min_signal_quality(SensorReadQuality min) { this->min_signal_quality_ = min; };
39
38
 
40
39
  void set_level(sensor::Sensor *level) { level_ = level; };
@@ -48,7 +48,6 @@ class MopekaStdCheck : public Component, public esp32_ble_tracker::ESPBTDeviceLi
48
48
 
49
49
  bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
50
50
  void dump_config() override;
51
- float get_setup_priority() const override { return setup_priority::DATA; }
52
51
 
53
52
  void set_level(sensor::Sensor *level) { this->level_ = level; };
54
53
  void set_temperature(sensor::Sensor *temperature) { this->temperature_ = temperature; };
@@ -91,8 +91,6 @@ class MPL3115A2Component : public PollingComponent, public i2c::I2CDevice {
91
91
  void dump_config() override;
92
92
  void update() override;
93
93
 
94
- float get_setup_priority() const override { return setup_priority::DATA; }
95
-
96
94
  protected:
97
95
  sensor::Sensor *temperature_{nullptr};
98
96
  sensor::Sensor *altitude_{nullptr};
@@ -5,6 +5,7 @@ from esphome.automation import Condition
5
5
  import esphome.codegen as cg
6
6
  from esphome.components import logger
7
7
  from esphome.components.esp32 import add_idf_sdkconfig_option
8
+ from esphome.config_helpers import filter_source_files_from_platform
8
9
  import esphome.config_validation as cv
9
10
  from esphome.const import (
10
11
  CONF_AVAILABILITY,
@@ -54,6 +55,7 @@ from esphome.const import (
54
55
  PLATFORM_BK72XX,
55
56
  PLATFORM_ESP32,
56
57
  PLATFORM_ESP8266,
58
+ PlatformFramework,
57
59
  )
58
60
  from esphome.core import CORE, coroutine_with_priority
59
61
 
@@ -68,6 +70,7 @@ def AUTO_LOAD():
68
70
 
69
71
  CONF_DISCOVER_IP = "discover_ip"
70
72
  CONF_IDF_SEND_ASYNC = "idf_send_async"
73
+ CONF_WAIT_FOR_CONNECTION = "wait_for_connection"
71
74
 
72
75
 
73
76
  def validate_message_just_topic(value):
@@ -298,6 +301,7 @@ CONFIG_SCHEMA = cv.All(
298
301
  }
299
302
  ),
300
303
  cv.Optional(CONF_PUBLISH_NAN_AS_NONE, default=False): cv.boolean,
304
+ cv.Optional(CONF_WAIT_FOR_CONNECTION, default=False): cv.boolean,
301
305
  }
302
306
  ),
303
307
  validate_config,
@@ -453,6 +457,8 @@ async def to_code(config):
453
457
 
454
458
  cg.add(var.set_publish_nan_as_none(config[CONF_PUBLISH_NAN_AS_NONE]))
455
459
 
460
+ cg.add(var.set_wait_for_connection(config[CONF_WAIT_FOR_CONNECTION]))
461
+
456
462
 
457
463
  MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema(
458
464
  {
@@ -592,3 +598,13 @@ async def mqtt_enable_to_code(config, action_id, template_arg, args):
592
598
  async def mqtt_disable_to_code(config, action_id, template_arg, args):
593
599
  paren = await cg.get_variable(config[CONF_ID])
594
600
  return cg.new_Pvariable(action_id, template_arg, paren)
601
+
602
+
603
+ FILTER_SOURCE_FILES = filter_source_files_from_platform(
604
+ {
605
+ "mqtt_backend_esp32.cpp": {
606
+ PlatformFramework.ESP32_ARDUINO,
607
+ PlatformFramework.ESP32_IDF,
608
+ },
609
+ }
610
+ )
@@ -17,7 +17,8 @@ enum class MQTTClientDisconnectReason : int8_t {
17
17
  MQTT_MALFORMED_CREDENTIALS = 4,
18
18
  MQTT_NOT_AUTHORIZED = 5,
19
19
  ESP8266_NOT_ENOUGH_SPACE = 6,
20
- TLS_BAD_FINGERPRINT = 7
20
+ TLS_BAD_FINGERPRINT = 7,
21
+ DNS_RESOLVE_ERROR = 8
21
22
  };
22
23
 
23
24
  /// internal struct for MQTT messages.