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
@@ -6,45 +6,39 @@ namespace pmsx003 {
6
6
 
7
7
  static const char *const TAG = "pmsx003";
8
8
 
9
- void PMSX003Component::set_pm_1_0_std_sensor(sensor::Sensor *pm_1_0_std_sensor) {
10
- pm_1_0_std_sensor_ = pm_1_0_std_sensor;
11
- }
12
- void PMSX003Component::set_pm_2_5_std_sensor(sensor::Sensor *pm_2_5_std_sensor) {
13
- pm_2_5_std_sensor_ = pm_2_5_std_sensor;
14
- }
15
- void PMSX003Component::set_pm_10_0_std_sensor(sensor::Sensor *pm_10_0_std_sensor) {
16
- pm_10_0_std_sensor_ = pm_10_0_std_sensor;
17
- }
9
+ static const uint8_t START_CHARACTER_1 = 0x42;
10
+ static const uint8_t START_CHARACTER_2 = 0x4D;
18
11
 
19
- void PMSX003Component::set_pm_1_0_sensor(sensor::Sensor *pm_1_0_sensor) { pm_1_0_sensor_ = pm_1_0_sensor; }
20
- void PMSX003Component::set_pm_2_5_sensor(sensor::Sensor *pm_2_5_sensor) { pm_2_5_sensor_ = pm_2_5_sensor; }
21
- void PMSX003Component::set_pm_10_0_sensor(sensor::Sensor *pm_10_0_sensor) { pm_10_0_sensor_ = pm_10_0_sensor; }
12
+ static const uint16_t PMS_STABILISING_MS = 30000; // time taken for the sensor to become stable after power on in ms
22
13
 
23
- void PMSX003Component::set_pm_particles_03um_sensor(sensor::Sensor *pm_particles_03um_sensor) {
24
- pm_particles_03um_sensor_ = pm_particles_03um_sensor;
25
- }
26
- void PMSX003Component::set_pm_particles_05um_sensor(sensor::Sensor *pm_particles_05um_sensor) {
27
- pm_particles_05um_sensor_ = pm_particles_05um_sensor;
28
- }
29
- void PMSX003Component::set_pm_particles_10um_sensor(sensor::Sensor *pm_particles_10um_sensor) {
30
- pm_particles_10um_sensor_ = pm_particles_10um_sensor;
31
- }
32
- void PMSX003Component::set_pm_particles_25um_sensor(sensor::Sensor *pm_particles_25um_sensor) {
33
- pm_particles_25um_sensor_ = pm_particles_25um_sensor;
34
- }
35
- void PMSX003Component::set_pm_particles_50um_sensor(sensor::Sensor *pm_particles_50um_sensor) {
36
- pm_particles_50um_sensor_ = pm_particles_50um_sensor;
37
- }
38
- void PMSX003Component::set_pm_particles_100um_sensor(sensor::Sensor *pm_particles_100um_sensor) {
39
- pm_particles_100um_sensor_ = pm_particles_100um_sensor;
40
- }
14
+ static const uint16_t PMS_CMD_MEASUREMENT_MODE_PASSIVE =
15
+ 0x0000; // use `PMS_CMD_MANUAL_MEASUREMENT` to trigger a measurement
16
+ static const uint16_t PMS_CMD_MEASUREMENT_MODE_ACTIVE = 0x0001; // automatically perform measurements
17
+ static const uint16_t PMS_CMD_SLEEP_MODE_SLEEP = 0x0000; // go to sleep mode
18
+ static const uint16_t PMS_CMD_SLEEP_MODE_WAKEUP = 0x0001; // wake up from sleep mode
41
19
 
42
- void PMSX003Component::set_temperature_sensor(sensor::Sensor *temperature_sensor) {
43
- temperature_sensor_ = temperature_sensor;
44
- }
45
- void PMSX003Component::set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; }
46
- void PMSX003Component::set_formaldehyde_sensor(sensor::Sensor *formaldehyde_sensor) {
47
- formaldehyde_sensor_ = formaldehyde_sensor;
20
+ void PMSX003Component::dump_config() {
21
+ ESP_LOGCONFIG(TAG, "PMSX003:");
22
+ LOG_SENSOR(" ", "PM1.0STD", this->pm_1_0_std_sensor_);
23
+ LOG_SENSOR(" ", "PM2.5STD", this->pm_2_5_std_sensor_);
24
+ LOG_SENSOR(" ", "PM10.0STD", this->pm_10_0_std_sensor_);
25
+
26
+ LOG_SENSOR(" ", "PM1.0", this->pm_1_0_sensor_);
27
+ LOG_SENSOR(" ", "PM2.5", this->pm_2_5_sensor_);
28
+ LOG_SENSOR(" ", "PM10.0", this->pm_10_0_sensor_);
29
+
30
+ LOG_SENSOR(" ", "PM0.3um", this->pm_particles_03um_sensor_);
31
+ LOG_SENSOR(" ", "PM0.5um", this->pm_particles_05um_sensor_);
32
+ LOG_SENSOR(" ", "PM1.0um", this->pm_particles_10um_sensor_);
33
+ LOG_SENSOR(" ", "PM2.5um", this->pm_particles_25um_sensor_);
34
+ LOG_SENSOR(" ", "PM5.0um", this->pm_particles_50um_sensor_);
35
+ LOG_SENSOR(" ", "PM10.0um", this->pm_particles_100um_sensor_);
36
+
37
+ LOG_SENSOR(" ", "Formaldehyde", this->formaldehyde_sensor_);
38
+
39
+ LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
40
+ LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
41
+ this->check_uart_settings(9600);
48
42
  }
49
43
 
50
44
  void PMSX003Component::loop() {
@@ -55,8 +49,8 @@ void PMSX003Component::loop() {
55
49
  // need to keep track of what state we're in.
56
50
  if (this->update_interval_ > PMS_STABILISING_MS) {
57
51
  if (this->initialised_ == 0) {
58
- this->send_command_(PMS_CMD_AUTO_MANUAL, 0);
59
- this->send_command_(PMS_CMD_ON_STANDBY, 1);
52
+ this->send_command_(PMS_CMD_MEASUREMENT_MODE, PMS_CMD_MEASUREMENT_MODE_PASSIVE);
53
+ this->send_command_(PMS_CMD_SLEEP_MODE, PMS_CMD_SLEEP_MODE_WAKEUP);
60
54
  this->initialised_ = 1;
61
55
  }
62
56
  switch (this->state_) {
@@ -66,7 +60,7 @@ void PMSX003Component::loop() {
66
60
  return;
67
61
 
68
62
  this->state_ = PMSX003_STATE_STABILISING;
69
- this->send_command_(PMS_CMD_ON_STANDBY, 1);
63
+ this->send_command_(PMS_CMD_SLEEP_MODE, PMS_CMD_SLEEP_MODE_WAKEUP);
70
64
  this->fan_on_time_ = now;
71
65
  return;
72
66
  case PMSX003_STATE_STABILISING:
@@ -77,7 +71,7 @@ void PMSX003Component::loop() {
77
71
  while (this->available())
78
72
  this->read_byte(&this->data_[0]);
79
73
  // Trigger a new read
80
- this->send_command_(PMS_CMD_TRIG_MANUAL, 0);
74
+ this->send_command_(PMS_CMD_MANUAL_MEASUREMENT, 0);
81
75
  this->state_ = PMSX003_STATE_WAITING;
82
76
  break;
83
77
  case PMSX003_STATE_WAITING:
@@ -116,242 +110,212 @@ void PMSX003Component::loop() {
116
110
  }
117
111
  }
118
112
  }
119
- float PMSX003Component::get_setup_priority() const { return setup_priority::DATA; }
113
+
120
114
  optional<bool> PMSX003Component::check_byte_() {
121
- uint8_t index = this->data_index_;
122
- uint8_t byte = this->data_[index];
115
+ const uint8_t index = this->data_index_;
116
+ const uint8_t byte = this->data_[index];
123
117
 
124
- if (index == 0)
125
- return byte == 0x42;
118
+ if (index == 0 || index == 1) {
119
+ const uint8_t start_char = index == 0 ? START_CHARACTER_1 : START_CHARACTER_2;
120
+ if (byte == start_char) {
121
+ return true;
122
+ }
126
123
 
127
- if (index == 1)
128
- return byte == 0x4D;
124
+ ESP_LOGW(TAG, "Start character %u mismatch: 0x%02X != 0x%02X", index + 1, byte, START_CHARACTER_1);
125
+ return false;
126
+ }
129
127
 
130
- if (index == 2)
128
+ if (index == 2) {
131
129
  return true;
130
+ }
132
131
 
133
- uint16_t payload_length = this->get_16_bit_uint_(2);
132
+ const uint16_t payload_length = this->get_16_bit_uint_(2);
134
133
  if (index == 3) {
135
- bool length_matches = false;
136
- switch (this->type_) {
137
- case PMSX003_TYPE_X003:
138
- length_matches = payload_length == 28 || payload_length == 20;
139
- break;
140
- case PMSX003_TYPE_5003T:
141
- case PMSX003_TYPE_5003S:
142
- length_matches = payload_length == 28;
143
- break;
144
- case PMSX003_TYPE_5003ST:
145
- length_matches = payload_length == 36;
146
- break;
147
- }
148
-
149
- if (!length_matches) {
150
- ESP_LOGW(TAG, "PMSX003 length %u doesn't match. Are you using the correct PMSX003 type?", payload_length);
134
+ if (this->check_payload_length_(payload_length)) {
135
+ return true;
136
+ } else {
137
+ ESP_LOGW(TAG, "Payload length %u doesn't match. Are you using the correct PMSX003 type?", payload_length);
151
138
  return false;
152
139
  }
153
- return true;
154
140
  }
155
141
 
156
- // start (16bit) + length (16bit) + DATA (payload_length-2 bytes) + checksum (16bit)
157
- uint8_t total_size = 4 + payload_length;
142
+ // start (16bit) + length (16bit) + DATA (payload_length - 16bit) + checksum (16bit)
143
+ const uint16_t total_size = 4 + payload_length;
158
144
 
159
- if (index < total_size - 1)
145
+ if (index < total_size - 1) {
160
146
  return true;
147
+ }
161
148
 
162
149
  // checksum is without checksum bytes
163
150
  uint16_t checksum = 0;
164
- for (uint8_t i = 0; i < total_size - 2; i++)
151
+ for (uint16_t i = 0; i < total_size - 2; i++) {
165
152
  checksum += this->data_[i];
153
+ }
166
154
 
167
- uint16_t check = this->get_16_bit_uint_(total_size - 2);
155
+ const uint16_t check = this->get_16_bit_uint_(total_size - 2);
168
156
  if (checksum != check) {
169
- ESP_LOGW(TAG, "PMSX003 checksum mismatch! 0x%02X!=0x%02X", checksum, check);
157
+ ESP_LOGW(TAG, "PMSX003 checksum mismatch! 0x%02X != 0x%02X", checksum, check);
170
158
  return false;
171
159
  }
172
160
 
173
161
  return {};
174
162
  }
175
163
 
176
- void PMSX003Component::send_command_(uint8_t cmd, uint16_t data) {
177
- this->data_index_ = 0;
178
- this->data_[data_index_++] = 0x42;
179
- this->data_[data_index_++] = 0x4D;
180
- this->data_[data_index_++] = cmd;
181
- this->data_[data_index_++] = (data >> 8) & 0xFF;
182
- this->data_[data_index_++] = (data >> 0) & 0xFF;
183
- int sum = 0;
184
- for (int i = 0; i < data_index_; i++) {
185
- sum += this->data_[i];
164
+ bool PMSX003Component::check_payload_length_(uint16_t payload_length) {
165
+ switch (this->type_) {
166
+ case PMSX003_TYPE_X003:
167
+ // The expected payload length is typically 28 bytes.
168
+ // However, a 20-byte payload check was already present in the code.
169
+ // No official documentation was found confirming this.
170
+ // Retaining this check to avoid breaking existing behavior.
171
+ return payload_length == 28 || payload_length == 20; // 2*13+2
172
+ case PMSX003_TYPE_5003T:
173
+ case PMSX003_TYPE_5003S:
174
+ return payload_length == 28; // 2*13+2 (Data 13 not set/reserved)
175
+ case PMSX003_TYPE_5003ST:
176
+ return payload_length == 36; // 2*17+2 (Data 16 not set/reserved)
186
177
  }
187
- this->data_[data_index_++] = (sum >> 8) & 0xFF;
188
- this->data_[data_index_++] = (sum >> 0) & 0xFF;
189
- for (int i = 0; i < data_index_; i++) {
190
- this->write_byte(this->data_[i]);
178
+ return false;
179
+ }
180
+
181
+ void PMSX003Component::send_command_(PMSX0003Command cmd, uint16_t data) {
182
+ uint8_t send_data[7] = {
183
+ START_CHARACTER_1, // Start Byte 1
184
+ START_CHARACTER_2, // Start Byte 2
185
+ cmd, // Command
186
+ uint8_t((data >> 8) & 0xFF), // Data 1
187
+ uint8_t((data >> 0) & 0xFF), // Data 2
188
+ 0, // Verify Byte 1
189
+ 0, // Verify Byte 2
190
+ };
191
+
192
+ // Calculate checksum
193
+ uint16_t checksum = 0;
194
+ for (uint8_t i = 0; i < 5; i++) {
195
+ checksum += send_data[i];
196
+ }
197
+ send_data[5] = (checksum >> 8) & 0xFF; // Verify Byte 1
198
+ send_data[6] = (checksum >> 0) & 0xFF; // Verify Byte 2
199
+
200
+ for (auto send_byte : send_data) {
201
+ this->write_byte(send_byte);
191
202
  }
192
- this->data_index_ = 0;
193
203
  }
194
204
 
195
205
  void PMSX003Component::parse_data_() {
196
- switch (this->type_) {
197
- case PMSX003_TYPE_5003ST: {
198
- float temperature = (int16_t) this->get_16_bit_uint_(30) / 10.0f;
199
- float humidity = this->get_16_bit_uint_(32) / 10.0f;
206
+ // Particle Matter
207
+ const uint16_t pm_1_0_std_concentration = this->get_16_bit_uint_(4);
208
+ const uint16_t pm_2_5_std_concentration = this->get_16_bit_uint_(6);
209
+ const uint16_t pm_10_0_std_concentration = this->get_16_bit_uint_(8);
210
+
211
+ const uint16_t pm_1_0_concentration = this->get_16_bit_uint_(10);
212
+ const uint16_t pm_2_5_concentration = this->get_16_bit_uint_(12);
213
+ const uint16_t pm_10_0_concentration = this->get_16_bit_uint_(14);
214
+
215
+ const uint16_t pm_particles_03um = this->get_16_bit_uint_(16);
216
+ const uint16_t pm_particles_05um = this->get_16_bit_uint_(18);
217
+ const uint16_t pm_particles_10um = this->get_16_bit_uint_(20);
218
+ const uint16_t pm_particles_25um = this->get_16_bit_uint_(22);
219
+
220
+ ESP_LOGD(TAG,
221
+ "Got PM1.0 Standard Concentration: %u µg/m³, PM2.5 Standard Concentration %u µg/m³, PM10.0 Standard "
222
+ "Concentration: %u µg/m³, PM1.0 Concentration: %u µg/m³, PM2.5 Concentration %u µg/m³, PM10.0 "
223
+ "Concentration: %u µg/m³",
224
+ pm_1_0_std_concentration, pm_2_5_std_concentration, pm_10_0_std_concentration, pm_1_0_concentration,
225
+ pm_2_5_concentration, pm_10_0_concentration);
226
+
227
+ if (this->pm_1_0_std_sensor_ != nullptr)
228
+ this->pm_1_0_std_sensor_->publish_state(pm_1_0_std_concentration);
229
+ if (this->pm_2_5_std_sensor_ != nullptr)
230
+ this->pm_2_5_std_sensor_->publish_state(pm_2_5_std_concentration);
231
+ if (this->pm_10_0_std_sensor_ != nullptr)
232
+ this->pm_10_0_std_sensor_->publish_state(pm_10_0_std_concentration);
233
+
234
+ if (this->pm_1_0_sensor_ != nullptr)
235
+ this->pm_1_0_sensor_->publish_state(pm_1_0_concentration);
236
+ if (this->pm_2_5_sensor_ != nullptr)
237
+ this->pm_2_5_sensor_->publish_state(pm_2_5_concentration);
238
+ if (this->pm_10_0_sensor_ != nullptr)
239
+ this->pm_10_0_sensor_->publish_state(pm_10_0_concentration);
240
+
241
+ if (this->pm_particles_03um_sensor_ != nullptr)
242
+ this->pm_particles_03um_sensor_->publish_state(pm_particles_03um);
243
+ if (this->pm_particles_05um_sensor_ != nullptr)
244
+ this->pm_particles_05um_sensor_->publish_state(pm_particles_05um);
245
+ if (this->pm_particles_10um_sensor_ != nullptr)
246
+ this->pm_particles_10um_sensor_->publish_state(pm_particles_10um);
247
+ if (this->pm_particles_25um_sensor_ != nullptr)
248
+ this->pm_particles_25um_sensor_->publish_state(pm_particles_25um);
249
+
250
+ if (this->type_ == PMSX003_TYPE_5003T) {
251
+ ESP_LOGD(TAG,
252
+ "Got PM0.3 Particles: %u Count/0.1L, PM0.5 Particles: %u Count/0.1L, PM1.0 Particles: %u Count/0.1L, "
253
+ "PM2.5 Particles %u Count/0.1L",
254
+ pm_particles_03um, pm_particles_05um, pm_particles_10um, pm_particles_25um);
255
+ } else {
256
+ // Note the pm particles 50um & 100um are not returned,
257
+ // as PMS5003T uses those data values for temperature and humidity.
258
+ const uint16_t pm_particles_50um = this->get_16_bit_uint_(24);
259
+ const uint16_t pm_particles_100um = this->get_16_bit_uint_(26);
260
+
261
+ ESP_LOGD(TAG,
262
+ "Got PM0.3 Particles: %u Count/0.1L, PM0.5 Particles: %u Count/0.1L, PM1.0 Particles: %u Count/0.1L, "
263
+ "PM2.5 Particles %u Count/0.1L, PM5.0 Particles: %u Count/0.1L, PM10.0 Particles %u Count/0.1L",
264
+ pm_particles_03um, pm_particles_05um, pm_particles_10um, pm_particles_25um, pm_particles_50um,
265
+ pm_particles_100um);
266
+
267
+ if (this->pm_particles_50um_sensor_ != nullptr)
268
+ this->pm_particles_50um_sensor_->publish_state(pm_particles_50um);
269
+ if (this->pm_particles_100um_sensor_ != nullptr)
270
+ this->pm_particles_100um_sensor_->publish_state(pm_particles_100um);
271
+ }
200
272
 
201
- ESP_LOGD(TAG, "Got Temperature: %.1f°C, Humidity: %.1f%%", temperature, humidity);
273
+ // Formaldehyde
274
+ if (this->type_ == PMSX003_TYPE_5003ST || this->type_ == PMSX003_TYPE_5003S) {
275
+ const uint16_t formaldehyde = this->get_16_bit_uint_(28);
202
276
 
203
- if (this->temperature_sensor_ != nullptr)
204
- this->temperature_sensor_->publish_state(temperature);
205
- if (this->humidity_sensor_ != nullptr)
206
- this->humidity_sensor_->publish_state(humidity);
207
- // The rest of the PMS5003ST matches the PMS5003S, continue on
208
- }
209
- case PMSX003_TYPE_5003S: {
210
- uint16_t formaldehyde = this->get_16_bit_uint_(28);
277
+ ESP_LOGD(TAG, "Got Formaldehyde: %u µg/m^3", formaldehyde);
211
278
 
212
- ESP_LOGD(TAG, "Got Formaldehyde: %u µg/m^3", formaldehyde);
279
+ if (this->formaldehyde_sensor_ != nullptr)
280
+ this->formaldehyde_sensor_->publish_state(formaldehyde);
281
+ }
213
282
 
214
- if (this->formaldehyde_sensor_ != nullptr)
215
- this->formaldehyde_sensor_->publish_state(formaldehyde);
216
- // The rest of the PMS5003S matches the PMS5003, continue on
217
- }
218
- case PMSX003_TYPE_X003: {
219
- uint16_t pm_1_0_std_concentration = this->get_16_bit_uint_(4);
220
- uint16_t pm_2_5_std_concentration = this->get_16_bit_uint_(6);
221
- uint16_t pm_10_0_std_concentration = this->get_16_bit_uint_(8);
222
-
223
- uint16_t pm_1_0_concentration = this->get_16_bit_uint_(10);
224
- uint16_t pm_2_5_concentration = this->get_16_bit_uint_(12);
225
- uint16_t pm_10_0_concentration = this->get_16_bit_uint_(14);
226
-
227
- uint16_t pm_particles_03um = this->get_16_bit_uint_(16);
228
- uint16_t pm_particles_05um = this->get_16_bit_uint_(18);
229
- uint16_t pm_particles_10um = this->get_16_bit_uint_(20);
230
- uint16_t pm_particles_25um = this->get_16_bit_uint_(22);
231
- uint16_t pm_particles_50um = this->get_16_bit_uint_(24);
232
- uint16_t pm_particles_100um = this->get_16_bit_uint_(26);
233
-
234
- ESP_LOGD(TAG,
235
- "Got PM1.0 Concentration: %u µg/m^3, PM2.5 Concentration %u µg/m^3, PM10.0 Concentration: %u µg/m^3",
236
- pm_1_0_concentration, pm_2_5_concentration, pm_10_0_concentration);
237
-
238
- if (this->pm_1_0_std_sensor_ != nullptr)
239
- this->pm_1_0_std_sensor_->publish_state(pm_1_0_std_concentration);
240
- if (this->pm_2_5_std_sensor_ != nullptr)
241
- this->pm_2_5_std_sensor_->publish_state(pm_2_5_std_concentration);
242
- if (this->pm_10_0_std_sensor_ != nullptr)
243
- this->pm_10_0_std_sensor_->publish_state(pm_10_0_std_concentration);
244
-
245
- if (this->pm_1_0_sensor_ != nullptr)
246
- this->pm_1_0_sensor_->publish_state(pm_1_0_concentration);
247
- if (this->pm_2_5_sensor_ != nullptr)
248
- this->pm_2_5_sensor_->publish_state(pm_2_5_concentration);
249
- if (this->pm_10_0_sensor_ != nullptr)
250
- this->pm_10_0_sensor_->publish_state(pm_10_0_concentration);
251
-
252
- if (this->pm_particles_03um_sensor_ != nullptr)
253
- this->pm_particles_03um_sensor_->publish_state(pm_particles_03um);
254
- if (this->pm_particles_05um_sensor_ != nullptr)
255
- this->pm_particles_05um_sensor_->publish_state(pm_particles_05um);
256
- if (this->pm_particles_10um_sensor_ != nullptr)
257
- this->pm_particles_10um_sensor_->publish_state(pm_particles_10um);
258
- if (this->pm_particles_25um_sensor_ != nullptr)
259
- this->pm_particles_25um_sensor_->publish_state(pm_particles_25um);
260
- if (this->pm_particles_50um_sensor_ != nullptr)
261
- this->pm_particles_50um_sensor_->publish_state(pm_particles_50um);
262
- if (this->pm_particles_100um_sensor_ != nullptr)
263
- this->pm_particles_100um_sensor_->publish_state(pm_particles_100um);
264
- break;
265
- }
266
- case PMSX003_TYPE_5003T: {
267
- uint16_t pm_1_0_std_concentration = this->get_16_bit_uint_(4);
268
- uint16_t pm_2_5_std_concentration = this->get_16_bit_uint_(6);
269
- uint16_t pm_10_0_std_concentration = this->get_16_bit_uint_(8);
270
-
271
- uint16_t pm_1_0_concentration = this->get_16_bit_uint_(10);
272
- uint16_t pm_2_5_concentration = this->get_16_bit_uint_(12);
273
- uint16_t pm_10_0_concentration = this->get_16_bit_uint_(14);
274
-
275
- uint16_t pm_particles_03um = this->get_16_bit_uint_(16);
276
- uint16_t pm_particles_05um = this->get_16_bit_uint_(18);
277
- uint16_t pm_particles_10um = this->get_16_bit_uint_(20);
278
- uint16_t pm_particles_25um = this->get_16_bit_uint_(22);
279
- // Note the pm particles 50um & 100um are not returned,
280
- // as PMS5003T uses those data values for temperature and humidity.
281
-
282
- float temperature = (int16_t) this->get_16_bit_uint_(24) / 10.0f;
283
- float humidity = this->get_16_bit_uint_(26) / 10.0f;
284
-
285
- ESP_LOGD(TAG,
286
- "Got PM1.0 Concentration: %u µg/m^3, PM2.5 Concentration %u µg/m^3, PM10.0 Concentration: %u µg/m^3, "
287
- "Temperature: %.1f°C, Humidity: %.1f%%",
288
- pm_1_0_concentration, pm_2_5_concentration, pm_10_0_concentration, temperature, humidity);
289
-
290
- if (this->pm_1_0_std_sensor_ != nullptr)
291
- this->pm_1_0_std_sensor_->publish_state(pm_1_0_std_concentration);
292
- if (this->pm_2_5_std_sensor_ != nullptr)
293
- this->pm_2_5_std_sensor_->publish_state(pm_2_5_std_concentration);
294
- if (this->pm_10_0_std_sensor_ != nullptr)
295
- this->pm_10_0_std_sensor_->publish_state(pm_10_0_std_concentration);
296
-
297
- if (this->pm_1_0_sensor_ != nullptr)
298
- this->pm_1_0_sensor_->publish_state(pm_1_0_concentration);
299
- if (this->pm_2_5_sensor_ != nullptr)
300
- this->pm_2_5_sensor_->publish_state(pm_2_5_concentration);
301
- if (this->pm_10_0_sensor_ != nullptr)
302
- this->pm_10_0_sensor_->publish_state(pm_10_0_concentration);
303
-
304
- if (this->pm_particles_03um_sensor_ != nullptr)
305
- this->pm_particles_03um_sensor_->publish_state(pm_particles_03um);
306
- if (this->pm_particles_05um_sensor_ != nullptr)
307
- this->pm_particles_05um_sensor_->publish_state(pm_particles_05um);
308
- if (this->pm_particles_10um_sensor_ != nullptr)
309
- this->pm_particles_10um_sensor_->publish_state(pm_particles_10um);
310
- if (this->pm_particles_25um_sensor_ != nullptr)
311
- this->pm_particles_25um_sensor_->publish_state(pm_particles_25um);
312
-
313
- if (this->temperature_sensor_ != nullptr)
314
- this->temperature_sensor_->publish_state(temperature);
315
- if (this->humidity_sensor_ != nullptr)
316
- this->humidity_sensor_->publish_state(humidity);
317
- break;
318
- }
283
+ // Temperature and Humidity
284
+ if (this->type_ == PMSX003_TYPE_5003ST || this->type_ == PMSX003_TYPE_5003T) {
285
+ const uint8_t temperature_offset = (this->type_ == PMSX003_TYPE_5003T) ? 24 : 30;
286
+
287
+ const float temperature = static_cast<int16_t>(this->get_16_bit_uint_(temperature_offset)) / 10.0f;
288
+ const float humidity = this->get_16_bit_uint_(temperature_offset + 2) / 10.0f;
289
+
290
+ ESP_LOGD(TAG, "Got Temperature: %.1f°C, Humidity: %.1f%%", temperature, humidity);
291
+
292
+ if (this->temperature_sensor_ != nullptr)
293
+ this->temperature_sensor_->publish_state(temperature);
294
+ if (this->humidity_sensor_ != nullptr)
295
+ this->humidity_sensor_->publish_state(humidity);
296
+ }
297
+
298
+ // Firmware Version and Error Code
299
+ if (this->type_ == PMSX003_TYPE_5003ST) {
300
+ const uint8_t firmware_version = this->data_[36];
301
+ const uint8_t error_code = this->data_[37];
302
+
303
+ ESP_LOGD(TAG, "Got Firmware Version: 0x%02X, Error Code: 0x%02X", firmware_version, error_code);
319
304
  }
320
305
 
321
306
  // Spin down the sensor again if we aren't going to need it until more time has
322
307
  // passed than it takes to stabilise
323
308
  if (this->update_interval_ > PMS_STABILISING_MS) {
324
- this->send_command_(PMS_CMD_ON_STANDBY, 0);
309
+ this->send_command_(PMS_CMD_SLEEP_MODE, PMS_CMD_SLEEP_MODE_SLEEP);
325
310
  this->state_ = PMSX003_STATE_IDLE;
326
311
  }
327
312
 
328
313
  this->status_clear_warning();
329
314
  }
315
+
330
316
  uint16_t PMSX003Component::get_16_bit_uint_(uint8_t start_index) {
331
317
  return (uint16_t(this->data_[start_index]) << 8) | uint16_t(this->data_[start_index + 1]);
332
318
  }
333
- void PMSX003Component::dump_config() {
334
- ESP_LOGCONFIG(TAG, "PMSX003:");
335
- LOG_SENSOR(" ", "PM1.0STD", this->pm_1_0_std_sensor_);
336
- LOG_SENSOR(" ", "PM2.5STD", this->pm_2_5_std_sensor_);
337
- LOG_SENSOR(" ", "PM10.0STD", this->pm_10_0_std_sensor_);
338
-
339
- LOG_SENSOR(" ", "PM1.0", this->pm_1_0_sensor_);
340
- LOG_SENSOR(" ", "PM2.5", this->pm_2_5_sensor_);
341
- LOG_SENSOR(" ", "PM10.0", this->pm_10_0_sensor_);
342
-
343
- LOG_SENSOR(" ", "PM0.3um", this->pm_particles_03um_sensor_);
344
- LOG_SENSOR(" ", "PM0.5um", this->pm_particles_05um_sensor_);
345
- LOG_SENSOR(" ", "PM1.0um", this->pm_particles_10um_sensor_);
346
- LOG_SENSOR(" ", "PM2.5um", this->pm_particles_25um_sensor_);
347
- LOG_SENSOR(" ", "PM5.0um", this->pm_particles_50um_sensor_);
348
- LOG_SENSOR(" ", "PM10.0um", this->pm_particles_100um_sensor_);
349
-
350
- LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
351
- LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
352
- LOG_SENSOR(" ", "Formaldehyde", this->formaldehyde_sensor_);
353
- this->check_uart_settings(9600);
354
- }
355
319
 
356
320
  } // namespace pmsx003
357
321
  } // namespace esphome
@@ -7,13 +7,12 @@
7
7
  namespace esphome {
8
8
  namespace pmsx003 {
9
9
 
10
- // known command bytes
11
- static const uint8_t PMS_CMD_AUTO_MANUAL =
12
- 0xE1; // data=0: perform measurement manually, data=1: perform measurement automatically
13
- static const uint8_t PMS_CMD_TRIG_MANUAL = 0xE2; // trigger a manual measurement
14
- static const uint8_t PMS_CMD_ON_STANDBY = 0xE4; // data=0: go to standby mode, data=1: go to normal mode
15
-
16
- static const uint16_t PMS_STABILISING_MS = 30000; // time taken for the sensor to become stable after power on
10
+ enum PMSX0003Command : uint8_t {
11
+ PMS_CMD_MEASUREMENT_MODE =
12
+ 0xE1, // Data Options: `PMS_CMD_MEASUREMENT_MODE_PASSIVE`, `PMS_CMD_MEASUREMENT_MODE_ACTIVE`
13
+ PMS_CMD_MANUAL_MEASUREMENT = 0xE2,
14
+ PMS_CMD_SLEEP_MODE = 0xE4, // Data Options: `PMS_CMD_SLEEP_MODE_SLEEP`, `PMS_CMD_SLEEP_MODE_WAKEUP`
15
+ };
17
16
 
18
17
  enum PMSX003Type {
19
18
  PMSX003_TYPE_X003 = 0,
@@ -31,37 +30,53 @@ enum PMSX003State {
31
30
  class PMSX003Component : public uart::UARTDevice, public Component {
32
31
  public:
33
32
  PMSX003Component() = default;
34
- void loop() override;
35
- float get_setup_priority() const override;
33
+ float get_setup_priority() const override { return setup_priority::DATA; }
36
34
  void dump_config() override;
35
+ void loop() override;
37
36
 
38
- void set_type(PMSX003Type type) { type_ = type; }
39
-
40
- void set_update_interval(uint32_t val) { update_interval_ = val; };
41
-
42
- void set_pm_1_0_std_sensor(sensor::Sensor *pm_1_0_std_sensor);
43
- void set_pm_2_5_std_sensor(sensor::Sensor *pm_2_5_std_sensor);
44
- void set_pm_10_0_std_sensor(sensor::Sensor *pm_10_0_std_sensor);
45
-
46
- void set_pm_1_0_sensor(sensor::Sensor *pm_1_0_sensor);
47
- void set_pm_2_5_sensor(sensor::Sensor *pm_2_5_sensor);
48
- void set_pm_10_0_sensor(sensor::Sensor *pm_10_0_sensor);
49
-
50
- void set_pm_particles_03um_sensor(sensor::Sensor *pm_particles_03um_sensor);
51
- void set_pm_particles_05um_sensor(sensor::Sensor *pm_particles_05um_sensor);
52
- void set_pm_particles_10um_sensor(sensor::Sensor *pm_particles_10um_sensor);
53
- void set_pm_particles_25um_sensor(sensor::Sensor *pm_particles_25um_sensor);
54
- void set_pm_particles_50um_sensor(sensor::Sensor *pm_particles_50um_sensor);
55
- void set_pm_particles_100um_sensor(sensor::Sensor *pm_particles_100um_sensor);
56
-
57
- void set_temperature_sensor(sensor::Sensor *temperature_sensor);
58
- void set_humidity_sensor(sensor::Sensor *humidity_sensor);
59
- void set_formaldehyde_sensor(sensor::Sensor *formaldehyde_sensor);
37
+ void set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; }
38
+
39
+ void set_type(PMSX003Type type) { this->type_ = type; }
40
+
41
+ void set_pm_1_0_std_sensor(sensor::Sensor *pm_1_0_std_sensor) { this->pm_1_0_std_sensor_ = pm_1_0_std_sensor; }
42
+ void set_pm_2_5_std_sensor(sensor::Sensor *pm_2_5_std_sensor) { this->pm_2_5_std_sensor_ = pm_2_5_std_sensor; }
43
+ void set_pm_10_0_std_sensor(sensor::Sensor *pm_10_0_std_sensor) { this->pm_10_0_std_sensor_ = pm_10_0_std_sensor; }
44
+
45
+ void set_pm_1_0_sensor(sensor::Sensor *pm_1_0_sensor) { this->pm_1_0_sensor_ = pm_1_0_sensor; }
46
+ void set_pm_2_5_sensor(sensor::Sensor *pm_2_5_sensor) { this->pm_2_5_sensor_ = pm_2_5_sensor; }
47
+ void set_pm_10_0_sensor(sensor::Sensor *pm_10_0_sensor) { this->pm_10_0_sensor_ = pm_10_0_sensor; }
48
+
49
+ void set_pm_particles_03um_sensor(sensor::Sensor *pm_particles_03um_sensor) {
50
+ this->pm_particles_03um_sensor_ = pm_particles_03um_sensor;
51
+ }
52
+ void set_pm_particles_05um_sensor(sensor::Sensor *pm_particles_05um_sensor) {
53
+ this->pm_particles_05um_sensor_ = pm_particles_05um_sensor;
54
+ }
55
+ void set_pm_particles_10um_sensor(sensor::Sensor *pm_particles_10um_sensor) {
56
+ this->pm_particles_10um_sensor_ = pm_particles_10um_sensor;
57
+ }
58
+ void set_pm_particles_25um_sensor(sensor::Sensor *pm_particles_25um_sensor) {
59
+ this->pm_particles_25um_sensor_ = pm_particles_25um_sensor;
60
+ }
61
+ void set_pm_particles_50um_sensor(sensor::Sensor *pm_particles_50um_sensor) {
62
+ this->pm_particles_50um_sensor_ = pm_particles_50um_sensor;
63
+ }
64
+ void set_pm_particles_100um_sensor(sensor::Sensor *pm_particles_100um_sensor) {
65
+ this->pm_particles_100um_sensor_ = pm_particles_100um_sensor;
66
+ }
67
+
68
+ void set_formaldehyde_sensor(sensor::Sensor *formaldehyde_sensor) {
69
+ this->formaldehyde_sensor_ = formaldehyde_sensor;
70
+ }
71
+
72
+ void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; }
73
+ void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; }
60
74
 
61
75
  protected:
62
76
  optional<bool> check_byte_();
63
77
  void parse_data_();
64
- void send_command_(uint8_t cmd, uint16_t data);
78
+ bool check_payload_length_(uint16_t payload_length);
79
+ void send_command_(PMSX0003Command cmd, uint16_t data);
65
80
  uint16_t get_16_bit_uint_(uint8_t start_index);
66
81
 
67
82
  uint8_t data_[64];
@@ -92,9 +107,12 @@ class PMSX003Component : public uart::UARTDevice, public Component {
92
107
  sensor::Sensor *pm_particles_50um_sensor_{nullptr};
93
108
  sensor::Sensor *pm_particles_100um_sensor_{nullptr};
94
109
 
110
+ // Formaldehyde
111
+ sensor::Sensor *formaldehyde_sensor_{nullptr};
112
+
113
+ // Temperature and Humidity
95
114
  sensor::Sensor *temperature_sensor_{nullptr};
96
115
  sensor::Sensor *humidity_sensor_{nullptr};
97
- sensor::Sensor *formaldehyde_sensor_{nullptr};
98
116
  };
99
117
 
100
118
  } // namespace pmsx003