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