esphome 2025.4.1__py3-none-any.whl → 2025.5.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 (412) hide show
  1. esphome/components/ac_dimmer/ac_dimmer.cpp +3 -2
  2. esphome/components/adc/__init__.py +51 -34
  3. esphome/components/airthings_wave_base/__init__.py +1 -1
  4. esphome/components/alarm_control_panel/__init__.py +37 -2
  5. esphome/components/am43/cover/__init__.py +4 -5
  6. esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +6 -4
  7. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +4 -5
  8. esphome/components/analog_threshold/binary_sensor.py +10 -8
  9. esphome/components/anova/climate.py +4 -5
  10. esphome/components/api/__init__.py +25 -8
  11. esphome/components/api/api_connection.cpp +77 -10
  12. esphome/components/api/api_connection.h +6 -1
  13. esphome/components/api/api_frame_helper.cpp +98 -130
  14. esphome/components/api/api_frame_helper.h +12 -2
  15. esphome/components/api/api_noise_context.h +13 -4
  16. esphome/components/api/api_pb2.cpp +1422 -1
  17. esphome/components/api/api_pb2.h +255 -1
  18. esphome/components/api/api_pb2_service.cpp +162 -49
  19. esphome/components/api/api_pb2_service.h +90 -51
  20. esphome/components/api/api_pb2_size.h +361 -0
  21. esphome/components/api/api_server.cpp +110 -34
  22. esphome/components/api/api_server.h +8 -0
  23. esphome/components/api/proto.h +38 -9
  24. esphome/components/as3935_i2c/as3935_i2c.h +0 -3
  25. esphome/components/as7341/as7341.h +1 -1
  26. esphome/components/atm90e32/__init__.py +1 -0
  27. esphome/components/atm90e32/atm90e32.cpp +576 -199
  28. esphome/components/atm90e32/atm90e32.h +128 -31
  29. esphome/components/atm90e32/atm90e32_reg.h +4 -2
  30. esphome/components/atm90e32/button/__init__.py +62 -10
  31. esphome/components/atm90e32/button/atm90e32_button.cpp +63 -4
  32. esphome/components/atm90e32/button/atm90e32_button.h +36 -4
  33. esphome/components/atm90e32/number/__init__.py +130 -0
  34. esphome/components/atm90e32/number/atm90e32_number.h +16 -0
  35. esphome/components/atm90e32/sensor.py +21 -4
  36. esphome/components/atm90e32/text_sensor/__init__.py +48 -0
  37. esphome/components/audio/__init__.py +96 -49
  38. esphome/components/audio/audio.h +48 -0
  39. esphome/components/audio/audio_decoder.cpp +1 -1
  40. esphome/components/audio/audio_resampler.cpp +2 -0
  41. esphome/components/audio/audio_resampler.h +1 -0
  42. esphome/components/ballu/climate.py +2 -9
  43. esphome/components/bang_bang/climate.py +5 -6
  44. esphome/components/bedjet/climate/__init__.py +3 -8
  45. esphome/components/bedjet/fan/__init__.py +2 -11
  46. esphome/components/binary/fan/__init__.py +13 -16
  47. esphome/components/binary_sensor/__init__.py +13 -10
  48. esphome/components/binary_sensor/binary_sensor.cpp +6 -10
  49. esphome/components/binary_sensor/binary_sensor.h +1 -1
  50. esphome/components/binary_sensor/filter.cpp +21 -21
  51. esphome/components/binary_sensor/filter.h +10 -10
  52. esphome/components/bl0906/constants.h +16 -16
  53. esphome/components/ble_client/text_sensor/__init__.py +3 -5
  54. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
  55. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +135 -21
  56. esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
  57. esphome/components/button/__init__.py +11 -8
  58. esphome/components/canbus/canbus.cpp +3 -0
  59. esphome/components/canbus/canbus.h +16 -0
  60. esphome/components/climate/__init__.py +35 -2
  61. esphome/components/climate/climate_mode.h +1 -1
  62. esphome/components/climate/climate_traits.h +63 -57
  63. esphome/components/climate_ir/__init__.py +57 -17
  64. esphome/components/climate_ir_lg/climate.py +2 -5
  65. esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
  66. esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
  67. esphome/components/color/__init__.py +2 -0
  68. esphome/components/const/__init__.py +5 -0
  69. esphome/components/coolix/climate.py +2 -9
  70. esphome/components/copy/cover/__init__.py +10 -9
  71. esphome/components/copy/fan/__init__.py +11 -9
  72. esphome/components/copy/lock/__init__.py +11 -9
  73. esphome/components/copy/text/__init__.py +9 -6
  74. esphome/components/cover/__init__.py +37 -2
  75. esphome/components/cst226/binary_sensor/__init__.py +28 -0
  76. esphome/components/cst226/binary_sensor/cs226_button.h +22 -0
  77. esphome/components/cst226/binary_sensor/cstt6_button.cpp +19 -0
  78. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +27 -5
  79. esphome/components/cst226/touchscreen/cst226_touchscreen.h +10 -10
  80. esphome/components/current_based/cover.py +37 -36
  81. esphome/components/daikin/climate.py +2 -9
  82. esphome/components/daikin/daikin.cpp +15 -9
  83. esphome/components/daikin/daikin.h +5 -5
  84. esphome/components/daikin_arc/climate.py +2 -7
  85. esphome/components/daikin_brc/climate.py +3 -5
  86. esphome/components/dallas_temp/dallas_temp.cpp +17 -24
  87. esphome/components/dallas_temp/dallas_temp.h +0 -1
  88. esphome/components/debug/debug_component.cpp +5 -0
  89. esphome/components/debug/debug_component.h +6 -0
  90. esphome/components/debug/debug_esp32.cpp +109 -254
  91. esphome/components/debug/sensor.py +14 -0
  92. esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
  93. esphome/components/delonghi/climate.py +2 -9
  94. esphome/components/demo/__init__.py +18 -20
  95. esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
  96. esphome/components/display/rect.cpp +4 -9
  97. esphome/components/display/rect.h +1 -1
  98. esphome/components/emmeti/climate.py +2 -9
  99. esphome/components/endstop/cover.py +17 -16
  100. esphome/components/esp32/__init__.py +60 -3
  101. esphome/components/esp32/core.cpp +11 -5
  102. esphome/components/esp32/gpio.cpp +86 -24
  103. esphome/components/esp32/gpio.py +15 -16
  104. esphome/components/esp32/gpio_esp32.py +1 -2
  105. esphome/components/esp32/gpio_esp32_c2.py +1 -1
  106. esphome/components/esp32/gpio_esp32_c3.py +1 -1
  107. esphome/components/esp32/gpio_esp32_c6.py +1 -1
  108. esphome/components/esp32/gpio_esp32_h2.py +1 -1
  109. esphome/components/esp32_ble/ble.cpp +1 -8
  110. esphome/components/esp32_ble/ble.h +5 -3
  111. esphome/components/esp32_ble/ble_advertising.h +1 -0
  112. esphome/components/esp32_ble_server/__init__.py +3 -0
  113. esphome/components/esp32_ble_tracker/__init__.py +7 -1
  114. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
  115. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
  116. esphome/components/esp32_can/esp32_can.cpp +1 -1
  117. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  118. esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
  119. esphome/components/esp32_rmt_led_strip/light.py +9 -1
  120. esphome/components/esp8266/gpio.cpp +69 -8
  121. esphome/components/event/__init__.py +13 -10
  122. esphome/components/factory_reset/switch/__init__.py +7 -21
  123. esphome/components/fan/__init__.py +52 -5
  124. esphome/components/fastled_base/__init__.py +1 -4
  125. esphome/components/fastled_base/fastled_light.cpp +1 -1
  126. esphome/components/feedback/cover.py +38 -33
  127. esphome/components/fujitsu_general/climate.py +2 -9
  128. esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
  129. esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
  130. esphome/components/gpio_expander/cached_gpio.h +22 -7
  131. esphome/components/gps/__init__.py +11 -2
  132. esphome/components/gps/gps.cpp +11 -8
  133. esphome/components/gps/gps.h +9 -6
  134. esphome/components/graph/__init__.py +1 -2
  135. esphome/components/gree/climate.py +4 -6
  136. esphome/components/gree/gree.cpp +16 -2
  137. esphome/components/gree/gree.h +2 -2
  138. esphome/components/haier/climate.py +37 -34
  139. esphome/components/hbridge/fan/__init__.py +19 -17
  140. esphome/components/he60r/cover.py +4 -5
  141. esphome/components/heatpumpir/climate.py +3 -6
  142. esphome/components/hitachi_ac344/climate.py +2 -9
  143. esphome/components/hitachi_ac424/climate.py +2 -9
  144. esphome/components/hlw8012/hlw8012.cpp +1 -1
  145. esphome/components/hm3301/hm3301.h +1 -1
  146. esphome/components/http_request/__init__.py +39 -6
  147. esphome/components/http_request/http_request.cpp +20 -0
  148. esphome/components/http_request/http_request.h +57 -15
  149. esphome/components/http_request/http_request_arduino.cpp +22 -6
  150. esphome/components/http_request/http_request_arduino.h +4 -3
  151. esphome/components/http_request/http_request_host.cpp +141 -0
  152. esphome/components/http_request/http_request_host.h +37 -0
  153. esphome/components/http_request/http_request_idf.cpp +35 -3
  154. esphome/components/http_request/http_request_idf.h +10 -3
  155. esphome/components/http_request/httplib.h +9691 -0
  156. esphome/components/http_request/update/__init__.py +11 -8
  157. esphome/components/i2c/i2c.h +4 -0
  158. esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
  159. esphome/components/i2s_audio/__init__.py +131 -22
  160. esphome/components/i2s_audio/i2s_audio.h +44 -4
  161. esphome/components/i2s_audio/media_player/__init__.py +19 -9
  162. esphome/components/i2s_audio/microphone/__init__.py +63 -5
  163. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
  164. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
  165. esphome/components/i2s_audio/speaker/__init__.py +31 -5
  166. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
  167. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
  168. esphome/components/ili9xxx/ili9xxx_init.h +1 -1
  169. esphome/components/image/__init__.py +37 -17
  170. esphome/components/image/image.cpp +25 -8
  171. esphome/components/internal_temperature/internal_temperature.cpp +6 -4
  172. esphome/components/key_collector/__init__.py +35 -0
  173. esphome/components/key_collector/key_collector.cpp +8 -0
  174. esphome/components/key_collector/key_collector.h +10 -0
  175. esphome/components/ld2410/ld2410.h +1 -1
  176. esphome/components/ld2450/ld2450.h +1 -1
  177. esphome/components/light/__init__.py +57 -0
  178. esphome/components/lock/__init__.py +51 -4
  179. esphome/components/lock/automation.h +2 -13
  180. esphome/components/logger/__init__.py +21 -0
  181. esphome/components/logger/logger.cpp +125 -95
  182. esphome/components/logger/logger.h +160 -35
  183. esphome/components/logger/task_log_buffer.cpp +138 -0
  184. esphome/components/logger/task_log_buffer.h +69 -0
  185. esphome/components/lvgl/__init__.py +13 -5
  186. esphome/components/lvgl/automation.py +50 -1
  187. esphome/components/lvgl/defines.py +0 -1
  188. esphome/components/lvgl/lv_validation.py +10 -1
  189. esphome/components/lvgl/lvgl_esphome.cpp +5 -1
  190. esphome/components/lvgl/schemas.py +14 -14
  191. esphome/components/lvgl/text/__init__.py +1 -2
  192. esphome/components/lvgl/widgets/arc.py +7 -6
  193. esphome/components/lvgl/widgets/buttonmatrix.py +3 -3
  194. esphome/components/lvgl/widgets/checkbox.py +2 -2
  195. esphome/components/lvgl/widgets/dropdown.py +2 -1
  196. esphome/components/lvgl/widgets/img.py +15 -12
  197. esphome/components/mapping/__init__.py +134 -0
  198. esphome/components/max7219digit/max7219digit.cpp +27 -27
  199. esphome/components/mdns/__init__.py +11 -5
  200. esphome/components/mdns/mdns_component.cpp +11 -5
  201. esphome/components/mdns/mdns_component.h +3 -2
  202. esphome/components/mdns/mdns_esp32.cpp +4 -3
  203. esphome/components/mdns/mdns_esp8266.cpp +4 -2
  204. esphome/components/mdns/mdns_libretiny.cpp +4 -2
  205. esphome/components/mdns/mdns_rp2040.cpp +4 -2
  206. esphome/components/media_player/__init__.py +40 -6
  207. esphome/components/micro_wake_word/__init__.py +99 -31
  208. esphome/components/micro_wake_word/automation.h +54 -0
  209. esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
  210. esphome/components/micro_wake_word/micro_wake_word.h +58 -105
  211. esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
  212. esphome/components/micro_wake_word/streaming_model.cpp +158 -41
  213. esphome/components/micro_wake_word/streaming_model.h +85 -13
  214. esphome/components/microphone/__init__.py +139 -9
  215. esphome/components/microphone/automation.h +14 -2
  216. esphome/components/microphone/microphone.cpp +21 -0
  217. esphome/components/microphone/microphone.h +14 -5
  218. esphome/components/microphone/microphone_source.cpp +95 -0
  219. esphome/components/microphone/microphone_source.h +80 -0
  220. esphome/components/mics_4514/sensor.py +25 -14
  221. esphome/components/midea/climate.py +3 -4
  222. esphome/components/midea_ir/climate.py +3 -5
  223. esphome/components/mipi_spi/__init__.py +15 -0
  224. esphome/components/mipi_spi/display.py +474 -0
  225. esphome/components/mipi_spi/mipi_spi.cpp +481 -0
  226. esphome/components/mipi_spi/mipi_spi.h +171 -0
  227. esphome/components/mipi_spi/models/__init__.py +65 -0
  228. esphome/components/mipi_spi/models/amoled.py +72 -0
  229. esphome/components/mipi_spi/models/commands.py +82 -0
  230. esphome/components/mipi_spi/models/cyd.py +10 -0
  231. esphome/components/mipi_spi/models/ili.py +749 -0
  232. esphome/components/mipi_spi/models/jc.py +260 -0
  233. esphome/components/mipi_spi/models/lanbon.py +15 -0
  234. esphome/components/mipi_spi/models/lilygo.py +60 -0
  235. esphome/components/mipi_spi/models/waveshare.py +139 -0
  236. esphome/components/mitsubishi/climate.py +2 -5
  237. esphome/components/mitsubishi/mitsubishi.cpp +9 -9
  238. esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
  239. esphome/components/mixer/speaker/mixer_speaker.h +1 -3
  240. esphome/components/mlx90393/sensor.py +5 -0
  241. esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
  242. esphome/components/mlx90393/sensor_mlx90393.h +21 -4
  243. esphome/components/mqtt/__init__.py +1 -1
  244. esphome/components/mqtt/mqtt_client.cpp +5 -1
  245. esphome/components/mqtt/mqtt_const.h +4 -0
  246. esphome/components/mqtt/mqtt_fan.cpp +39 -0
  247. esphome/components/mqtt/mqtt_fan.h +2 -0
  248. esphome/components/network/__init__.py +1 -1
  249. esphome/components/nextion/base_component.py +17 -16
  250. esphome/components/nextion/display.py +11 -2
  251. esphome/components/nextion/nextion.cpp +39 -1
  252. esphome/components/nextion/nextion.h +50 -0
  253. esphome/components/noblex/climate.py +2 -9
  254. esphome/components/number/__init__.py +12 -9
  255. esphome/components/one_wire/one_wire_bus.cpp +14 -10
  256. esphome/components/one_wire/one_wire_bus.h +14 -8
  257. esphome/components/online_image/bmp_image.cpp +48 -11
  258. esphome/components/online_image/bmp_image.h +2 -0
  259. esphome/components/opentherm/binary_sensor/__init__.py +2 -4
  260. esphome/components/opentherm/number/__init__.py +11 -20
  261. esphome/components/opentherm/sensor/__init__.py +3 -3
  262. esphome/components/opentherm/switch/__init__.py +3 -5
  263. esphome/components/output/lock/__init__.py +11 -9
  264. esphome/components/packages/__init__.py +33 -31
  265. esphome/components/packet_transport/__init__.py +201 -0
  266. esphome/components/packet_transport/binary_sensor.py +19 -0
  267. esphome/components/packet_transport/packet_transport.cpp +534 -0
  268. esphome/components/packet_transport/packet_transport.h +154 -0
  269. esphome/components/packet_transport/sensor.py +19 -0
  270. esphome/components/pca9685/pca9685_output.cpp +2 -1
  271. esphome/components/pid/climate.py +2 -4
  272. esphome/components/pm2005/__init__.py +1 -0
  273. esphome/components/pm2005/pm2005.cpp +123 -0
  274. esphome/components/pm2005/pm2005.h +46 -0
  275. esphome/components/pm2005/sensor.py +86 -0
  276. esphome/components/pmsa003i/pmsa003i.cpp +43 -16
  277. esphome/components/pmsa003i/pmsa003i.h +25 -25
  278. esphome/components/pmsx003/pmsx003.cpp +193 -229
  279. esphome/components/pmsx003/pmsx003.h +51 -33
  280. esphome/components/pmsx003/sensor.py +21 -11
  281. esphome/components/pn7150/pn7150.h +2 -2
  282. esphome/components/pn7160/pn7160.h +2 -2
  283. esphome/components/prometheus/prometheus_handler.cpp +174 -0
  284. esphome/components/prometheus/prometheus_handler.h +17 -0
  285. esphome/components/psram/__init__.py +7 -5
  286. esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
  287. esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
  288. esphome/components/qspi_dbi/__init__.py +0 -1
  289. esphome/components/qspi_dbi/display.py +2 -1
  290. esphome/components/qspi_dbi/models.py +1 -2
  291. esphome/components/remote_base/__init__.py +91 -0
  292. esphome/components/remote_base/beo4_protocol.cpp +153 -0
  293. esphome/components/remote_base/beo4_protocol.h +43 -0
  294. esphome/components/remote_base/gobox_protocol.cpp +131 -0
  295. esphome/components/remote_base/gobox_protocol.h +54 -0
  296. esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
  297. esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
  298. esphome/components/resampler/speaker/resampler_speaker.h +1 -1
  299. esphome/components/scd30/sensor.py +2 -3
  300. esphome/components/scd4x/sensor.py +4 -5
  301. esphome/components/sdp3x/sensor.py +2 -1
  302. esphome/components/select/__init__.py +19 -20
  303. esphome/components/sen5x/sensor.py +1 -1
  304. esphome/components/sensor/__init__.py +158 -14
  305. esphome/components/sensor/filter.cpp +23 -0
  306. esphome/components/sensor/filter.h +22 -0
  307. esphome/components/sgp4x/sensor.py +1 -1
  308. esphome/components/sht4x/sht4x.cpp +43 -22
  309. esphome/components/sht4x/sht4x.h +1 -1
  310. esphome/components/sml/text_sensor/__init__.py +4 -6
  311. esphome/components/sound_level/__init__.py +0 -0
  312. esphome/components/sound_level/sensor.py +97 -0
  313. esphome/components/sound_level/sound_level.cpp +194 -0
  314. esphome/components/sound_level/sound_level.h +73 -0
  315. esphome/components/speaker/media_player/__init__.py +4 -8
  316. esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
  317. esphome/components/speaker/media_player/speaker_media_player.h +0 -11
  318. esphome/components/speaker/speaker.h +4 -7
  319. esphome/components/speed/fan/__init__.py +17 -16
  320. esphome/components/spi/spi.h +11 -1
  321. esphome/components/sprinkler/__init__.py +18 -19
  322. esphome/components/switch/__init__.py +32 -42
  323. esphome/components/syslog/__init__.py +41 -0
  324. esphome/components/syslog/esphome_syslog.cpp +49 -0
  325. esphome/components/syslog/esphome_syslog.h +27 -0
  326. esphome/components/tca9555/tca9555.cpp +11 -6
  327. esphome/components/tcl112/climate.py +2 -9
  328. esphome/components/template/alarm_control_panel/__init__.py +7 -6
  329. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
  330. esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
  331. esphome/components/template/cover/__init__.py +27 -21
  332. esphome/components/template/fan/__init__.py +14 -12
  333. esphome/components/template/lock/__init__.py +20 -25
  334. esphome/components/template/lock/automation.h +18 -0
  335. esphome/components/template/text/__init__.py +4 -3
  336. esphome/components/template/valve/__init__.py +32 -21
  337. esphome/components/template/valve/automation.h +24 -0
  338. esphome/components/text/__init__.py +32 -1
  339. esphome/components/text_sensor/__init__.py +24 -29
  340. esphome/components/thermostat/climate.py +5 -5
  341. esphome/components/time_based/cover.py +17 -16
  342. esphome/components/tm1638/switch/__init__.py +10 -7
  343. esphome/components/tormatic/cover.py +4 -5
  344. esphome/components/toshiba/climate.py +3 -5
  345. esphome/components/touchscreen/touchscreen.cpp +3 -1
  346. esphome/components/tt21100/touchscreen/tt21100.cpp +1 -1
  347. esphome/components/tuya/climate/__init__.py +5 -6
  348. esphome/components/tuya/cover/__init__.py +6 -11
  349. esphome/components/tuya/select/__init__.py +15 -5
  350. esphome/components/tuya/select/tuya_select.cpp +6 -1
  351. esphome/components/tuya/select/tuya_select.h +5 -1
  352. esphome/components/uart/packet_transport/__init__.py +20 -0
  353. esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
  354. esphome/components/uart/packet_transport/uart_transport.h +41 -0
  355. esphome/components/udp/__init__.py +126 -128
  356. esphome/components/udp/automation.h +40 -0
  357. esphome/components/udp/binary_sensor.py +3 -25
  358. esphome/components/udp/packet_transport/__init__.py +29 -0
  359. esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
  360. esphome/components/udp/packet_transport/udp_transport.h +28 -0
  361. esphome/components/udp/sensor.py +3 -25
  362. esphome/components/udp/udp_component.cpp +26 -470
  363. esphome/components/udp/udp_component.h +21 -128
  364. esphome/components/update/__init__.py +31 -1
  365. esphome/components/uponor_smatrix/climate/__init__.py +4 -9
  366. esphome/components/uptime/text_sensor/__init__.py +47 -7
  367. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
  368. esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
  369. esphome/components/valve/__init__.py +34 -3
  370. esphome/components/valve/automation.h +1 -19
  371. esphome/components/vl53l0x/sensor.py +11 -0
  372. esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
  373. esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
  374. esphome/components/voice_assistant/__init__.py +36 -10
  375. esphome/components/voice_assistant/voice_assistant.cpp +170 -144
  376. esphome/components/voice_assistant/voice_assistant.h +26 -25
  377. esphome/components/waveshare_epaper/display.py +6 -0
  378. esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
  379. esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
  380. esphome/components/whirlpool/climate.py +3 -5
  381. esphome/components/whynter/climate.py +3 -5
  382. esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
  383. esphome/components/yashima/climate.py +6 -6
  384. esphome/components/zhlt01/climate.py +2 -7
  385. esphome/config_validation.py +38 -58
  386. esphome/const.py +15 -1
  387. esphome/core/__init__.py +2 -0
  388. esphome/core/application.cpp +1 -0
  389. esphome/core/application.h +4 -0
  390. esphome/core/automation.h +4 -3
  391. esphome/core/component.cpp +19 -3
  392. esphome/core/component.h +5 -0
  393. esphome/core/defines.h +23 -17
  394. esphome/core/macros.h +4 -0
  395. esphome/core/scheduler.cpp +3 -0
  396. esphome/cpp_generator.py +6 -2
  397. esphome/dashboard/web_server.py +3 -3
  398. esphome/helpers.py +39 -0
  399. esphome/loader.py +4 -0
  400. esphome/mqtt.py +21 -8
  401. esphome/platformio_api.py +1 -1
  402. esphome/schema_extractors.py +0 -1
  403. esphome/vscode.py +15 -0
  404. esphome/wizard.py +2 -2
  405. esphome/zeroconf.py +7 -3
  406. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/METADATA +10 -11
  407. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/RECORD +411 -352
  408. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/WHEEL +1 -1
  409. esphome/components/esp32_ble/const_esp32c6.h +0 -74
  410. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/entry_points.txt +0 -0
  411. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/licenses/LICENSE +0 -0
  412. {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/top_level.txt +0 -0
@@ -10,8 +10,10 @@ static const char *const TAG = "gpio.one_wire";
10
10
  void GPIOOneWireBus::setup() {
11
11
  ESP_LOGCONFIG(TAG, "Setting up 1-wire bus...");
12
12
  this->t_pin_->setup();
13
- // clear bus with 480µs high, otherwise initial reset in search might fail
14
13
  this->t_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
14
+ // clear bus with 480µs high, otherwise initial reset in search might fail
15
+ this->pin_.digital_write(true);
16
+ this->pin_.pin_mode(gpio::FLAG_OUTPUT);
15
17
  delayMicroseconds(480);
16
18
  this->search();
17
19
  }
@@ -22,40 +24,49 @@ void GPIOOneWireBus::dump_config() {
22
24
  this->dump_devices_(TAG);
23
25
  }
24
26
 
25
- bool HOT IRAM_ATTR GPIOOneWireBus::reset() {
27
+ int HOT IRAM_ATTR GPIOOneWireBus::reset_int() {
28
+ InterruptLock lock;
26
29
  // See reset here:
27
30
  // https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/126.html
28
31
  // Wait for communication to clear (delay G)
29
- pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
32
+ this->pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
30
33
  uint8_t retries = 125;
31
34
  do {
32
35
  if (--retries == 0)
33
- return false;
36
+ return -1;
34
37
  delayMicroseconds(2);
35
- } while (!pin_.digital_read());
38
+ } while (!this->pin_.digital_read());
36
39
 
37
- bool r;
40
+ bool r = false;
38
41
 
39
42
  // Send 480µs LOW TX reset pulse (drive bus low, delay H)
40
- pin_.pin_mode(gpio::FLAG_OUTPUT);
41
- pin_.digital_write(false);
43
+ this->pin_.digital_write(false);
44
+ this->pin_.pin_mode(gpio::FLAG_OUTPUT);
42
45
  delayMicroseconds(480);
43
46
 
44
47
  // Release the bus, delay I
45
- pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
46
- delayMicroseconds(70);
48
+ this->pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
49
+ uint32_t start = micros();
50
+ delayMicroseconds(30);
51
+
52
+ while (micros() - start < 300) {
53
+ // sample bus, 0=device(s) present, 1=no device present
54
+ r = !this->pin_.digital_read();
55
+ if (r)
56
+ break;
57
+ delayMicroseconds(1);
58
+ }
47
59
 
48
- // sample bus, 0=device(s) present, 1=no device present
49
- r = !pin_.digital_read();
50
60
  // delay J
51
- delayMicroseconds(410);
52
- return r;
61
+ delayMicroseconds(start + 480 - micros());
62
+ this->pin_.digital_write(true);
63
+ this->pin_.pin_mode(gpio::FLAG_OUTPUT);
64
+ return r ? 1 : 0;
53
65
  }
54
66
 
55
67
  void HOT IRAM_ATTR GPIOOneWireBus::write_bit_(bool bit) {
56
68
  // drive bus low
57
- pin_.pin_mode(gpio::FLAG_OUTPUT);
58
- pin_.digital_write(false);
69
+ this->pin_.digital_write(false);
59
70
 
60
71
  // from datasheet:
61
72
  // write 0 low time: t_low0: min=60µs, max=120µs
@@ -64,72 +75,62 @@ void HOT IRAM_ATTR GPIOOneWireBus::write_bit_(bool bit) {
64
75
  // recovery time: t_rec: min=1µs
65
76
  // ds18b20 appears to read the bus after roughly 14µs
66
77
  uint32_t delay0 = bit ? 6 : 60;
67
- uint32_t delay1 = bit ? 59 : 5;
78
+ uint32_t delay1 = bit ? 64 : 10;
68
79
 
69
80
  // delay A/C
70
81
  delayMicroseconds(delay0);
71
82
  // release bus
72
- pin_.digital_write(true);
83
+ this->pin_.digital_write(true);
73
84
  // delay B/D
74
85
  delayMicroseconds(delay1);
75
86
  }
76
87
 
77
88
  bool HOT IRAM_ATTR GPIOOneWireBus::read_bit_() {
78
89
  // drive bus low
79
- pin_.pin_mode(gpio::FLAG_OUTPUT);
80
- pin_.digital_write(false);
90
+ this->pin_.digital_write(false);
81
91
 
82
- // note: for reading we'll need very accurate timing, as the
83
- // timing for the digital_read() is tight; according to the datasheet,
84
- // we should read at the end of 16µs starting from the bus low
85
- // typically, the ds18b20 pulls the line high after 11µs for a logical 1
86
- // and 29µs for a logical 0
87
-
88
- uint32_t start = micros();
89
- // datasheet says >1µs
90
- delayMicroseconds(2);
92
+ // datasheet says >= 1µs
93
+ delayMicroseconds(5);
91
94
 
92
95
  // release bus, delay E
93
- pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
94
-
95
- // measure from start value directly, to get best accurate timing no matter
96
- // how long pin_mode/delayMicroseconds took
97
- uint32_t now = micros();
98
- if (now - start < 12)
99
- delayMicroseconds(12 - (now - start));
96
+ this->pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
100
97
 
98
+ delayMicroseconds(8);
101
99
  // sample bus to read bit from peer
102
- bool r = pin_.digital_read();
100
+ bool r = this->pin_.digital_read();
103
101
 
104
- // read slot is at least 60µs; get as close to 60µs to spend less time with interrupts locked
105
- now = micros();
106
- if (now - start < 60)
107
- delayMicroseconds(60 - (now - start));
102
+ // read slot is at least 60µs
103
+ delayMicroseconds(50);
108
104
 
105
+ this->pin_.digital_write(true);
106
+ this->pin_.pin_mode(gpio::FLAG_OUTPUT);
109
107
  return r;
110
108
  }
111
109
 
112
110
  void IRAM_ATTR GPIOOneWireBus::write8(uint8_t val) {
111
+ InterruptLock lock;
113
112
  for (uint8_t i = 0; i < 8; i++) {
114
113
  this->write_bit_(bool((1u << i) & val));
115
114
  }
116
115
  }
117
116
 
118
117
  void IRAM_ATTR GPIOOneWireBus::write64(uint64_t val) {
118
+ InterruptLock lock;
119
119
  for (uint8_t i = 0; i < 64; i++) {
120
120
  this->write_bit_(bool((1ULL << i) & val));
121
121
  }
122
122
  }
123
123
 
124
124
  uint8_t IRAM_ATTR GPIOOneWireBus::read8() {
125
+ InterruptLock lock;
125
126
  uint8_t ret = 0;
126
- for (uint8_t i = 0; i < 8; i++) {
127
+ for (uint8_t i = 0; i < 8; i++)
127
128
  ret |= (uint8_t(this->read_bit_()) << i);
128
- }
129
129
  return ret;
130
130
  }
131
131
 
132
132
  uint64_t IRAM_ATTR GPIOOneWireBus::read64() {
133
+ InterruptLock lock;
133
134
  uint64_t ret = 0;
134
135
  for (uint8_t i = 0; i < 8; i++) {
135
136
  ret |= (uint64_t(this->read_bit_()) << i);
@@ -144,6 +145,7 @@ void GPIOOneWireBus::reset_search() {
144
145
  }
145
146
 
146
147
  uint64_t IRAM_ATTR GPIOOneWireBus::search_int() {
148
+ InterruptLock lock;
147
149
  if (this->last_device_flag_)
148
150
  return 0u;
149
151
 
@@ -18,7 +18,6 @@ class GPIOOneWireBus : public one_wire::OneWireBus, public Component {
18
18
  this->pin_ = pin->to_isr();
19
19
  }
20
20
 
21
- bool reset() override;
22
21
  void write8(uint8_t val) override;
23
22
  void write64(uint64_t val) override;
24
23
  uint8_t read8() override;
@@ -31,10 +30,12 @@ class GPIOOneWireBus : public one_wire::OneWireBus, public Component {
31
30
  bool last_device_flag_{false};
32
31
  uint64_t address_;
33
32
 
33
+ int reset_int() override;
34
34
  void reset_search() override;
35
35
  uint64_t search_int() override;
36
36
  void write_bit_(bool bit);
37
37
  bool read_bit_();
38
+ bool read_bit_(uint32_t *t);
38
39
  };
39
40
 
40
41
  } // namespace gpio
@@ -8,30 +8,45 @@ namespace esphome {
8
8
  namespace gpio_expander {
9
9
 
10
10
  /// @brief A class to cache the read state of a GPIO expander.
11
+ /// This class caches reads between GPIO Pins which are on the same bank.
12
+ /// This means that for reading whole Port (ex. 8 pins) component needs only one
13
+ /// I2C/SPI read per main loop call. It assumes, that one bit in byte identifies one GPIO pin
14
+ /// Template parameters:
15
+ /// T - Type which represents internal register. Could be uint8_t or uint16_t. Adjust to
16
+ /// match size of your internal GPIO bank register.
17
+ /// N - Number of pins
11
18
  template<typename T, T N> class CachedGpioExpander {
12
19
  public:
13
20
  bool digital_read(T pin) {
14
- if (!this->read_cache_invalidated_[pin]) {
15
- this->read_cache_invalidated_[pin] = true;
16
- return this->digital_read_cache(pin);
21
+ uint8_t bank = pin / (sizeof(T) * BITS_PER_BYTE);
22
+ if (this->read_cache_invalidated_[bank]) {
23
+ this->read_cache_invalidated_[bank] = false;
24
+ if (!this->digital_read_hw(pin))
25
+ return false;
17
26
  }
18
- return this->digital_read_hw(pin);
27
+ return this->digital_read_cache(pin);
19
28
  }
20
29
 
21
30
  void digital_write(T pin, bool value) { this->digital_write_hw(pin, value); }
22
31
 
23
32
  protected:
33
+ /// @brief Call component low level function to read GPIO state from device
24
34
  virtual bool digital_read_hw(T pin) = 0;
35
+ /// @brief Call component read function from internal cache.
25
36
  virtual bool digital_read_cache(T pin) = 0;
37
+ /// @brief Call component low level function to write GPIO state to device
26
38
  virtual void digital_write_hw(T pin, bool value) = 0;
39
+ const uint8_t cache_byte_size_ = N / (sizeof(T) * BITS_PER_BYTE);
27
40
 
41
+ /// @brief Invalidate cache. This function should be called in component loop().
28
42
  void reset_pin_cache_() {
29
- for (T i = 0; i < N; i++) {
30
- this->read_cache_invalidated_[i] = false;
43
+ for (T i = 0; i < this->cache_byte_size_; i++) {
44
+ this->read_cache_invalidated_[i] = true;
31
45
  }
32
46
  }
33
47
 
34
- std::array<bool, N> read_cache_invalidated_{};
48
+ static const uint8_t BITS_PER_BYTE = 8;
49
+ std::array<bool, N / (sizeof(T) * BITS_PER_BYTE)> read_cache_invalidated_{};
35
50
  };
36
51
 
37
52
  } // namespace gpio_expander
@@ -25,6 +25,7 @@ GPS = gps_ns.class_("GPS", cg.Component, uart.UARTDevice)
25
25
  GPSListener = gps_ns.class_("GPSListener")
26
26
 
27
27
  CONF_GPS_ID = "gps_id"
28
+ CONF_HDOP = "hdop"
28
29
  MULTI_CONF = True
29
30
  CONFIG_SCHEMA = cv.All(
30
31
  cv.Schema(
@@ -40,7 +41,7 @@ CONFIG_SCHEMA = cv.All(
40
41
  ),
41
42
  cv.Optional(CONF_SPEED): sensor.sensor_schema(
42
43
  unit_of_measurement=UNIT_KILOMETER_PER_HOUR,
43
- accuracy_decimals=6,
44
+ accuracy_decimals=3,
44
45
  ),
45
46
  cv.Optional(CONF_COURSE): sensor.sensor_schema(
46
47
  unit_of_measurement=UNIT_DEGREES,
@@ -48,12 +49,16 @@ CONFIG_SCHEMA = cv.All(
48
49
  ),
49
50
  cv.Optional(CONF_ALTITUDE): sensor.sensor_schema(
50
51
  unit_of_measurement=UNIT_METER,
51
- accuracy_decimals=1,
52
+ accuracy_decimals=2,
52
53
  ),
53
54
  cv.Optional(CONF_SATELLITES): sensor.sensor_schema(
54
55
  accuracy_decimals=0,
55
56
  state_class=STATE_CLASS_MEASUREMENT,
56
57
  ),
58
+ cv.Optional(CONF_HDOP): sensor.sensor_schema(
59
+ accuracy_decimals=3,
60
+ state_class=STATE_CLASS_MEASUREMENT,
61
+ ),
57
62
  }
58
63
  )
59
64
  .extend(cv.polling_component_schema("20s"))
@@ -92,5 +97,9 @@ async def to_code(config):
92
97
  sens = await sensor.new_sensor(config[CONF_SATELLITES])
93
98
  cg.add(var.set_satellites_sensor(sens))
94
99
 
100
+ if hdop_config := config.get(CONF_HDOP):
101
+ sens = await sensor.new_sensor(hdop_config)
102
+ cg.add(var.set_hdop_sensor(sens))
103
+
95
104
  # https://platformio.org/lib/show/1655/TinyGPSPlus
96
105
  cg.add_library("mikalhart/TinyGPSPlus", "1.0.2")
@@ -28,6 +28,9 @@ void GPS::update() {
28
28
 
29
29
  if (this->satellites_sensor_ != nullptr)
30
30
  this->satellites_sensor_->publish_state(this->satellites_);
31
+
32
+ if (this->hdop_sensor_ != nullptr)
33
+ this->hdop_sensor_->publish_state(this->hdop_);
31
34
  }
32
35
 
33
36
  void GPS::loop() {
@@ -44,23 +47,23 @@ void GPS::loop() {
44
47
 
45
48
  if (tiny_gps_.speed.isUpdated()) {
46
49
  this->speed_ = tiny_gps_.speed.kmph();
47
- ESP_LOGD(TAG, "Speed:");
48
- ESP_LOGD(TAG, " %f km/h", this->speed_);
50
+ ESP_LOGD(TAG, "Speed: %.3f km/h", this->speed_);
49
51
  }
50
52
  if (tiny_gps_.course.isUpdated()) {
51
53
  this->course_ = tiny_gps_.course.deg();
52
- ESP_LOGD(TAG, "Course:");
53
- ESP_LOGD(TAG, " %f °", this->course_);
54
+ ESP_LOGD(TAG, "Course: %.2f °", this->course_);
54
55
  }
55
56
  if (tiny_gps_.altitude.isUpdated()) {
56
57
  this->altitude_ = tiny_gps_.altitude.meters();
57
- ESP_LOGD(TAG, "Altitude:");
58
- ESP_LOGD(TAG, " %f m", this->altitude_);
58
+ ESP_LOGD(TAG, "Altitude: %.2f m", this->altitude_);
59
59
  }
60
60
  if (tiny_gps_.satellites.isUpdated()) {
61
61
  this->satellites_ = tiny_gps_.satellites.value();
62
- ESP_LOGD(TAG, "Satellites:");
63
- ESP_LOGD(TAG, " %d", this->satellites_);
62
+ ESP_LOGD(TAG, "Satellites: %d", this->satellites_);
63
+ }
64
+ if (tiny_gps_.hdop.isUpdated()) {
65
+ this->hdop_ = tiny_gps_.hdop.hdop();
66
+ ESP_LOGD(TAG, "HDOP: %.3f", this->hdop_);
64
67
  }
65
68
 
66
69
  for (auto *listener : this->listeners_)
@@ -33,6 +33,7 @@ class GPS : public PollingComponent, public uart::UARTDevice {
33
33
  void set_course_sensor(sensor::Sensor *course_sensor) { course_sensor_ = course_sensor; }
34
34
  void set_altitude_sensor(sensor::Sensor *altitude_sensor) { altitude_sensor_ = altitude_sensor; }
35
35
  void set_satellites_sensor(sensor::Sensor *satellites_sensor) { satellites_sensor_ = satellites_sensor; }
36
+ void set_hdop_sensor(sensor::Sensor *hdop_sensor) { hdop_sensor_ = hdop_sensor; }
36
37
 
37
38
  void register_listener(GPSListener *listener) {
38
39
  listener->parent_ = this;
@@ -46,12 +47,13 @@ class GPS : public PollingComponent, public uart::UARTDevice {
46
47
  TinyGPSPlus &get_tiny_gps() { return this->tiny_gps_; }
47
48
 
48
49
  protected:
49
- float latitude_ = -1;
50
- float longitude_ = -1;
51
- float speed_ = -1;
52
- float course_ = -1;
53
- float altitude_ = -1;
54
- int satellites_ = -1;
50
+ float latitude_ = NAN;
51
+ float longitude_ = NAN;
52
+ float speed_ = NAN;
53
+ float course_ = NAN;
54
+ float altitude_ = NAN;
55
+ int satellites_ = 0;
56
+ double hdop_ = NAN;
55
57
 
56
58
  sensor::Sensor *latitude_sensor_{nullptr};
57
59
  sensor::Sensor *longitude_sensor_{nullptr};
@@ -59,6 +61,7 @@ class GPS : public PollingComponent, public uart::UARTDevice {
59
61
  sensor::Sensor *course_sensor_{nullptr};
60
62
  sensor::Sensor *altitude_sensor_{nullptr};
61
63
  sensor::Sensor *satellites_sensor_{nullptr};
64
+ sensor::Sensor *hdop_sensor_{nullptr};
62
65
 
63
66
  bool has_time_{false};
64
67
  TinyGPSPlus tiny_gps_;
@@ -5,6 +5,7 @@ import esphome.config_validation as cv
5
5
  from esphome.const import (
6
6
  CONF_BORDER,
7
7
  CONF_COLOR,
8
+ CONF_CONTINUOUS,
8
9
  CONF_DIRECTION,
9
10
  CONF_DURATION,
10
11
  CONF_HEIGHT,
@@ -61,8 +62,6 @@ VALUE_POSITION_TYPE = {
61
62
  "BELOW": ValuePositionType.VALUE_POSITION_TYPE_BELOW,
62
63
  }
63
64
 
64
- CONF_CONTINUOUS = "continuous"
65
-
66
65
  GRAPH_TRACE_SCHEMA = cv.Schema(
67
66
  {
68
67
  cv.GenerateID(): cv.declare_id(GraphTrace),
@@ -1,7 +1,7 @@
1
1
  import esphome.codegen as cg
2
2
  from esphome.components import climate_ir
3
3
  import esphome.config_validation as cv
4
- from esphome.const import CONF_ID, CONF_MODEL
4
+ from esphome.const import CONF_MODEL
5
5
 
6
6
  CODEOWNERS = ["@orestismers"]
7
7
 
@@ -18,18 +18,16 @@ MODELS = {
18
18
  "yac": Model.GREE_YAC,
19
19
  "yac1fb9": Model.GREE_YAC1FB9,
20
20
  "yx1ff": Model.GREE_YX1FF,
21
+ "yag": Model.GREE_YAG,
21
22
  }
22
23
 
23
- CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend(
24
+ CONFIG_SCHEMA = climate_ir.climare_ir_with_receiver_schema(GreeClimate).extend(
24
25
  {
25
- cv.GenerateID(): cv.declare_id(GreeClimate),
26
26
  cv.Required(CONF_MODEL): cv.enum(MODELS),
27
27
  }
28
28
  )
29
29
 
30
30
 
31
31
  async def to_code(config):
32
- var = cg.new_Pvariable(config[CONF_ID])
32
+ var = await climate_ir.new_climate_ir(config)
33
33
  cg.add(var.set_model(config[CONF_MODEL]))
34
-
35
- await climate_ir.register_climate_ir(var, config)
@@ -22,13 +22,21 @@ void GreeClimate::transmit_state() {
22
22
  remote_state[0] = this->fan_speed_() | this->operation_mode_();
23
23
  remote_state[1] = this->temperature_();
24
24
 
25
- if (this->model_ == GREE_YAN || this->model_ == GREE_YX1FF) {
25
+ if (this->model_ == GREE_YAN || this->model_ == GREE_YX1FF || this->model_ == GREE_YAG) {
26
26
  remote_state[2] = 0x60;
27
27
  remote_state[3] = 0x50;
28
28
  remote_state[4] = this->vertical_swing_();
29
29
  }
30
30
 
31
- if (this->model_ == GREE_YAC) {
31
+ if (this->model_ == GREE_YAG) {
32
+ remote_state[5] = 0x40;
33
+
34
+ if (this->vertical_swing_() == GREE_VDIR_SWING || this->horizontal_swing_() == GREE_HDIR_SWING) {
35
+ remote_state[0] |= (1 << 6);
36
+ }
37
+ }
38
+
39
+ if (this->model_ == GREE_YAC || this->model_ == GREE_YAG) {
32
40
  remote_state[4] |= (this->horizontal_swing_() << 4);
33
41
  }
34
42
 
@@ -57,6 +65,12 @@ void GreeClimate::transmit_state() {
57
65
  // Calculate the checksum
58
66
  if (this->model_ == GREE_YAN || this->model_ == GREE_YX1FF) {
59
67
  remote_state[7] = ((remote_state[0] << 4) + (remote_state[1] << 4) + 0xC0);
68
+ } else if (this->model_ == GREE_YAG) {
69
+ remote_state[7] =
70
+ ((((remote_state[0] & 0x0F) + (remote_state[1] & 0x0F) + (remote_state[2] & 0x0F) + (remote_state[3] & 0x0F) +
71
+ ((remote_state[4] & 0xF0) >> 4) + ((remote_state[5] & 0xF0) >> 4) + ((remote_state[6] & 0xF0) >> 4) + 0x0A) &
72
+ 0x0F)
73
+ << 4);
60
74
  } else {
61
75
  remote_state[7] =
62
76
  ((((remote_state[0] & 0x0F) + (remote_state[1] & 0x0F) + (remote_state[2] & 0x0F) + (remote_state[3] & 0x0F) +
@@ -58,7 +58,7 @@ const uint8_t GREE_VDIR_MIDDLE = 0x04;
58
58
  const uint8_t GREE_VDIR_MDOWN = 0x05;
59
59
  const uint8_t GREE_VDIR_DOWN = 0x06;
60
60
 
61
- // Only available on YAC
61
+ // Only available on YAC/YAG
62
62
  // Horizontal air directions. Note that these cannot be set on all heat pumps
63
63
  const uint8_t GREE_HDIR_AUTO = 0x00;
64
64
  const uint8_t GREE_HDIR_MANUAL = 0x00;
@@ -78,7 +78,7 @@ const uint8_t GREE_PRESET_SLEEP = 0x01;
78
78
  const uint8_t GREE_PRESET_SLEEP_BIT = 0x80;
79
79
 
80
80
  // Model codes
81
- enum Model { GREE_GENERIC, GREE_YAN, GREE_YAA, GREE_YAC, GREE_YAC1FB9, GREE_YX1FF };
81
+ enum Model { GREE_GENERIC, GREE_YAN, GREE_YAA, GREE_YAC, GREE_YAC1FB9, GREE_YX1FF, GREE_YAG };
82
82
 
83
83
  class GreeClimate : public climate_ir::ClimateIR {
84
84
  public:
@@ -30,6 +30,7 @@ from esphome.const import (
30
30
  CONF_VISUAL,
31
31
  CONF_WIFI,
32
32
  )
33
+ from esphome.cpp_generator import MockObjClass
33
34
  import esphome.final_validate as fv
34
35
 
35
36
  _LOGGER = logging.getLogger(__name__)
@@ -185,42 +186,46 @@ def validate_visual(config):
185
186
  return config
186
187
 
187
188
 
188
- BASE_CONFIG_SCHEMA = (
189
- climate.CLIMATE_SCHEMA.extend(
190
- {
191
- cv.Optional(CONF_SUPPORTED_MODES): cv.ensure_list(
192
- cv.enum(SUPPORTED_CLIMATE_MODES_OPTIONS, upper=True)
193
- ),
194
- cv.Optional(
195
- CONF_SUPPORTED_SWING_MODES,
196
- default=[
197
- "VERTICAL",
198
- "HORIZONTAL",
199
- "BOTH",
200
- ],
201
- ): cv.ensure_list(cv.enum(SUPPORTED_SWING_MODES_OPTIONS, upper=True)),
202
- cv.Optional(CONF_WIFI_SIGNAL, default=False): cv.boolean,
203
- cv.Optional(CONF_DISPLAY): cv.boolean,
204
- cv.Optional(
205
- CONF_ANSWER_TIMEOUT,
206
- ): cv.positive_time_period_milliseconds,
207
- cv.Optional(CONF_ON_STATUS_MESSAGE): automation.validate_automation(
208
- {
209
- cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StatusMessageTrigger),
210
- }
211
- ),
212
- }
189
+ def _base_config_schema(class_: MockObjClass) -> cv.Schema:
190
+ return (
191
+ climate.climate_schema(class_)
192
+ .extend(
193
+ {
194
+ cv.Optional(CONF_SUPPORTED_MODES): cv.ensure_list(
195
+ cv.enum(SUPPORTED_CLIMATE_MODES_OPTIONS, upper=True)
196
+ ),
197
+ cv.Optional(
198
+ CONF_SUPPORTED_SWING_MODES,
199
+ default=[
200
+ "VERTICAL",
201
+ "HORIZONTAL",
202
+ "BOTH",
203
+ ],
204
+ ): cv.ensure_list(cv.enum(SUPPORTED_SWING_MODES_OPTIONS, upper=True)),
205
+ cv.Optional(CONF_WIFI_SIGNAL, default=False): cv.boolean,
206
+ cv.Optional(CONF_DISPLAY): cv.boolean,
207
+ cv.Optional(
208
+ CONF_ANSWER_TIMEOUT,
209
+ ): cv.positive_time_period_milliseconds,
210
+ cv.Optional(CONF_ON_STATUS_MESSAGE): automation.validate_automation(
211
+ {
212
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
213
+ StatusMessageTrigger
214
+ ),
215
+ }
216
+ ),
217
+ }
218
+ )
219
+ .extend(uart.UART_DEVICE_SCHEMA)
220
+ .extend(cv.COMPONENT_SCHEMA)
213
221
  )
214
- .extend(uart.UART_DEVICE_SCHEMA)
215
- .extend(cv.COMPONENT_SCHEMA)
216
- )
222
+
217
223
 
218
224
  CONFIG_SCHEMA = cv.All(
219
225
  cv.typed_schema(
220
226
  {
221
- PROTOCOL_SMARTAIR2: BASE_CONFIG_SCHEMA.extend(
227
+ PROTOCOL_SMARTAIR2: _base_config_schema(Smartair2Climate).extend(
222
228
  {
223
- cv.GenerateID(): cv.declare_id(Smartair2Climate),
224
229
  cv.Optional(
225
230
  CONF_ALTERNATIVE_SWING_CONTROL, default=False
226
231
  ): cv.boolean,
@@ -232,9 +237,8 @@ CONFIG_SCHEMA = cv.All(
232
237
  ),
233
238
  }
234
239
  ),
235
- PROTOCOL_HON: BASE_CONFIG_SCHEMA.extend(
240
+ PROTOCOL_HON: _base_config_schema(HonClimate).extend(
236
241
  {
237
- cv.GenerateID(): cv.declare_id(HonClimate),
238
242
  cv.Optional(
239
243
  CONF_CONTROL_METHOD, default="SET_GROUP_PARAMETERS"
240
244
  ): cv.ensure_list(
@@ -464,10 +468,9 @@ FINAL_VALIDATE_SCHEMA = _final_validate
464
468
 
465
469
  async def to_code(config):
466
470
  cg.add(haier_ns.init_haier_protocol_logging())
467
- var = cg.new_Pvariable(config[CONF_ID])
471
+ var = await climate.new_climate(config)
468
472
  await cg.register_component(var, config)
469
473
  await uart.register_uart_device(var, config)
470
- await climate.register_climate(var, config)
471
474
 
472
475
  cg.add(var.set_send_wifi(config[CONF_WIFI_SIGNAL]))
473
476
  if CONF_CONTROL_METHOD in config:
@@ -30,25 +30,28 @@ DECAY_MODE_OPTIONS = {
30
30
  # Actions
31
31
  BrakeAction = hbridge_ns.class_("BrakeAction", automation.Action)
32
32
 
33
- CONFIG_SCHEMA = fan.FAN_SCHEMA.extend(
34
- {
35
- cv.GenerateID(CONF_ID): cv.declare_id(HBridgeFan),
36
- cv.Required(CONF_PIN_A): cv.use_id(output.FloatOutput),
37
- cv.Required(CONF_PIN_B): cv.use_id(output.FloatOutput),
38
- cv.Optional(CONF_DECAY_MODE, default="SLOW"): cv.enum(
39
- DECAY_MODE_OPTIONS, upper=True
40
- ),
41
- cv.Optional(CONF_SPEED_COUNT, default=100): cv.int_range(min=1),
42
- cv.Optional(CONF_ENABLE_PIN): cv.use_id(output.FloatOutput),
43
- cv.Optional(CONF_PRESET_MODES): validate_preset_modes,
44
- }
45
- ).extend(cv.COMPONENT_SCHEMA)
33
+ CONFIG_SCHEMA = (
34
+ fan.fan_schema(HBridgeFan)
35
+ .extend(
36
+ {
37
+ cv.Required(CONF_PIN_A): cv.use_id(output.FloatOutput),
38
+ cv.Required(CONF_PIN_B): cv.use_id(output.FloatOutput),
39
+ cv.Optional(CONF_DECAY_MODE, default="SLOW"): cv.enum(
40
+ DECAY_MODE_OPTIONS, upper=True
41
+ ),
42
+ cv.Optional(CONF_SPEED_COUNT, default=100): cv.int_range(min=1),
43
+ cv.Optional(CONF_ENABLE_PIN): cv.use_id(output.FloatOutput),
44
+ cv.Optional(CONF_PRESET_MODES): validate_preset_modes,
45
+ }
46
+ )
47
+ .extend(cv.COMPONENT_SCHEMA)
48
+ )
46
49
 
47
50
 
48
51
  @automation.register_action(
49
52
  "fan.hbridge.brake",
50
53
  BrakeAction,
51
- maybe_simple_id({cv.Required(CONF_ID): cv.use_id(HBridgeFan)}),
54
+ maybe_simple_id({cv.GenerateID(): cv.use_id(HBridgeFan)}),
52
55
  )
53
56
  async def fan_hbridge_brake_to_code(config, action_id, template_arg, args):
54
57
  paren = await cg.get_variable(config[CONF_ID])
@@ -56,13 +59,12 @@ async def fan_hbridge_brake_to_code(config, action_id, template_arg, args):
56
59
 
57
60
 
58
61
  async def to_code(config):
59
- var = cg.new_Pvariable(
60
- config[CONF_ID],
62
+ var = await fan.new_fan(
63
+ config,
61
64
  config[CONF_SPEED_COUNT],
62
65
  config[CONF_DECAY_MODE],
63
66
  )
64
67
  await cg.register_component(var, config)
65
- await fan.register_fan(var, config)
66
68
  pin_a_ = await cg.get_variable(config[CONF_PIN_A])
67
69
  cg.add(var.set_pin_a(pin_a_))
68
70
  pin_b_ = await cg.get_variable(config[CONF_PIN_B])