esphome 2025.4.2__py3-none-any.whl → 2025.5.0b3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. esphome/__main__.py +16 -14
  2. esphome/components/ac_dimmer/ac_dimmer.cpp +3 -2
  3. esphome/components/adc/__init__.py +51 -34
  4. esphome/components/airthings_wave_base/__init__.py +1 -1
  5. esphome/components/alarm_control_panel/__init__.py +37 -2
  6. esphome/components/am43/cover/__init__.py +4 -5
  7. esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +6 -4
  8. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +4 -5
  9. esphome/components/analog_threshold/binary_sensor.py +10 -8
  10. esphome/components/anova/climate.py +4 -5
  11. esphome/components/api/__init__.py +25 -8
  12. esphome/components/api/api_connection.cpp +81 -13
  13. esphome/components/api/api_connection.h +13 -1
  14. esphome/components/api/api_frame_helper.cpp +232 -177
  15. esphome/components/api/api_frame_helper.h +61 -8
  16. esphome/components/api/api_noise_context.h +13 -4
  17. esphome/components/api/api_pb2.cpp +1422 -1
  18. esphome/components/api/api_pb2.h +255 -1
  19. esphome/components/api/api_pb2_service.cpp +162 -49
  20. esphome/components/api/api_pb2_service.h +90 -51
  21. esphome/components/api/api_pb2_size.h +361 -0
  22. esphome/components/api/api_server.cpp +110 -34
  23. esphome/components/api/api_server.h +8 -0
  24. esphome/components/api/proto.h +86 -17
  25. esphome/components/as7341/as7341.h +1 -1
  26. esphome/components/atm90e32/__init__.py +1 -0
  27. esphome/components/atm90e32/atm90e32.cpp +576 -199
  28. esphome/components/atm90e32/atm90e32.h +128 -31
  29. esphome/components/atm90e32/atm90e32_reg.h +4 -2
  30. esphome/components/atm90e32/button/__init__.py +62 -10
  31. esphome/components/atm90e32/button/atm90e32_button.cpp +63 -4
  32. esphome/components/atm90e32/button/atm90e32_button.h +36 -4
  33. esphome/components/atm90e32/number/__init__.py +130 -0
  34. esphome/components/atm90e32/number/atm90e32_number.h +16 -0
  35. esphome/components/atm90e32/sensor.py +21 -4
  36. esphome/components/atm90e32/text_sensor/__init__.py +48 -0
  37. esphome/components/audio/__init__.py +96 -49
  38. esphome/components/audio/audio.h +48 -0
  39. esphome/components/audio/audio_decoder.cpp +1 -1
  40. esphome/components/audio/audio_resampler.cpp +2 -0
  41. esphome/components/audio/audio_resampler.h +1 -0
  42. esphome/components/ballu/climate.py +2 -9
  43. esphome/components/bang_bang/climate.py +5 -6
  44. esphome/components/bedjet/bedjet_hub.cpp +1 -0
  45. esphome/components/bedjet/climate/__init__.py +3 -8
  46. esphome/components/bedjet/fan/__init__.py +2 -11
  47. esphome/components/binary/fan/__init__.py +13 -16
  48. esphome/components/binary_sensor/__init__.py +13 -10
  49. esphome/components/bl0906/constants.h +16 -16
  50. esphome/components/ble_client/text_sensor/__init__.py +3 -5
  51. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
  52. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +136 -21
  53. esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
  54. esphome/components/button/__init__.py +11 -8
  55. esphome/components/canbus/canbus.cpp +3 -0
  56. esphome/components/canbus/canbus.h +16 -0
  57. esphome/components/ccs811/sensor.py +9 -6
  58. esphome/components/climate/__init__.py +35 -2
  59. esphome/components/climate/climate_mode.h +1 -1
  60. esphome/components/climate/climate_traits.h +63 -57
  61. esphome/components/climate_ir/__init__.py +57 -17
  62. esphome/components/climate_ir_lg/climate.py +2 -5
  63. esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
  64. esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
  65. esphome/components/color/__init__.py +2 -0
  66. esphome/components/const/__init__.py +5 -0
  67. esphome/components/coolix/climate.py +2 -9
  68. esphome/components/copy/cover/__init__.py +10 -9
  69. esphome/components/copy/fan/__init__.py +11 -9
  70. esphome/components/copy/lock/__init__.py +11 -9
  71. esphome/components/copy/text/__init__.py +9 -6
  72. esphome/components/cover/__init__.py +37 -2
  73. esphome/components/cse7766/cse7766.cpp +2 -1
  74. esphome/components/cst226/binary_sensor/__init__.py +28 -0
  75. esphome/components/cst226/binary_sensor/cs226_button.h +22 -0
  76. esphome/components/cst226/binary_sensor/cstt6_button.cpp +19 -0
  77. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +27 -5
  78. esphome/components/cst226/touchscreen/cst226_touchscreen.h +10 -10
  79. esphome/components/current_based/cover.py +37 -36
  80. esphome/components/current_based/current_based_cover.cpp +2 -1
  81. esphome/components/daikin/climate.py +2 -9
  82. esphome/components/daikin/daikin.cpp +15 -9
  83. esphome/components/daikin/daikin.h +5 -5
  84. esphome/components/daikin_arc/climate.py +2 -7
  85. esphome/components/daikin_brc/climate.py +3 -5
  86. esphome/components/dallas_temp/dallas_temp.cpp +17 -24
  87. esphome/components/dallas_temp/dallas_temp.h +0 -1
  88. esphome/components/daly_bms/daly_bms.cpp +2 -1
  89. esphome/components/debug/debug_component.cpp +6 -1
  90. esphome/components/debug/debug_component.h +6 -0
  91. esphome/components/debug/debug_esp32.cpp +109 -254
  92. esphome/components/debug/sensor.py +14 -0
  93. esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
  94. esphome/components/delonghi/climate.py +2 -9
  95. esphome/components/demo/__init__.py +18 -20
  96. esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
  97. esphome/components/dps310/sensor.py +6 -6
  98. esphome/components/ee895/sensor.py +9 -9
  99. esphome/components/emmeti/climate.py +2 -9
  100. esphome/components/endstop/cover.py +17 -16
  101. esphome/components/endstop/endstop_cover.cpp +2 -1
  102. esphome/components/ens160_base/__init__.py +12 -9
  103. esphome/components/esp32/__init__.py +60 -3
  104. esphome/components/esp32/core.cpp +11 -5
  105. esphome/components/esp32/gpio.cpp +86 -24
  106. esphome/components/esp32/gpio.py +15 -16
  107. esphome/components/esp32/gpio_esp32.py +1 -2
  108. esphome/components/esp32/gpio_esp32_c2.py +1 -1
  109. esphome/components/esp32/gpio_esp32_c3.py +1 -1
  110. esphome/components/esp32/gpio_esp32_c6.py +1 -1
  111. esphome/components/esp32/gpio_esp32_h2.py +1 -1
  112. esphome/components/esp32_ble/ble.cpp +1 -0
  113. esphome/components/esp32_ble/ble.h +5 -3
  114. esphome/components/esp32_ble/ble_advertising.cpp +2 -1
  115. esphome/components/esp32_ble/ble_advertising.h +1 -0
  116. esphome/components/esp32_ble_server/__init__.py +3 -0
  117. esphome/components/esp32_ble_tracker/__init__.py +7 -1
  118. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
  119. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
  120. esphome/components/esp32_camera/esp32_camera.cpp +2 -1
  121. esphome/components/esp32_camera/esp32_camera.h +1 -1
  122. esphome/components/esp32_can/esp32_can.cpp +1 -1
  123. esphome/components/esp32_improv/esp32_improv_component.cpp +1 -1
  124. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  125. esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
  126. esphome/components/esp32_rmt_led_strip/light.py +9 -1
  127. esphome/components/esp32_touch/esp32_touch.cpp +1 -1
  128. esphome/components/esp8266/gpio.cpp +69 -8
  129. esphome/components/ethernet/ethernet_component.cpp +1 -1
  130. esphome/components/event/__init__.py +13 -10
  131. esphome/components/factory_reset/switch/__init__.py +7 -21
  132. esphome/components/fan/__init__.py +52 -5
  133. esphome/components/fastled_base/__init__.py +1 -4
  134. esphome/components/fastled_base/fastled_light.cpp +1 -1
  135. esphome/components/feedback/cover.py +38 -33
  136. esphome/components/feedback/feedback_cover.cpp +2 -1
  137. esphome/components/fujitsu_general/climate.py +2 -9
  138. esphome/components/gcja5/gcja5.cpp +2 -1
  139. esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
  140. esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
  141. esphome/components/gpio_expander/cached_gpio.h +22 -7
  142. esphome/components/gps/__init__.py +47 -17
  143. esphome/components/gps/gps.cpp +42 -23
  144. esphome/components/gps/gps.h +17 -13
  145. esphome/components/graph/__init__.py +1 -2
  146. esphome/components/gree/climate.py +4 -6
  147. esphome/components/gree/gree.cpp +16 -2
  148. esphome/components/gree/gree.h +2 -2
  149. esphome/components/growatt_solar/growatt_solar.cpp +2 -1
  150. esphome/components/haier/climate.py +37 -34
  151. esphome/components/hbridge/fan/__init__.py +19 -17
  152. esphome/components/he60r/cover.py +4 -5
  153. esphome/components/heatpumpir/climate.py +3 -6
  154. esphome/components/hitachi_ac344/climate.py +2 -9
  155. esphome/components/hitachi_ac424/climate.py +2 -9
  156. esphome/components/hm3301/hm3301.h +1 -1
  157. esphome/components/hte501/sensor.py +6 -6
  158. esphome/components/http_request/__init__.py +39 -6
  159. esphome/components/http_request/http_request.cpp +20 -0
  160. esphome/components/http_request/http_request.h +57 -15
  161. esphome/components/http_request/http_request_arduino.cpp +22 -6
  162. esphome/components/http_request/http_request_arduino.h +4 -3
  163. esphome/components/http_request/http_request_host.cpp +141 -0
  164. esphome/components/http_request/http_request_host.h +37 -0
  165. esphome/components/http_request/http_request_idf.cpp +35 -3
  166. esphome/components/http_request/http_request_idf.h +10 -3
  167. esphome/components/http_request/httplib.h +9691 -0
  168. esphome/components/http_request/update/__init__.py +11 -8
  169. esphome/components/hyt271/sensor.py +6 -6
  170. esphome/components/i2c/i2c.h +4 -0
  171. esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
  172. esphome/components/i2s_audio/__init__.py +131 -22
  173. esphome/components/i2s_audio/i2s_audio.h +44 -4
  174. esphome/components/i2s_audio/media_player/__init__.py +19 -9
  175. esphome/components/i2s_audio/microphone/__init__.py +63 -5
  176. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
  177. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
  178. esphome/components/i2s_audio/speaker/__init__.py +31 -5
  179. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
  180. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
  181. esphome/components/ili9xxx/ili9xxx_init.h +1 -1
  182. esphome/components/image/__init__.py +37 -17
  183. esphome/components/image/image.cpp +25 -8
  184. esphome/components/internal_temperature/internal_temperature.cpp +6 -4
  185. esphome/components/key_collector/__init__.py +35 -0
  186. esphome/components/key_collector/key_collector.cpp +8 -0
  187. esphome/components/key_collector/key_collector.h +10 -0
  188. esphome/components/kuntze/kuntze.cpp +2 -1
  189. esphome/components/ld2410/ld2410.h +1 -1
  190. esphome/components/ld2450/ld2450.h +1 -1
  191. esphome/components/light/__init__.py +57 -0
  192. esphome/components/lock/__init__.py +51 -4
  193. esphome/components/lock/automation.h +2 -13
  194. esphome/components/logger/__init__.py +22 -0
  195. esphome/components/logger/logger.cpp +154 -103
  196. esphome/components/logger/logger.h +211 -36
  197. esphome/components/logger/task_log_buffer.cpp +138 -0
  198. esphome/components/logger/task_log_buffer.h +69 -0
  199. esphome/components/lvgl/__init__.py +13 -5
  200. esphome/components/lvgl/automation.py +50 -1
  201. esphome/components/lvgl/defines.py +0 -1
  202. esphome/components/lvgl/lvgl_esphome.cpp +5 -1
  203. esphome/components/lvgl/text/__init__.py +1 -2
  204. esphome/components/mapping/__init__.py +134 -0
  205. esphome/components/matrix_keypad/matrix_keypad.cpp +2 -1
  206. esphome/components/max7219digit/max7219digit.cpp +28 -27
  207. esphome/components/mdns/__init__.py +11 -5
  208. esphome/components/mdns/mdns_component.cpp +11 -5
  209. esphome/components/mdns/mdns_component.h +3 -2
  210. esphome/components/mdns/mdns_esp32.cpp +4 -3
  211. esphome/components/mdns/mdns_esp8266.cpp +4 -2
  212. esphome/components/mdns/mdns_libretiny.cpp +4 -2
  213. esphome/components/mdns/mdns_rp2040.cpp +4 -2
  214. esphome/components/media_player/__init__.py +33 -1
  215. esphome/components/mhz19/sensor.py +11 -7
  216. esphome/components/micro_wake_word/__init__.py +99 -31
  217. esphome/components/micro_wake_word/automation.h +54 -0
  218. esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
  219. esphome/components/micro_wake_word/micro_wake_word.h +58 -105
  220. esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
  221. esphome/components/micro_wake_word/streaming_model.cpp +158 -41
  222. esphome/components/micro_wake_word/streaming_model.h +85 -13
  223. esphome/components/microphone/__init__.py +139 -9
  224. esphome/components/microphone/automation.h +14 -2
  225. esphome/components/microphone/microphone.cpp +21 -0
  226. esphome/components/microphone/microphone.h +14 -5
  227. esphome/components/microphone/microphone_source.cpp +95 -0
  228. esphome/components/microphone/microphone_source.h +80 -0
  229. esphome/components/mics_4514/sensor.py +25 -14
  230. esphome/components/midea/climate.py +3 -4
  231. esphome/components/midea_ir/climate.py +3 -5
  232. esphome/components/mipi_spi/__init__.py +15 -0
  233. esphome/components/mipi_spi/display.py +474 -0
  234. esphome/components/mipi_spi/mipi_spi.cpp +481 -0
  235. esphome/components/mipi_spi/mipi_spi.h +171 -0
  236. esphome/components/mipi_spi/models/__init__.py +65 -0
  237. esphome/components/mipi_spi/models/amoled.py +72 -0
  238. esphome/components/mipi_spi/models/commands.py +82 -0
  239. esphome/components/mipi_spi/models/cyd.py +10 -0
  240. esphome/components/mipi_spi/models/ili.py +749 -0
  241. esphome/components/mipi_spi/models/jc.py +260 -0
  242. esphome/components/mipi_spi/models/lanbon.py +15 -0
  243. esphome/components/mipi_spi/models/lilygo.py +60 -0
  244. esphome/components/mipi_spi/models/waveshare.py +139 -0
  245. esphome/components/mitsubishi/climate.py +2 -5
  246. esphome/components/mitsubishi/mitsubishi.cpp +9 -9
  247. esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
  248. esphome/components/mixer/speaker/mixer_speaker.h +1 -3
  249. esphome/components/mlx90393/sensor.py +5 -0
  250. esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
  251. esphome/components/mlx90393/sensor_mlx90393.h +21 -4
  252. esphome/components/modbus/modbus.cpp +2 -1
  253. esphome/components/mqtt/__init__.py +1 -1
  254. esphome/components/mqtt/mqtt_client.cpp +6 -2
  255. esphome/components/mqtt/mqtt_const.h +4 -0
  256. esphome/components/mqtt/mqtt_fan.cpp +39 -0
  257. esphome/components/mqtt/mqtt_fan.h +2 -0
  258. esphome/components/ms5611/sensor.py +6 -6
  259. esphome/components/ms8607/sensor.py +3 -3
  260. esphome/components/network/__init__.py +1 -1
  261. esphome/components/nextion/base_component.py +17 -16
  262. esphome/components/nextion/display.py +11 -2
  263. esphome/components/nextion/nextion.cpp +39 -1
  264. esphome/components/nextion/nextion.h +50 -0
  265. esphome/components/noblex/climate.py +2 -9
  266. esphome/components/number/__init__.py +12 -9
  267. esphome/components/one_wire/one_wire_bus.cpp +14 -10
  268. esphome/components/one_wire/one_wire_bus.h +14 -8
  269. esphome/components/online_image/bmp_image.cpp +48 -11
  270. esphome/components/online_image/bmp_image.h +2 -0
  271. esphome/components/opentherm/binary_sensor/__init__.py +2 -4
  272. esphome/components/opentherm/number/__init__.py +11 -20
  273. esphome/components/opentherm/sensor/__init__.py +3 -3
  274. esphome/components/opentherm/switch/__init__.py +3 -5
  275. esphome/components/output/lock/__init__.py +11 -9
  276. esphome/components/packages/__init__.py +33 -31
  277. esphome/components/packet_transport/__init__.py +201 -0
  278. esphome/components/packet_transport/binary_sensor.py +19 -0
  279. esphome/components/packet_transport/packet_transport.cpp +534 -0
  280. esphome/components/packet_transport/packet_transport.h +154 -0
  281. esphome/components/packet_transport/sensor.py +19 -0
  282. esphome/components/pca9685/pca9685_output.cpp +2 -1
  283. esphome/components/pid/climate.py +2 -4
  284. esphome/components/pm2005/__init__.py +1 -0
  285. esphome/components/pm2005/pm2005.cpp +123 -0
  286. esphome/components/pm2005/pm2005.h +46 -0
  287. esphome/components/pm2005/sensor.py +86 -0
  288. esphome/components/pmsa003i/pmsa003i.cpp +43 -16
  289. esphome/components/pmsa003i/pmsa003i.h +25 -25
  290. esphome/components/pmsx003/pmsx003.cpp +195 -230
  291. esphome/components/pmsx003/pmsx003.h +51 -33
  292. esphome/components/pmsx003/sensor.py +21 -11
  293. esphome/components/pn7150/pn7150.h +2 -2
  294. esphome/components/pn7160/pn7160.h +2 -2
  295. esphome/components/prometheus/prometheus_handler.cpp +174 -0
  296. esphome/components/prometheus/prometheus_handler.h +17 -0
  297. esphome/components/psram/__init__.py +7 -5
  298. esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
  299. esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
  300. esphome/components/pzem004t/pzem004t.cpp +2 -1
  301. esphome/components/qspi_dbi/__init__.py +0 -1
  302. esphome/components/qspi_dbi/display.py +2 -1
  303. esphome/components/qspi_dbi/models.py +1 -2
  304. esphome/components/remote_base/__init__.py +91 -0
  305. esphome/components/remote_base/beo4_protocol.cpp +153 -0
  306. esphome/components/remote_base/beo4_protocol.h +43 -0
  307. esphome/components/remote_base/gobox_protocol.cpp +131 -0
  308. esphome/components/remote_base/gobox_protocol.h +54 -0
  309. esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
  310. esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
  311. esphome/components/resampler/speaker/resampler_speaker.h +1 -1
  312. esphome/components/rf_bridge/rf_bridge.cpp +2 -1
  313. esphome/components/scd30/sensor.py +2 -3
  314. esphome/components/scd4x/sensor.py +4 -5
  315. esphome/components/sdp3x/sensor.py +2 -1
  316. esphome/components/sds011/sds011.cpp +2 -1
  317. esphome/components/select/__init__.py +19 -20
  318. esphome/components/sen5x/sen5x.cpp +55 -36
  319. esphome/components/sen5x/sensor.py +1 -1
  320. esphome/components/senseair/sensor.py +3 -3
  321. esphome/components/sensor/__init__.py +158 -14
  322. esphome/components/sensor/filter.cpp +23 -0
  323. esphome/components/sensor/filter.h +22 -0
  324. esphome/components/sgp30/sensor.py +14 -16
  325. esphome/components/sgp4x/sensor.py +1 -1
  326. esphome/components/sht4x/sht4x.cpp +43 -22
  327. esphome/components/sht4x/sht4x.h +1 -1
  328. esphome/components/shtcx/sensor.py +6 -6
  329. esphome/components/slow_pwm/slow_pwm_output.cpp +2 -1
  330. esphome/components/sml/text_sensor/__init__.py +4 -6
  331. esphome/components/sound_level/__init__.py +0 -0
  332. esphome/components/sound_level/sensor.py +97 -0
  333. esphome/components/sound_level/sound_level.cpp +194 -0
  334. esphome/components/sound_level/sound_level.h +73 -0
  335. esphome/components/speaker/media_player/__init__.py +4 -8
  336. esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
  337. esphome/components/speaker/media_player/speaker_media_player.h +0 -11
  338. esphome/components/speaker/speaker.h +4 -7
  339. esphome/components/speed/fan/__init__.py +17 -16
  340. esphome/components/spi/spi.h +11 -1
  341. esphome/components/sprinkler/__init__.py +18 -19
  342. esphome/components/sprinkler/sprinkler.cpp +6 -5
  343. esphome/components/switch/__init__.py +32 -42
  344. esphome/components/syslog/__init__.py +41 -0
  345. esphome/components/syslog/esphome_syslog.cpp +49 -0
  346. esphome/components/syslog/esphome_syslog.h +27 -0
  347. esphome/components/t6615/sensor.py +3 -3
  348. esphome/components/t6615/t6615.cpp +2 -1
  349. esphome/components/tca9555/tca9555.cpp +11 -6
  350. esphome/components/tcl112/climate.py +2 -9
  351. esphome/components/template/alarm_control_panel/__init__.py +7 -6
  352. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
  353. esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
  354. esphome/components/template/cover/__init__.py +27 -21
  355. esphome/components/template/fan/__init__.py +14 -12
  356. esphome/components/template/lock/__init__.py +20 -25
  357. esphome/components/template/lock/automation.h +18 -0
  358. esphome/components/template/text/__init__.py +4 -3
  359. esphome/components/template/valve/__init__.py +32 -21
  360. esphome/components/template/valve/automation.h +24 -0
  361. esphome/components/text/__init__.py +32 -1
  362. esphome/components/text_sensor/__init__.py +24 -29
  363. esphome/components/thermostat/climate.py +5 -5
  364. esphome/components/time_based/cover.py +17 -16
  365. esphome/components/time_based/time_based_cover.cpp +2 -1
  366. esphome/components/tm1638/switch/__init__.py +10 -7
  367. esphome/components/tormatic/cover.py +4 -5
  368. esphome/components/toshiba/climate.py +3 -5
  369. esphome/components/touchscreen/touchscreen.cpp +3 -1
  370. esphome/components/tuya/climate/__init__.py +5 -6
  371. esphome/components/tuya/cover/__init__.py +6 -11
  372. esphome/components/tuya/select/__init__.py +15 -5
  373. esphome/components/tuya/select/tuya_select.cpp +6 -1
  374. esphome/components/tuya/select/tuya_select.h +5 -1
  375. esphome/components/uart/packet_transport/__init__.py +20 -0
  376. esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
  377. esphome/components/uart/packet_transport/uart_transport.h +41 -0
  378. esphome/components/uart/switch/uart_switch.cpp +2 -1
  379. esphome/components/udp/__init__.py +126 -128
  380. esphome/components/udp/automation.h +40 -0
  381. esphome/components/udp/binary_sensor.py +3 -25
  382. esphome/components/udp/packet_transport/__init__.py +29 -0
  383. esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
  384. esphome/components/udp/packet_transport/udp_transport.h +28 -0
  385. esphome/components/udp/sensor.py +3 -25
  386. esphome/components/udp/udp_component.cpp +26 -470
  387. esphome/components/udp/udp_component.h +21 -128
  388. esphome/components/update/__init__.py +31 -1
  389. esphome/components/uponor_smatrix/climate/__init__.py +4 -9
  390. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +2 -1
  391. esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
  392. esphome/components/uptime/text_sensor/__init__.py +47 -7
  393. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
  394. esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
  395. esphome/components/valve/__init__.py +34 -3
  396. esphome/components/valve/automation.h +1 -19
  397. esphome/components/vl53l0x/sensor.py +11 -0
  398. esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
  399. esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
  400. esphome/components/voice_assistant/__init__.py +36 -10
  401. esphome/components/voice_assistant/voice_assistant.cpp +170 -144
  402. esphome/components/voice_assistant/voice_assistant.h +26 -25
  403. esphome/components/waveshare_epaper/display.py +6 -0
  404. esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
  405. esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
  406. esphome/components/whirlpool/climate.py +3 -5
  407. esphome/components/whynter/climate.py +3 -5
  408. esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
  409. esphome/components/yashima/climate.py +6 -6
  410. esphome/components/zhlt01/climate.py +2 -7
  411. esphome/config.py +13 -13
  412. esphome/config_validation.py +38 -58
  413. esphome/const.py +15 -1
  414. esphome/core/__init__.py +2 -0
  415. esphome/core/application.cpp +23 -10
  416. esphome/core/application.h +9 -1
  417. esphome/core/automation.h +4 -3
  418. esphome/core/component.cpp +28 -7
  419. esphome/core/component.h +10 -1
  420. esphome/core/defines.h +23 -17
  421. esphome/core/macros.h +4 -0
  422. esphome/core/scheduler.cpp +7 -1
  423. esphome/cpp_generator.py +6 -2
  424. esphome/dashboard/web_server.py +3 -3
  425. esphome/helpers.py +39 -0
  426. esphome/loader.py +4 -0
  427. esphome/log.py +15 -19
  428. esphome/mqtt.py +23 -10
  429. esphome/platformio_api.py +1 -1
  430. esphome/schema_extractors.py +0 -1
  431. esphome/voluptuous_schema.py +3 -1
  432. esphome/vscode.py +15 -0
  433. esphome/wizard.py +47 -37
  434. esphome/zeroconf.py +7 -3
  435. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/METADATA +10 -11
  436. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/RECORD +440 -380
  437. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/WHEEL +1 -1
  438. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/entry_points.txt +0 -0
  439. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/licenses/LICENSE +0 -0
  440. {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,5 @@
1
1
  import esphome.codegen as cg
2
2
  from esphome.components import climate_ir
3
- import esphome.config_validation as cv
4
- from esphome.const import CONF_ID
5
3
 
6
4
  AUTO_LOAD = ["climate_ir"]
7
5
 
@@ -10,13 +8,8 @@ FujitsuGeneralClimate = fujitsu_general_ns.class_(
10
8
  "FujitsuGeneralClimate", climate_ir.ClimateIR
11
9
  )
12
10
 
13
- CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend(
14
- {
15
- cv.GenerateID(): cv.declare_id(FujitsuGeneralClimate),
16
- }
17
- )
11
+ CONFIG_SCHEMA = climate_ir.climate_ir_with_receiver_schema(FujitsuGeneralClimate)
18
12
 
19
13
 
20
14
  async def to_code(config):
21
- var = cg.new_Pvariable(config[CONF_ID])
22
- await climate_ir.register_climate_ir(var, config)
15
+ await climate_ir.new_climate_ir(config)
@@ -6,6 +6,7 @@
6
6
  */
7
7
  #include "gcja5.h"
8
8
  #include "esphome/core/log.h"
9
+ #include "esphome/core/application.h"
9
10
  #include <cstring>
10
11
 
11
12
  namespace esphome {
@@ -16,7 +17,7 @@ static const char *const TAG = "gcja5";
16
17
  void GCJA5Component::setup() { ESP_LOGCONFIG(TAG, "Setting up gcja5..."); }
17
18
 
18
19
  void GCJA5Component::loop() {
19
- const uint32_t now = millis();
20
+ const uint32_t now = App.get_loop_component_start_time();
20
21
  if (now - this->last_transmission_ >= 500) {
21
22
  // last transmission too long ago. Reset RX index.
22
23
  this->rx_message_.clear();
@@ -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
@@ -9,22 +9,32 @@ from esphome.const import (
9
9
  CONF_LONGITUDE,
10
10
  CONF_SATELLITES,
11
11
  CONF_SPEED,
12
+ DEVICE_CLASS_SPEED,
12
13
  STATE_CLASS_MEASUREMENT,
13
14
  UNIT_DEGREES,
14
15
  UNIT_KILOMETER_PER_HOUR,
15
16
  UNIT_METER,
16
17
  )
17
18
 
19
+ CONF_GPS_ID = "gps_id"
20
+ CONF_HDOP = "hdop"
21
+
22
+ ICON_ALTIMETER = "mdi:altimeter"
23
+ ICON_COMPASS = "mdi:compass"
24
+ ICON_LATITUDE = "mdi:latitude"
25
+ ICON_LONGITUDE = "mdi:longitude"
26
+ ICON_SATELLITE = "mdi:satellite-variant"
27
+ ICON_SPEEDOMETER = "mdi:speedometer"
28
+
18
29
  DEPENDENCIES = ["uart"]
19
30
  AUTO_LOAD = ["sensor"]
20
31
 
21
- CODEOWNERS = ["@coogle"]
32
+ CODEOWNERS = ["@coogle", "@ximex"]
22
33
 
23
34
  gps_ns = cg.esphome_ns.namespace("gps")
24
35
  GPS = gps_ns.class_("GPS", cg.Component, uart.UARTDevice)
25
36
  GPSListener = gps_ns.class_("GPSListener")
26
37
 
27
- CONF_GPS_ID = "gps_id"
28
38
  MULTI_CONF = True
29
39
  CONFIG_SCHEMA = cv.All(
30
40
  cv.Schema(
@@ -32,28 +42,44 @@ CONFIG_SCHEMA = cv.All(
32
42
  cv.GenerateID(): cv.declare_id(GPS),
33
43
  cv.Optional(CONF_LATITUDE): sensor.sensor_schema(
34
44
  unit_of_measurement=UNIT_DEGREES,
45
+ icon=ICON_LATITUDE,
35
46
  accuracy_decimals=6,
47
+ state_class=STATE_CLASS_MEASUREMENT,
36
48
  ),
37
49
  cv.Optional(CONF_LONGITUDE): sensor.sensor_schema(
38
50
  unit_of_measurement=UNIT_DEGREES,
51
+ icon=ICON_LONGITUDE,
39
52
  accuracy_decimals=6,
53
+ state_class=STATE_CLASS_MEASUREMENT,
40
54
  ),
41
55
  cv.Optional(CONF_SPEED): sensor.sensor_schema(
42
56
  unit_of_measurement=UNIT_KILOMETER_PER_HOUR,
43
- accuracy_decimals=6,
57
+ icon=ICON_SPEEDOMETER,
58
+ accuracy_decimals=3,
59
+ device_class=DEVICE_CLASS_SPEED,
60
+ state_class=STATE_CLASS_MEASUREMENT,
44
61
  ),
45
62
  cv.Optional(CONF_COURSE): sensor.sensor_schema(
46
63
  unit_of_measurement=UNIT_DEGREES,
64
+ icon=ICON_COMPASS,
47
65
  accuracy_decimals=2,
66
+ state_class=STATE_CLASS_MEASUREMENT,
48
67
  ),
49
68
  cv.Optional(CONF_ALTITUDE): sensor.sensor_schema(
50
69
  unit_of_measurement=UNIT_METER,
51
- accuracy_decimals=1,
70
+ icon=ICON_ALTIMETER,
71
+ accuracy_decimals=2,
72
+ state_class=STATE_CLASS_MEASUREMENT,
52
73
  ),
53
74
  cv.Optional(CONF_SATELLITES): sensor.sensor_schema(
75
+ icon=ICON_SATELLITE,
54
76
  accuracy_decimals=0,
55
77
  state_class=STATE_CLASS_MEASUREMENT,
56
78
  ),
79
+ cv.Optional(CONF_HDOP): sensor.sensor_schema(
80
+ accuracy_decimals=3,
81
+ state_class=STATE_CLASS_MEASUREMENT,
82
+ ),
57
83
  }
58
84
  )
59
85
  .extend(cv.polling_component_schema("20s"))
@@ -68,29 +94,33 @@ async def to_code(config):
68
94
  await cg.register_component(var, config)
69
95
  await uart.register_uart_device(var, config)
70
96
 
71
- if CONF_LATITUDE in config:
72
- sens = await sensor.new_sensor(config[CONF_LATITUDE])
97
+ if latitude_config := config.get(CONF_LATITUDE):
98
+ sens = await sensor.new_sensor(latitude_config)
73
99
  cg.add(var.set_latitude_sensor(sens))
74
100
 
75
- if CONF_LONGITUDE in config:
76
- sens = await sensor.new_sensor(config[CONF_LONGITUDE])
101
+ if longitude_config := config.get(CONF_LONGITUDE):
102
+ sens = await sensor.new_sensor(longitude_config)
77
103
  cg.add(var.set_longitude_sensor(sens))
78
104
 
79
- if CONF_SPEED in config:
80
- sens = await sensor.new_sensor(config[CONF_SPEED])
105
+ if speed_config := config.get(CONF_SPEED):
106
+ sens = await sensor.new_sensor(speed_config)
81
107
  cg.add(var.set_speed_sensor(sens))
82
108
 
83
- if CONF_COURSE in config:
84
- sens = await sensor.new_sensor(config[CONF_COURSE])
109
+ if course_config := config.get(CONF_COURSE):
110
+ sens = await sensor.new_sensor(course_config)
85
111
  cg.add(var.set_course_sensor(sens))
86
112
 
87
- if CONF_ALTITUDE in config:
88
- sens = await sensor.new_sensor(config[CONF_ALTITUDE])
113
+ if altitude_config := config.get(CONF_ALTITUDE):
114
+ sens = await sensor.new_sensor(altitude_config)
89
115
  cg.add(var.set_altitude_sensor(sens))
90
116
 
91
- if CONF_SATELLITES in config:
92
- sens = await sensor.new_sensor(config[CONF_SATELLITES])
117
+ if satellites_config := config.get(CONF_SATELLITES):
118
+ sens = await sensor.new_sensor(satellites_config)
93
119
  cg.add(var.set_satellites_sensor(sens))
94
120
 
121
+ if hdop_config := config.get(CONF_HDOP):
122
+ sens = await sensor.new_sensor(hdop_config)
123
+ cg.add(var.set_hdop_sensor(sens))
124
+
95
125
  # https://platformio.org/lib/show/1655/TinyGPSPlus
96
- cg.add_library("mikalhart/TinyGPSPlus", "1.0.2")
126
+ cg.add_library("mikalhart/TinyGPSPlus", "1.1.0")
@@ -10,6 +10,17 @@ static const char *const TAG = "gps";
10
10
 
11
11
  TinyGPSPlus &GPSListener::get_tiny_gps() { return this->parent_->get_tiny_gps(); }
12
12
 
13
+ void GPS::dump_config() {
14
+ ESP_LOGCONFIG(TAG, "GPS:");
15
+ LOG_SENSOR(" ", "Latitude", this->latitude_sensor_);
16
+ LOG_SENSOR(" ", "Longitude", this->longitude_sensor_);
17
+ LOG_SENSOR(" ", "Speed", this->speed_sensor_);
18
+ LOG_SENSOR(" ", "Course", this->course_sensor_);
19
+ LOG_SENSOR(" ", "Altitude", this->altitude_sensor_);
20
+ LOG_SENSOR(" ", "Satellites", this->satellites_sensor_);
21
+ LOG_SENSOR(" ", "HDOP", this->hdop_sensor_);
22
+ }
23
+
13
24
  void GPS::update() {
14
25
  if (this->latitude_sensor_ != nullptr)
15
26
  this->latitude_sensor_->publish_state(this->latitude_);
@@ -28,43 +39,51 @@ void GPS::update() {
28
39
 
29
40
  if (this->satellites_sensor_ != nullptr)
30
41
  this->satellites_sensor_->publish_state(this->satellites_);
42
+
43
+ if (this->hdop_sensor_ != nullptr)
44
+ this->hdop_sensor_->publish_state(this->hdop_);
31
45
  }
32
46
 
33
47
  void GPS::loop() {
34
- while (this->available() && !this->has_time_) {
48
+ while (this->available() > 0 && !this->has_time_) {
35
49
  if (this->tiny_gps_.encode(this->read())) {
36
- if (tiny_gps_.location.isUpdated()) {
37
- this->latitude_ = tiny_gps_.location.lat();
38
- this->longitude_ = tiny_gps_.location.lng();
50
+ if (this->tiny_gps_.location.isUpdated()) {
51
+ this->latitude_ = this->tiny_gps_.location.lat();
52
+ this->longitude_ = this->tiny_gps_.location.lng();
39
53
 
40
54
  ESP_LOGD(TAG, "Location:");
41
- ESP_LOGD(TAG, " Lat: %f", this->latitude_);
42
- ESP_LOGD(TAG, " Lon: %f", this->longitude_);
55
+ ESP_LOGD(TAG, " Lat: %.6f °", this->latitude_);
56
+ ESP_LOGD(TAG, " Lon: %.6f °", this->longitude_);
43
57
  }
44
58
 
45
- if (tiny_gps_.speed.isUpdated()) {
46
- this->speed_ = tiny_gps_.speed.kmph();
47
- ESP_LOGD(TAG, "Speed:");
48
- ESP_LOGD(TAG, " %f km/h", this->speed_);
59
+ if (this->tiny_gps_.speed.isUpdated()) {
60
+ this->speed_ = this->tiny_gps_.speed.kmph();
61
+ ESP_LOGD(TAG, "Speed: %.3f km/h", this->speed_);
49
62
  }
50
- if (tiny_gps_.course.isUpdated()) {
51
- this->course_ = tiny_gps_.course.deg();
52
- ESP_LOGD(TAG, "Course:");
53
- ESP_LOGD(TAG, " %f °", this->course_);
63
+
64
+ if (this->tiny_gps_.course.isUpdated()) {
65
+ this->course_ = this->tiny_gps_.course.deg();
66
+ ESP_LOGD(TAG, "Course: %.2f °", this->course_);
54
67
  }
55
- if (tiny_gps_.altitude.isUpdated()) {
56
- this->altitude_ = tiny_gps_.altitude.meters();
57
- ESP_LOGD(TAG, "Altitude:");
58
- ESP_LOGD(TAG, " %f m", this->altitude_);
68
+
69
+ if (this->tiny_gps_.altitude.isUpdated()) {
70
+ this->altitude_ = this->tiny_gps_.altitude.meters();
71
+ ESP_LOGD(TAG, "Altitude: %.2f m", this->altitude_);
59
72
  }
60
- if (tiny_gps_.satellites.isUpdated()) {
61
- this->satellites_ = tiny_gps_.satellites.value();
62
- ESP_LOGD(TAG, "Satellites:");
63
- ESP_LOGD(TAG, " %d", this->satellites_);
73
+
74
+ if (this->tiny_gps_.satellites.isUpdated()) {
75
+ this->satellites_ = this->tiny_gps_.satellites.value();
76
+ ESP_LOGD(TAG, "Satellites: %d", this->satellites_);
77
+ }
78
+
79
+ if (this->tiny_gps_.hdop.isUpdated()) {
80
+ this->hdop_ = this->tiny_gps_.hdop.hdop();
81
+ ESP_LOGD(TAG, "HDOP: %.3f", this->hdop_);
64
82
  }
65
83
 
66
- for (auto *listener : this->listeners_)
84
+ for (auto *listener : this->listeners_) {
67
85
  listener->on_update(this->tiny_gps_);
86
+ }
68
87
  }
69
88
  }
70
89
  }
@@ -5,7 +5,7 @@
5
5
  #include "esphome/core/component.h"
6
6
  #include "esphome/components/uart/uart.h"
7
7
  #include "esphome/components/sensor/sensor.h"
8
- #include <TinyGPS++.h>
8
+ #include <TinyGPSPlus.h>
9
9
 
10
10
  #include <vector>
11
11
 
@@ -27,12 +27,13 @@ class GPSListener {
27
27
 
28
28
  class GPS : public PollingComponent, public uart::UARTDevice {
29
29
  public:
30
- void set_latitude_sensor(sensor::Sensor *latitude_sensor) { latitude_sensor_ = latitude_sensor; }
31
- void set_longitude_sensor(sensor::Sensor *longitude_sensor) { longitude_sensor_ = longitude_sensor; }
32
- void set_speed_sensor(sensor::Sensor *speed_sensor) { speed_sensor_ = speed_sensor; }
33
- void set_course_sensor(sensor::Sensor *course_sensor) { course_sensor_ = course_sensor; }
34
- void set_altitude_sensor(sensor::Sensor *altitude_sensor) { altitude_sensor_ = altitude_sensor; }
35
- void set_satellites_sensor(sensor::Sensor *satellites_sensor) { satellites_sensor_ = satellites_sensor; }
30
+ void set_latitude_sensor(sensor::Sensor *latitude_sensor) { this->latitude_sensor_ = latitude_sensor; }
31
+ void set_longitude_sensor(sensor::Sensor *longitude_sensor) { this->longitude_sensor_ = longitude_sensor; }
32
+ void set_speed_sensor(sensor::Sensor *speed_sensor) { this->speed_sensor_ = speed_sensor; }
33
+ void set_course_sensor(sensor::Sensor *course_sensor) { this->course_sensor_ = course_sensor; }
34
+ void set_altitude_sensor(sensor::Sensor *altitude_sensor) { this->altitude_sensor_ = altitude_sensor; }
35
+ void set_satellites_sensor(sensor::Sensor *satellites_sensor) { this->satellites_sensor_ = satellites_sensor; }
36
+ void set_hdop_sensor(sensor::Sensor *hdop_sensor) { this->hdop_sensor_ = hdop_sensor; }
36
37
 
37
38
  void register_listener(GPSListener *listener) {
38
39
  listener->parent_ = this;
@@ -40,18 +41,20 @@ class GPS : public PollingComponent, public uart::UARTDevice {
40
41
  }
41
42
  float get_setup_priority() const override { return setup_priority::HARDWARE; }
42
43
 
44
+ void dump_config() override;
43
45
  void loop() override;
44
46
  void update() override;
45
47
 
46
48
  TinyGPSPlus &get_tiny_gps() { return this->tiny_gps_; }
47
49
 
48
50
  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;
51
+ float latitude_{NAN};
52
+ float longitude_{NAN};
53
+ float speed_{NAN};
54
+ float course_{NAN};
55
+ float altitude_{NAN};
56
+ uint16_t satellites_{0};
57
+ float hdop_{NAN};
55
58
 
56
59
  sensor::Sensor *latitude_sensor_{nullptr};
57
60
  sensor::Sensor *longitude_sensor_{nullptr};
@@ -59,6 +62,7 @@ class GPS : public PollingComponent, public uart::UARTDevice {
59
62
  sensor::Sensor *course_sensor_{nullptr};
60
63
  sensor::Sensor *altitude_sensor_{nullptr};
61
64
  sensor::Sensor *satellites_sensor_{nullptr};
65
+ sensor::Sensor *hdop_sensor_{nullptr};
62
66
 
63
67
  bool has_time_{false};
64
68
  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.climate_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) +