esphome 2025.8.4__py3-none-any.whl → 2025.9.0b1__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 (344) hide show
  1. esphome/__main__.py +36 -42
  2. esphome/components/absolute_humidity/absolute_humidity.cpp +3 -5
  3. esphome/components/adc/adc_sensor_esp32.cpp +29 -6
  4. esphome/components/ags10/ags10.cpp +3 -18
  5. esphome/components/ags10/ags10.h +2 -12
  6. esphome/components/aht10/aht10.cpp +3 -3
  7. esphome/components/airthings_ble/__init__.py +2 -2
  8. esphome/components/alarm_control_panel/__init__.py +2 -2
  9. esphome/components/am2315c/am2315c.cpp +1 -17
  10. esphome/components/am2315c/am2315c.h +2 -3
  11. esphome/components/api/__init__.py +2 -2
  12. esphome/components/api/api_connection.cpp +34 -23
  13. esphome/components/api/api_connection.h +20 -39
  14. esphome/components/api/api_frame_helper.cpp +25 -25
  15. esphome/components/api/api_frame_helper.h +3 -3
  16. esphome/components/api/api_frame_helper_noise.cpp +75 -40
  17. esphome/components/api/api_frame_helper_noise.h +3 -7
  18. esphome/components/api/api_frame_helper_plaintext.cpp +17 -4
  19. esphome/components/api/api_frame_helper_plaintext.h +1 -4
  20. esphome/components/api/api_pb2.cpp +20 -2
  21. esphome/components/api/api_pb2.h +146 -141
  22. esphome/components/api/api_pb2_dump.cpp +12 -1
  23. esphome/components/api/proto.cpp +33 -37
  24. esphome/components/async_tcp/__init__.py +2 -2
  25. esphome/components/atm90e26/sensor.py +2 -0
  26. esphome/components/atm90e32/sensor.py +4 -2
  27. esphome/components/audio_adc/__init__.py +2 -2
  28. esphome/components/audio_dac/__init__.py +2 -2
  29. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +1 -1
  30. esphome/components/bedjet/bedjet_hub.cpp +1 -1
  31. esphome/components/binary_sensor/__init__.py +2 -2
  32. esphome/components/binary_sensor/binary_sensor.cpp +13 -0
  33. esphome/components/binary_sensor/binary_sensor.h +4 -7
  34. esphome/components/bl0940/__init__.py +6 -1
  35. esphome/components/bl0940/bl0940.cpp +178 -41
  36. esphome/components/bl0940/bl0940.h +121 -76
  37. esphome/components/bl0940/button/__init__.py +27 -0
  38. esphome/components/bl0940/button/calibration_reset_button.cpp +20 -0
  39. esphome/components/bl0940/button/calibration_reset_button.h +19 -0
  40. esphome/components/bl0940/number/__init__.py +94 -0
  41. esphome/components/bl0940/number/calibration_number.cpp +29 -0
  42. esphome/components/bl0940/number/calibration_number.h +26 -0
  43. esphome/components/bl0940/sensor.py +151 -2
  44. esphome/components/bl0942/bl0942.cpp +1 -1
  45. esphome/components/ble_client/output/__init__.py +4 -4
  46. esphome/components/bluetooth_proxy/__init__.py +1 -1
  47. esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -1
  48. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +15 -7
  49. esphome/components/bluetooth_proxy/bluetooth_proxy.h +3 -2
  50. esphome/components/button/__init__.py +2 -2
  51. esphome/components/button/button.cpp +13 -0
  52. esphome/components/button/button.h +4 -7
  53. esphome/components/camera/buffer.h +18 -0
  54. esphome/components/camera/buffer_impl.cpp +20 -0
  55. esphome/components/camera/buffer_impl.h +26 -0
  56. esphome/components/camera/camera.h +43 -0
  57. esphome/components/camera/encoder.h +69 -0
  58. esphome/components/camera_encoder/__init__.py +62 -0
  59. esphome/components/camera_encoder/encoder_buffer_impl.cpp +23 -0
  60. esphome/components/camera_encoder/encoder_buffer_impl.h +25 -0
  61. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +82 -0
  62. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +39 -0
  63. esphome/components/captive_portal/__init__.py +2 -2
  64. esphome/components/captive_portal/captive_portal.cpp +35 -12
  65. esphome/components/captive_portal/captive_portal.h +3 -3
  66. esphome/components/ccs811/ccs811.cpp +3 -3
  67. esphome/components/climate/__init__.py +2 -2
  68. esphome/components/climate/climate.cpp +1 -1
  69. esphome/components/cover/__init__.py +5 -5
  70. esphome/components/cover/cover.cpp +1 -1
  71. esphome/components/cover/cover.h +2 -2
  72. esphome/components/dallas_temp/dallas_temp.cpp +2 -2
  73. esphome/components/datetime/__init__.py +2 -2
  74. esphome/components/datetime/date_entity.h +2 -2
  75. esphome/components/datetime/datetime_entity.h +2 -2
  76. esphome/components/datetime/time_entity.h +2 -2
  77. esphome/components/debug/debug_esp32.cpp +1 -1
  78. esphome/components/display/__init__.py +4 -4
  79. esphome/components/duty_time/duty_time_sensor.cpp +1 -1
  80. esphome/components/esp32/__init__.py +0 -5
  81. esphome/components/esp32/gpio.cpp +27 -23
  82. esphome/components/esp32/gpio.h +26 -11
  83. esphome/components/esp32/preferences.cpp +8 -4
  84. esphome/components/esp32_ble/__init__.py +7 -2
  85. esphome/components/esp32_ble_client/ble_client_base.cpp +7 -3
  86. esphome/components/esp32_ble_tracker/__init__.py +2 -2
  87. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +9 -44
  88. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -14
  89. esphome/components/esp8266/__init__.py +2 -2
  90. esphome/components/esp8266/core.cpp +2 -2
  91. esphome/components/esp8266/gpio.py +4 -4
  92. esphome/components/esp8266/preferences.cpp +30 -28
  93. esphome/components/esphome/ota/__init__.py +2 -2
  94. esphome/components/esphome/ota/ota_esphome.cpp +21 -19
  95. esphome/components/esphome/ota/ota_esphome.h +6 -5
  96. esphome/components/ethernet/__init__.py +7 -2
  97. esphome/components/ethernet/ethernet_component.cpp +1 -1
  98. esphome/components/event/__init__.py +2 -2
  99. esphome/components/event/event.h +4 -4
  100. esphome/components/fan/__init__.py +2 -2
  101. esphome/components/fan/fan.cpp +2 -1
  102. esphome/components/gdk101/gdk101.cpp +4 -4
  103. esphome/components/globals/__init__.py +2 -2
  104. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +19 -18
  105. esphome/components/gpio_expander/cached_gpio.h +36 -16
  106. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +5 -5
  107. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +1 -1
  108. esphome/components/haier/haier_base.cpp +1 -1
  109. esphome/components/haier/hon_climate.cpp +1 -1
  110. esphome/components/hlw8012/hlw8012.cpp +5 -5
  111. esphome/components/honeywellabp2_i2c/honeywellabp2.cpp +4 -4
  112. esphome/components/host/preferences.h +3 -2
  113. esphome/components/hte501/hte501.cpp +3 -21
  114. esphome/components/hte501/hte501.h +2 -3
  115. esphome/components/http_request/ota/__init__.py +2 -2
  116. esphome/components/i2c/__init__.py +2 -2
  117. esphome/components/i2c/i2c.cpp +13 -9
  118. esphome/components/i2c/i2c_bus.h +36 -6
  119. esphome/components/i2s_audio/__init__.py +8 -2
  120. esphome/components/i2s_audio/media_player/__init__.py +1 -1
  121. esphome/components/i2s_audio/microphone/__init__.py +1 -1
  122. esphome/components/i2s_audio/speaker/__init__.py +1 -1
  123. esphome/components/inkplate/__init__.py +1 -0
  124. esphome/components/inkplate/const.py +105 -0
  125. esphome/components/inkplate/display.py +238 -0
  126. esphome/components/{inkplate6 → inkplate}/inkplate.cpp +156 -74
  127. esphome/components/{inkplate6 → inkplate}/inkplate.h +28 -68
  128. esphome/components/inkplate6/__init__.py +0 -1
  129. esphome/components/inkplate6/display.py +2 -211
  130. esphome/components/integration/integration_sensor.cpp +1 -1
  131. esphome/components/json/__init__.py +2 -2
  132. esphome/components/lc709203f/lc709203f.cpp +4 -17
  133. esphome/components/lc709203f/lc709203f.h +2 -3
  134. esphome/components/ld2420/text_sensor/{text_sensor.cpp → ld2420_text_sensor.cpp} +1 -1
  135. esphome/components/ld2450/ld2450.cpp +1 -1
  136. esphome/components/libretiny/preferences.cpp +13 -5
  137. esphome/components/light/__init__.py +2 -2
  138. esphome/components/light/addressable_light_effect.h +7 -0
  139. esphome/components/light/base_light_effects.h +8 -0
  140. esphome/components/light/light_call.cpp +22 -20
  141. esphome/components/light/light_effect.cpp +36 -0
  142. esphome/components/light/light_effect.h +14 -0
  143. esphome/components/light/light_json_schema.cpp +9 -1
  144. esphome/components/light/light_state.cpp +2 -2
  145. esphome/components/light/light_state.h +38 -0
  146. esphome/components/lock/__init__.py +2 -2
  147. esphome/components/lock/lock.h +2 -2
  148. esphome/components/logger/__init__.py +2 -2
  149. esphome/components/logger/logger.cpp +25 -4
  150. esphome/components/logger/logger.h +1 -1
  151. esphome/components/logger/logger_esp32.cpp +16 -8
  152. esphome/components/logger/logger_esp8266.cpp +11 -3
  153. esphome/components/logger/logger_libretiny.cpp +13 -3
  154. esphome/components/logger/logger_rp2040.cpp +14 -3
  155. esphome/components/logger/logger_zephyr.cpp +15 -4
  156. esphome/components/lvgl/defines.py +1 -0
  157. esphome/components/lvgl/hello_world.py +96 -33
  158. esphome/components/lvgl/number/lvgl_number.h +1 -1
  159. esphome/components/lvgl/select/lvgl_select.h +1 -1
  160. esphome/components/lvgl/widgets/__init__.py +0 -1
  161. esphome/components/lvgl/widgets/spinbox.py +20 -11
  162. esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp +1 -1
  163. esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp +1 -1
  164. esphome/components/mapping/__init__.py +13 -5
  165. esphome/components/mapping/mapping.h +69 -0
  166. esphome/components/max17043/max17043.cpp +2 -2
  167. esphome/components/mcp23016/__init__.py +1 -0
  168. esphome/components/mcp23016/mcp23016.cpp +20 -5
  169. esphome/components/mcp23016/mcp23016.h +10 -4
  170. esphome/components/mcp23x08_base/mcp23x08_base.cpp +1 -1
  171. esphome/components/mcp23x17_base/mcp23x17_base.cpp +2 -2
  172. esphome/components/mdns/__init__.py +2 -2
  173. esphome/components/mdns/mdns_component.cpp +145 -54
  174. esphome/components/media_player/__init__.py +2 -2
  175. esphome/components/micro_wake_word/__init__.py +2 -2
  176. esphome/components/microphone/__init__.py +2 -2
  177. esphome/components/mipi/__init__.py +77 -33
  178. esphome/components/mipi_rgb/__init__.py +2 -0
  179. esphome/components/mipi_rgb/display.py +321 -0
  180. esphome/components/mipi_rgb/mipi_rgb.cpp +388 -0
  181. esphome/components/mipi_rgb/mipi_rgb.h +127 -0
  182. esphome/components/mipi_rgb/models/guition.py +24 -0
  183. esphome/components/mipi_rgb/models/lilygo.py +228 -0
  184. esphome/components/mipi_rgb/models/rpi.py +9 -0
  185. esphome/components/mipi_rgb/models/st7701s.py +214 -0
  186. esphome/components/mipi_rgb/models/waveshare.py +64 -0
  187. esphome/components/mipi_spi/models/jc.py +229 -0
  188. esphome/components/mlx90614/mlx90614.cpp +1 -16
  189. esphome/components/mlx90614/mlx90614.h +0 -1
  190. esphome/components/mqtt/__init__.py +2 -2
  191. esphome/components/mqtt/mqtt_sensor.cpp +7 -2
  192. esphome/components/ms5611/ms5611.cpp +7 -6
  193. esphome/components/network/__init__.py +2 -2
  194. esphome/components/nextion/nextion_upload.cpp +4 -1
  195. esphome/components/nrf52/__init__.py +49 -6
  196. esphome/components/nrf52/const.py +1 -0
  197. esphome/components/nrf52/dfu.cpp +51 -0
  198. esphome/components/nrf52/dfu.h +24 -0
  199. esphome/components/ntc/ntc.cpp +1 -1
  200. esphome/components/number/__init__.py +2 -2
  201. esphome/components/number/automation.cpp +1 -1
  202. esphome/components/number/number.cpp +21 -0
  203. esphome/components/number/number.h +4 -13
  204. esphome/components/opentherm/hub.h +6 -6
  205. esphome/components/opentherm/number/{number.cpp → opentherm_number.cpp} +2 -2
  206. esphome/components/opentherm/output/{output.cpp → opentherm_output.cpp} +1 -1
  207. esphome/components/opentherm/switch/{switch.cpp → opentherm_switch.cpp} +1 -1
  208. esphome/components/ota/__init__.py +2 -2
  209. esphome/components/pca6416a/__init__.py +1 -0
  210. esphome/components/pca6416a/pca6416a.cpp +20 -5
  211. esphome/components/pca6416a/pca6416a.h +12 -5
  212. esphome/components/pca9554/__init__.py +2 -1
  213. esphome/components/pca9554/pca9554.cpp +12 -18
  214. esphome/components/pca9554/pca9554.h +10 -9
  215. esphome/components/pcf8574/__init__.py +1 -0
  216. esphome/components/pcf8574/pcf8574.cpp +14 -5
  217. esphome/components/pcf8574/pcf8574.h +13 -6
  218. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +7 -7
  219. esphome/components/pipsolar/__init__.py +3 -3
  220. esphome/components/pipsolar/output/__init__.py +4 -4
  221. esphome/components/pulse_width/pulse_width.cpp +2 -2
  222. esphome/components/qmp6988/qmp6988.cpp +81 -126
  223. esphome/components/qmp6988/qmp6988.h +31 -37
  224. esphome/components/radon_eye_ble/__init__.py +2 -2
  225. esphome/components/remote_base/__init__.py +6 -8
  226. esphome/components/rotary_encoder/rotary_encoder.cpp +1 -1
  227. esphome/components/rp2040/__init__.py +2 -2
  228. esphome/components/runtime_stats/runtime_stats.cpp +10 -23
  229. esphome/components/runtime_stats/runtime_stats.h +4 -10
  230. esphome/components/safe_mode/__init__.py +2 -2
  231. esphome/components/safe_mode/safe_mode.cpp +33 -31
  232. esphome/components/script/script.cpp +6 -0
  233. esphome/components/script/script.h +19 -5
  234. esphome/components/sdm_meter/sensor.py +3 -1
  235. esphome/components/select/__init__.py +2 -2
  236. esphome/components/select/select.h +2 -2
  237. esphome/components/sen5x/sen5x.cpp +57 -55
  238. esphome/components/sen5x/sen5x.h +21 -15
  239. esphome/components/sen5x/sensor.py +67 -44
  240. esphome/components/sensirion_common/i2c_sensirion.cpp +18 -47
  241. esphome/components/sensirion_common/i2c_sensirion.h +39 -55
  242. esphome/components/sensor/__init__.py +2 -2
  243. esphome/components/sensor/automation.h +1 -1
  244. esphome/components/sensor/sensor.cpp +34 -6
  245. esphome/components/sensor/sensor.h +4 -21
  246. esphome/components/sgp30/sgp30.cpp +34 -35
  247. esphome/components/sgp30/sgp30.h +11 -10
  248. esphome/components/sgp4x/sgp4x.cpp +2 -2
  249. esphome/components/shelly_dimmer/light.py +7 -7
  250. esphome/components/sht4x/sht4x.cpp +1 -1
  251. esphome/components/sntp/sntp_component.cpp +36 -9
  252. esphome/components/sntp/sntp_component.h +7 -0
  253. esphome/components/sound_level/sound_level.cpp +1 -1
  254. esphome/components/speaker/__init__.py +2 -2
  255. esphome/components/speaker/media_player/__init__.py +2 -2
  256. esphome/components/speaker/media_player/speaker_media_player.cpp +1 -1
  257. esphome/components/spi/__init__.py +2 -2
  258. esphome/components/sprinkler/sprinkler.cpp +1 -1
  259. esphome/components/sps30/sps30.cpp +18 -23
  260. esphome/components/sps30/sps30.h +3 -3
  261. esphome/components/status_led/__init__.py +2 -2
  262. esphome/components/stepper/__init__.py +2 -2
  263. esphome/components/switch/__init__.py +2 -2
  264. esphome/components/switch/switch.cpp +5 -5
  265. esphome/components/sx1509/__init__.py +1 -1
  266. esphome/components/sx1509/sx1509.cpp +12 -7
  267. esphome/components/sx1509/sx1509.h +11 -4
  268. esphome/components/tca9555/tca9555.cpp +5 -5
  269. esphome/components/tee501/tee501.cpp +2 -21
  270. esphome/components/tee501/tee501.h +2 -4
  271. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +1 -1
  272. esphome/components/template/datetime/template_date.cpp +1 -1
  273. esphome/components/template/datetime/template_datetime.cpp +2 -2
  274. esphome/components/template/datetime/template_time.cpp +1 -1
  275. esphome/components/template/number/template_number.cpp +1 -1
  276. esphome/components/template/select/template_select.cpp +1 -1
  277. esphome/components/template/text/template_text.cpp +1 -1
  278. esphome/components/text/__init__.py +2 -2
  279. esphome/components/text/text.h +2 -2
  280. esphome/components/text_sensor/__init__.py +2 -2
  281. esphome/components/text_sensor/text_sensor.h +4 -4
  282. esphome/components/thermostat/climate.py +11 -7
  283. esphome/components/thermostat/thermostat_climate.cpp +237 -206
  284. esphome/components/thermostat/thermostat_climate.h +52 -41
  285. esphome/components/time/__init__.py +2 -2
  286. esphome/components/tmp1075/tmp1075.cpp +1 -1
  287. esphome/components/total_daily_energy/total_daily_energy.cpp +1 -1
  288. esphome/components/touchscreen/__init__.py +2 -2
  289. esphome/components/tuya/number/tuya_number.cpp +1 -1
  290. esphome/components/udp/udp_component.cpp +3 -3
  291. esphome/components/ufire_ec/ufire_ec.cpp +4 -4
  292. esphome/components/ufire_ise/ufire_ise.cpp +4 -4
  293. esphome/components/update/__init__.py +2 -2
  294. esphome/components/usb_uart/usb_uart.cpp +1 -1
  295. esphome/components/valve/__init__.py +5 -5
  296. esphome/components/valve/valve.cpp +1 -1
  297. esphome/components/valve/valve.h +2 -2
  298. esphome/components/wake_on_lan/wake_on_lan.cpp +2 -2
  299. esphome/components/waveshare_epaper/waveshare_213v3.cpp +1 -1
  300. esphome/components/web_server/__init__.py +2 -2
  301. esphome/components/web_server/ota/__init__.py +2 -2
  302. esphome/components/web_server/ota/ota_web_server.cpp +11 -0
  303. esphome/components/web_server/web_server.cpp +58 -12
  304. esphome/components/web_server_base/__init__.py +2 -2
  305. esphome/components/wifi/__init__.py +5 -5
  306. esphome/components/wifi/wifi_component.cpp +3 -3
  307. esphome/components/wifi/wifi_component_esp_idf.cpp +2 -0
  308. esphome/config_validation.py +2 -2
  309. esphome/const.py +2 -1
  310. esphome/core/__init__.py +1 -0
  311. esphome/core/application.cpp +89 -51
  312. esphome/core/application.h +1 -0
  313. esphome/core/component.cpp +41 -19
  314. esphome/core/component.h +17 -13
  315. esphome/core/config.py +7 -7
  316. esphome/core/defines.h +4 -0
  317. esphome/core/entity_base.cpp +22 -8
  318. esphome/core/entity_base.h +43 -0
  319. esphome/core/helpers.cpp +26 -13
  320. esphome/core/helpers.h +4 -3
  321. esphome/core/ring_buffer.cpp +6 -2
  322. esphome/core/ring_buffer.h +2 -1
  323. esphome/core/scheduler.cpp +175 -94
  324. esphome/core/scheduler.h +66 -35
  325. esphome/core/time.cpp +6 -20
  326. esphome/coroutine.py +80 -3
  327. esphome/cpp_generator.py +13 -0
  328. esphome/cpp_helpers.py +2 -2
  329. esphome/dashboard/web_server.py +67 -10
  330. esphome/espota2.py +13 -6
  331. esphome/helpers.py +68 -83
  332. esphome/resolver.py +67 -0
  333. esphome/util.py +9 -6
  334. esphome/wizard.py +39 -26
  335. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/METADATA +9 -9
  336. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/RECORD +344 -313
  337. /esphome/components/ld2420/text_sensor/{text_sensor.h → ld2420_text_sensor.h} +0 -0
  338. /esphome/components/opentherm/number/{number.h → opentherm_number.h} +0 -0
  339. /esphome/components/opentherm/output/{output.h → opentherm_output.h} +0 -0
  340. /esphome/components/opentherm/switch/{switch.h → opentherm_switch.h} +0 -0
  341. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/WHEEL +0 -0
  342. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/entry_points.txt +0 -0
  343. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/licenses/LICENSE +0 -0
  344. {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/top_level.txt +0 -0
@@ -65,26 +65,47 @@ ACCELERATION_MODES = {
65
65
  "high": RhtAccelerationMode.HIGH_ACCELERATION,
66
66
  }
67
67
 
68
- GAS_SENSOR = cv.Schema(
69
- {
70
- cv.Optional(CONF_ALGORITHM_TUNING): cv.Schema(
71
- {
72
- cv.Optional(CONF_INDEX_OFFSET, default=100): cv.int_range(1, 250),
73
- cv.Optional(CONF_LEARNING_TIME_OFFSET_HOURS, default=12): cv.int_range(
74
- 1, 1000
75
- ),
76
- cv.Optional(CONF_LEARNING_TIME_GAIN_HOURS, default=12): cv.int_range(
77
- 1, 1000
78
- ),
79
- cv.Optional(
80
- CONF_GATING_MAX_DURATION_MINUTES, default=720
81
- ): cv.int_range(0, 3000),
82
- cv.Optional(CONF_STD_INITIAL, default=50): cv.int_,
83
- cv.Optional(CONF_GAIN_FACTOR, default=230): cv.int_range(1, 1000),
84
- }
85
- )
86
- }
87
- )
68
+
69
+ def _gas_sensor(
70
+ *,
71
+ index_offset: int,
72
+ learning_time_offset: int,
73
+ learning_time_gain: int,
74
+ gating_max_duration: int,
75
+ std_initial: int,
76
+ gain_factor: int,
77
+ ) -> cv.Schema:
78
+ return sensor.sensor_schema(
79
+ icon=ICON_RADIATOR,
80
+ accuracy_decimals=0,
81
+ device_class=DEVICE_CLASS_AQI,
82
+ state_class=STATE_CLASS_MEASUREMENT,
83
+ ).extend(
84
+ {
85
+ cv.Optional(CONF_ALGORITHM_TUNING): cv.Schema(
86
+ {
87
+ cv.Optional(CONF_INDEX_OFFSET, default=index_offset): cv.int_range(
88
+ 1, 250
89
+ ),
90
+ cv.Optional(
91
+ CONF_LEARNING_TIME_OFFSET_HOURS, default=learning_time_offset
92
+ ): cv.int_range(1, 1000),
93
+ cv.Optional(
94
+ CONF_LEARNING_TIME_GAIN_HOURS, default=learning_time_gain
95
+ ): cv.int_range(1, 1000),
96
+ cv.Optional(
97
+ CONF_GATING_MAX_DURATION_MINUTES, default=gating_max_duration
98
+ ): cv.int_range(0, 3000),
99
+ cv.Optional(CONF_STD_INITIAL, default=std_initial): cv.int_range(
100
+ 10, 5000
101
+ ),
102
+ cv.Optional(CONF_GAIN_FACTOR, default=gain_factor): cv.int_range(
103
+ 1, 1000
104
+ ),
105
+ }
106
+ )
107
+ }
108
+ )
88
109
 
89
110
 
90
111
  def float_previously_pct(value):
@@ -127,18 +148,22 @@ CONFIG_SCHEMA = (
127
148
  state_class=STATE_CLASS_MEASUREMENT,
128
149
  ),
129
150
  cv.Optional(CONF_AUTO_CLEANING_INTERVAL): cv.update_interval,
130
- cv.Optional(CONF_VOC): sensor.sensor_schema(
131
- icon=ICON_RADIATOR,
132
- accuracy_decimals=0,
133
- device_class=DEVICE_CLASS_AQI,
134
- state_class=STATE_CLASS_MEASUREMENT,
135
- ).extend(GAS_SENSOR),
136
- cv.Optional(CONF_NOX): sensor.sensor_schema(
137
- icon=ICON_RADIATOR,
138
- accuracy_decimals=0,
139
- device_class=DEVICE_CLASS_AQI,
140
- state_class=STATE_CLASS_MEASUREMENT,
141
- ).extend(GAS_SENSOR),
151
+ cv.Optional(CONF_VOC): _gas_sensor(
152
+ index_offset=100,
153
+ learning_time_offset=12,
154
+ learning_time_gain=12,
155
+ gating_max_duration=180,
156
+ std_initial=50,
157
+ gain_factor=230,
158
+ ),
159
+ cv.Optional(CONF_NOX): _gas_sensor(
160
+ index_offset=1,
161
+ learning_time_offset=12,
162
+ learning_time_gain=12,
163
+ gating_max_duration=720,
164
+ std_initial=50,
165
+ gain_factor=230,
166
+ ),
142
167
  cv.Optional(CONF_STORE_BASELINE, default=True): cv.boolean,
143
168
  cv.Optional(CONF_VOC_BASELINE): cv.hex_uint16_t,
144
169
  cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
@@ -194,16 +219,15 @@ async def to_code(config):
194
219
  await i2c.register_i2c_device(var, config)
195
220
 
196
221
  for key, funcName in SETTING_MAP.items():
197
- if key in config:
198
- cg.add(getattr(var, funcName)(config[key]))
222
+ if cfg := config.get(key):
223
+ cg.add(getattr(var, funcName)(cfg))
199
224
 
200
225
  for key, funcName in SENSOR_MAP.items():
201
- if key in config:
202
- sens = await sensor.new_sensor(config[key])
226
+ if cfg := config.get(key):
227
+ sens = await sensor.new_sensor(cfg)
203
228
  cg.add(getattr(var, funcName)(sens))
204
229
 
205
- if CONF_VOC in config and CONF_ALGORITHM_TUNING in config[CONF_VOC]:
206
- cfg = config[CONF_VOC][CONF_ALGORITHM_TUNING]
230
+ if cfg := config.get(CONF_VOC, {}).get(CONF_ALGORITHM_TUNING):
207
231
  cg.add(
208
232
  var.set_voc_algorithm_tuning(
209
233
  cfg[CONF_INDEX_OFFSET],
@@ -214,8 +238,7 @@ async def to_code(config):
214
238
  cfg[CONF_GAIN_FACTOR],
215
239
  )
216
240
  )
217
- if CONF_NOX in config and CONF_ALGORITHM_TUNING in config[CONF_NOX]:
218
- cfg = config[CONF_NOX][CONF_ALGORITHM_TUNING]
241
+ if cfg := config.get(CONF_NOX, {}).get(CONF_ALGORITHM_TUNING):
219
242
  cg.add(
220
243
  var.set_nox_algorithm_tuning(
221
244
  cfg[CONF_INDEX_OFFSET],
@@ -225,12 +248,12 @@ async def to_code(config):
225
248
  cfg[CONF_GAIN_FACTOR],
226
249
  )
227
250
  )
228
- if CONF_TEMPERATURE_COMPENSATION in config:
251
+ if cfg := config.get(CONF_TEMPERATURE_COMPENSATION):
229
252
  cg.add(
230
253
  var.set_temperature_compensation(
231
- config[CONF_TEMPERATURE_COMPENSATION][CONF_OFFSET],
232
- config[CONF_TEMPERATURE_COMPENSATION][CONF_NORMALIZED_OFFSET_SLOPE],
233
- config[CONF_TEMPERATURE_COMPENSATION][CONF_TIME_CONSTANT],
254
+ cfg[CONF_OFFSET],
255
+ cfg[CONF_NORMALIZED_OFFSET_SLOPE],
256
+ cfg[CONF_TIME_CONSTANT],
234
257
  )
235
258
  )
236
259
 
@@ -11,21 +11,22 @@ static const char *const TAG = "sensirion_i2c";
11
11
  // To avoid memory allocations for small writes a stack buffer is used
12
12
  static const size_t BUFFER_STACK_SIZE = 16;
13
13
 
14
- bool SensirionI2CDevice::read_data(uint16_t *data, uint8_t len) {
14
+ bool SensirionI2CDevice::read_data(uint16_t *data, const uint8_t len) {
15
15
  const uint8_t num_bytes = len * 3;
16
- std::vector<uint8_t> buf(num_bytes);
16
+ uint8_t buf[num_bytes];
17
17
 
18
- last_error_ = this->read(buf.data(), num_bytes);
19
- if (last_error_ != i2c::ERROR_OK) {
18
+ this->last_error_ = this->read(buf, num_bytes);
19
+ if (this->last_error_ != i2c::ERROR_OK) {
20
20
  return false;
21
21
  }
22
22
 
23
23
  for (uint8_t i = 0; i < len; i++) {
24
24
  const uint8_t j = 3 * i;
25
- uint8_t crc = sht_crc_(buf[j], buf[j + 1]);
25
+ // Use MSB first since Sensirion devices use CRC-8 with MSB first
26
+ uint8_t crc = crc8(&buf[j], 2, 0xFF, CRC_POLYNOMIAL, true);
26
27
  if (crc != buf[j + 2]) {
27
- ESP_LOGE(TAG, "CRC8 Checksum invalid at pos %d! 0x%02X != 0x%02X", i, buf[j + 2], crc);
28
- last_error_ = i2c::ERROR_CRC;
28
+ ESP_LOGE(TAG, "CRC invalid @ %d! 0x%02X != 0x%02X", i, buf[j + 2], crc);
29
+ this->last_error_ = i2c::ERROR_CRC;
29
30
  return false;
30
31
  }
31
32
  data[i] = encode_uint16(buf[j], buf[j + 1]);
@@ -34,10 +35,10 @@ bool SensirionI2CDevice::read_data(uint16_t *data, uint8_t len) {
34
35
  }
35
36
  /***
36
37
  * write command with parameters and insert crc
37
- * use stack array for less than 4 parameters. Most sensirion i2c commands have less parameters
38
+ * use stack array for less than 4 parameters. Most Sensirion I2C commands have less parameters
38
39
  */
39
40
  bool SensirionI2CDevice::write_command_(uint16_t command, CommandLen command_len, const uint16_t *data,
40
- uint8_t data_len) {
41
+ const uint8_t data_len) {
41
42
  uint8_t temp_stack[BUFFER_STACK_SIZE];
42
43
  std::unique_ptr<uint8_t[]> temp_heap;
43
44
  uint8_t *temp;
@@ -74,56 +75,26 @@ bool SensirionI2CDevice::write_command_(uint16_t command, CommandLen command_len
74
75
  temp[raw_idx++] = data[i] & 0xFF;
75
76
  temp[raw_idx++] = data[i] >> 8;
76
77
  #endif
77
- temp[raw_idx++] = sht_crc_(data[i]);
78
+ // Use MSB first since Sensirion devices use CRC-8 with MSB first
79
+ temp[raw_idx++] = crc8(&temp[raw_idx - 2], 2, 0xFF, CRC_POLYNOMIAL, true);
78
80
  }
79
- last_error_ = this->write(temp, raw_idx);
80
- return last_error_ == i2c::ERROR_OK;
81
+ this->last_error_ = this->write(temp, raw_idx);
82
+ return this->last_error_ == i2c::ERROR_OK;
81
83
  }
82
84
 
83
- bool SensirionI2CDevice::get_register_(uint16_t reg, CommandLen command_len, uint16_t *data, uint8_t len,
84
- uint8_t delay_ms) {
85
+ bool SensirionI2CDevice::get_register_(uint16_t reg, CommandLen command_len, uint16_t *data, const uint8_t len,
86
+ const uint8_t delay_ms) {
85
87
  if (!this->write_command_(reg, command_len, nullptr, 0)) {
86
- ESP_LOGE(TAG, "Failed to write i2c register=0x%X (%d) err=%d,", reg, command_len, this->last_error_);
88
+ ESP_LOGE(TAG, "Write failed: reg=0x%X (%d) err=%d,", reg, command_len, this->last_error_);
87
89
  return false;
88
90
  }
89
91
  delay(delay_ms);
90
92
  bool result = this->read_data(data, len);
91
93
  if (!result) {
92
- ESP_LOGE(TAG, "Failed to read data from register=0x%X err=%d,", reg, this->last_error_);
94
+ ESP_LOGE(TAG, "Read failed: reg=0x%X err=%d,", reg, this->last_error_);
93
95
  }
94
96
  return result;
95
97
  }
96
98
 
97
- // The 8-bit CRC checksum is transmitted after each data word
98
- uint8_t SensirionI2CDevice::sht_crc_(uint16_t data) {
99
- uint8_t bit;
100
- uint8_t crc = 0xFF;
101
- #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
102
- crc ^= data >> 8;
103
- #else
104
- crc ^= data & 0xFF;
105
- #endif
106
- for (bit = 8; bit > 0; --bit) {
107
- if (crc & 0x80) {
108
- crc = (crc << 1) ^ crc_polynomial_;
109
- } else {
110
- crc = (crc << 1);
111
- }
112
- }
113
- #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
114
- crc ^= data & 0xFF;
115
- #else
116
- crc ^= data >> 8;
117
- #endif
118
- for (bit = 8; bit > 0; --bit) {
119
- if (crc & 0x80) {
120
- crc = (crc << 1) ^ crc_polynomial_;
121
- } else {
122
- crc = (crc << 1);
123
- }
124
- }
125
- return crc;
126
- }
127
-
128
99
  } // namespace sensirion_common
129
100
  } // namespace esphome
@@ -8,90 +8,92 @@ namespace esphome {
8
8
  namespace sensirion_common {
9
9
 
10
10
  /**
11
- * Implementation of a i2c functions for Sensirion sensors
12
- * Sensirion data requires crc checking.
11
+ * Implementation of I2C functions for Sensirion sensors
12
+ * Sensirion data requires CRC checking.
13
13
  * Each 16 bit word is/must be followed 8 bit CRC code
14
- * (Applies to read and write - note the i2c command code doesn't need a CRC)
14
+ * (Applies to read and write - note the I2C command code doesn't need a CRC)
15
15
  * Format:
16
16
  * | 16 Bit Command Code | 16 bit Data word 1 | CRC of DW 1 | 16 bit Data word 1 | CRC of DW 2 | ..
17
17
  */
18
+ static const uint8_t CRC_POLYNOMIAL = 0x31; // default for Sensirion
19
+
18
20
  class SensirionI2CDevice : public i2c::I2CDevice {
19
21
  public:
20
22
  enum CommandLen : uint8_t { ADDR_8_BIT = 1, ADDR_16_BIT = 2 };
21
23
 
22
- /** Read data words from i2c device.
23
- * handles crc check used by Sensirion sensors
24
+ /** Read data words from I2C device.
25
+ * handles CRC check used by Sensirion sensors
24
26
  * @param data pointer to raw result
25
27
  * @param len number of words to read
26
28
  * @return true if reading succeeded
27
29
  */
28
30
  bool read_data(uint16_t *data, uint8_t len);
29
31
 
30
- /** Read 1 data word from i2c device.
32
+ /** Read 1 data word from I2C device.
31
33
  * @param data reference to raw result
32
34
  * @return true if reading succeeded
33
35
  */
34
36
  bool read_data(uint16_t &data) { return this->read_data(&data, 1); }
35
37
 
36
- /** get data words from i2c register.
37
- * handles crc check used by Sensirion sensors
38
- * @param i2c register
38
+ /** get data words from I2C register.
39
+ * handles CRC check used by Sensirion sensors
40
+ * @param I2C register
39
41
  * @param data pointer to raw result
40
42
  * @param len number of words to read
41
- * @param delay milliseconds to to wait between sending the i2c command and reading the result
43
+ * @param delay milliseconds to to wait between sending the I2C command and reading the result
42
44
  * @return true if reading succeeded
43
45
  */
44
46
  bool get_register(uint16_t command, uint16_t *data, uint8_t len, uint8_t delay = 0) {
45
47
  return get_register_(command, ADDR_16_BIT, data, len, delay);
46
48
  }
47
- /** Read 1 data word from 16 bit i2c register.
48
- * @param i2c register
49
+ /** Read 1 data word from 16 bit I2C register.
50
+ * @param I2C register
49
51
  * @param data reference to raw result
50
- * @param delay milliseconds to to wait between sending the i2c command and reading the result
52
+ * @param delay milliseconds to to wait between sending the I2C command and reading the result
51
53
  * @return true if reading succeeded
52
54
  */
53
55
  bool get_register(uint16_t i2c_register, uint16_t &data, uint8_t delay = 0) {
54
56
  return this->get_register_(i2c_register, ADDR_16_BIT, &data, 1, delay);
55
57
  }
56
58
 
57
- /** get data words from i2c register.
58
- * handles crc check used by Sensirion sensors
59
- * @param i2c register
59
+ /** get data words from I2C register.
60
+ * handles CRC check used by Sensirion sensors
61
+ * @param I2C register
60
62
  * @param data pointer to raw result
61
63
  * @param len number of words to read
62
- * @param delay milliseconds to to wait between sending the i2c command and reading the result
64
+ * @param delay milliseconds to to wait between sending the I2C command and reading the result
63
65
  * @return true if reading succeeded
64
66
  */
65
67
  bool get_8bit_register(uint8_t i2c_register, uint16_t *data, uint8_t len, uint8_t delay = 0) {
66
68
  return get_register_(i2c_register, ADDR_8_BIT, data, len, delay);
67
69
  }
68
70
 
69
- /** Read 1 data word from 8 bit i2c register.
70
- * @param i2c register
71
+ /** Read 1 data word from 8 bit I2C register.
72
+ * @param I2C register
71
73
  * @param data reference to raw result
72
- * @param delay milliseconds to to wait between sending the i2c command and reading the result
74
+ * @param delay milliseconds to to wait between sending the I2C command and reading the result
73
75
  * @return true if reading succeeded
74
76
  */
75
77
  bool get_8bit_register(uint8_t i2c_register, uint16_t &data, uint8_t delay = 0) {
76
78
  return this->get_register_(i2c_register, ADDR_8_BIT, &data, 1, delay);
77
79
  }
78
80
 
79
- /** Write a command to the i2c device.
80
- * @param command i2c command to send
81
+ /** Write a command to the I2C device.
82
+ * @param command I2C command to send
81
83
  * @return true if reading succeeded
82
84
  */
83
85
  template<class T> bool write_command(T i2c_register) { return write_command(i2c_register, nullptr, 0); }
84
86
 
85
- /** Write a command and one data word to the i2c device .
86
- * @param command i2c command to send
87
- * @param data argument for the i2c command
87
+ /** Write a command and one data word to the I2C device .
88
+ * @param command I2C command to send
89
+ * @param data argument for the I2C command
88
90
  * @return true if reading succeeded
89
91
  */
90
92
  template<class T> bool write_command(T i2c_register, uint16_t data) { return write_command(i2c_register, &data, 1); }
91
93
 
92
94
  /** Write a command with arguments as words
93
- * @param i2c_register i2c command to send - an be uint8_t or uint16_t
94
- * @param data vector<uint16> arguments for the i2c command
95
+ * @param i2c_register I2C command to send - an be uint8_t or uint16_t
96
+ * @param data vector<uint16> arguments for the I2C command
95
97
  * @return true if reading succeeded
96
98
  */
97
99
  template<class T> bool write_command(T i2c_register, const std::vector<uint16_t> &data) {
@@ -99,57 +101,39 @@ class SensirionI2CDevice : public i2c::I2CDevice {
99
101
  }
100
102
 
101
103
  /** Write a command with arguments as words
102
- * @param i2c_register i2c command to send - an be uint8_t or uint16_t
103
- * @param data arguments for the i2c command
104
+ * @param i2c_register I2C command to send - an be uint8_t or uint16_t
105
+ * @param data arguments for the I2C command
104
106
  * @param len number of arguments (words)
105
107
  * @return true if reading succeeded
106
108
  */
107
109
  template<class T> bool write_command(T i2c_register, const uint16_t *data, uint8_t len) {
108
110
  // limit to 8 or 16 bit only
109
- static_assert(sizeof(i2c_register) == 1 || sizeof(i2c_register) == 2,
110
- "only 8 or 16 bit command types are supported.");
111
+ static_assert(sizeof(i2c_register) == 1 || sizeof(i2c_register) == 2, "Only 8 or 16 bit command types supported");
111
112
  return write_command_(i2c_register, CommandLen(sizeof(T)), data, len);
112
113
  }
113
114
 
114
115
  protected:
115
- uint8_t crc_polynomial_{0x31u}; // default for sensirion
116
116
  /** Write a command with arguments as words
117
- * @param command i2c command to send can be uint8_t or uint16_t
117
+ * @param command I2C command to send can be uint8_t or uint16_t
118
118
  * @param command_len either 1 for short 8 bit command or 2 for 16 bit command codes
119
- * @param data arguments for the i2c command
119
+ * @param data arguments for the I2C command
120
120
  * @param data_len number of arguments (words)
121
121
  * @return true if reading succeeded
122
122
  */
123
123
  bool write_command_(uint16_t command, CommandLen command_len, const uint16_t *data, uint8_t data_len);
124
124
 
125
- /** get data words from i2c register.
126
- * handles crc check used by Sensirion sensors
127
- * @param i2c register
125
+ /** get data words from I2C register.
126
+ * handles CRC check used by Sensirion sensors
127
+ * @param I2C register
128
128
  * @param command_len either 1 for short 8 bit command or 2 for 16 bit command codes
129
129
  * @param data pointer to raw result
130
130
  * @param len number of words to read
131
- * @param delay milliseconds to to wait between sending the i2c command and reading the result
131
+ * @param delay milliseconds to to wait between sending the I2C command and reading the result
132
132
  * @return true if reading succeeded
133
133
  */
134
134
  bool get_register_(uint16_t reg, CommandLen command_len, uint16_t *data, uint8_t len, uint8_t delay);
135
135
 
136
- /** 8-bit CRC checksum that is transmitted after each data word for read and write operation
137
- * @param command i2c command to send
138
- * @param data data word for which the crc8 checksum is calculated
139
- * @param len number of arguments (words)
140
- * @return 8 Bit CRC
141
- */
142
- uint8_t sht_crc_(uint16_t data);
143
-
144
- /** 8-bit CRC checksum that is transmitted after each data word for read and write operation
145
- * @param command i2c command to send
146
- * @param data1 high byte of data word
147
- * @param data2 low byte of data word
148
- * @return 8 Bit CRC
149
- */
150
- uint8_t sht_crc_(uint8_t data1, uint8_t data2) { return sht_crc_(encode_uint16(data1, data2)); }
151
-
152
- /** last error code from i2c operation
136
+ /** last error code from I2C operation
153
137
  */
154
138
  i2c::ErrorCode last_error_;
155
139
  };
@@ -101,7 +101,7 @@ from esphome.const import (
101
101
  DEVICE_CLASS_WIND_SPEED,
102
102
  ENTITY_CATEGORY_CONFIG,
103
103
  )
104
- from esphome.core import CORE, coroutine_with_priority
104
+ from esphome.core import CORE, CoroPriority, coroutine_with_priority
105
105
  from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
106
106
  from esphome.cpp_generator import MockObjClass
107
107
  from esphome.util import Registry
@@ -1142,6 +1142,6 @@ def _lstsq(a, b):
1142
1142
  return _mat_dot(_mat_dot(x, a_t), b)
1143
1143
 
1144
1144
 
1145
- @coroutine_with_priority(100.0)
1145
+ @coroutine_with_priority(CoroPriority.CORE)
1146
1146
  async def to_code(config):
1147
1147
  cg.add_global(sensor_ns.using)
@@ -40,7 +40,7 @@ class ValueRangeTrigger : public Trigger<float>, public Component {
40
40
  template<typename V> void set_max(V max) { this->max_ = max; }
41
41
 
42
42
  void setup() override {
43
- this->rtc_ = global_preferences->make_preference<bool>(this->parent_->get_object_id_hash());
43
+ this->rtc_ = global_preferences->make_preference<bool>(this->parent_->get_preference_hash());
44
44
  bool initial_state;
45
45
  if (this->rtc_.load(&initial_state)) {
46
46
  this->previous_in_range_ = initial_state;
@@ -6,17 +6,45 @@ namespace sensor {
6
6
 
7
7
  static const char *const TAG = "sensor";
8
8
 
9
- std::string state_class_to_string(StateClass state_class) {
9
+ // Function implementation of LOG_SENSOR macro to reduce code size
10
+ void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *obj) {
11
+ if (obj == nullptr) {
12
+ return;
13
+ }
14
+
15
+ ESP_LOGCONFIG(tag,
16
+ "%s%s '%s'\n"
17
+ "%s State Class: '%s'\n"
18
+ "%s Unit of Measurement: '%s'\n"
19
+ "%s Accuracy Decimals: %d",
20
+ prefix, type, obj->get_name().c_str(), prefix,
21
+ LOG_STR_ARG(state_class_to_string(obj->get_state_class())), prefix,
22
+ obj->get_unit_of_measurement_ref().c_str(), prefix, obj->get_accuracy_decimals());
23
+
24
+ if (!obj->get_device_class_ref().empty()) {
25
+ ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj->get_device_class_ref().c_str());
26
+ }
27
+
28
+ if (!obj->get_icon_ref().empty()) {
29
+ ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj->get_icon_ref().c_str());
30
+ }
31
+
32
+ if (obj->get_force_update()) {
33
+ ESP_LOGV(tag, "%s Force Update: YES", prefix);
34
+ }
35
+ }
36
+
37
+ const LogString *state_class_to_string(StateClass state_class) {
10
38
  switch (state_class) {
11
39
  case STATE_CLASS_MEASUREMENT:
12
- return "measurement";
40
+ return LOG_STR("measurement");
13
41
  case STATE_CLASS_TOTAL_INCREASING:
14
- return "total_increasing";
42
+ return LOG_STR("total_increasing");
15
43
  case STATE_CLASS_TOTAL:
16
- return "total";
44
+ return LOG_STR("total");
17
45
  case STATE_CLASS_NONE:
18
46
  default:
19
- return "";
47
+ return LOG_STR("");
20
48
  }
21
49
  }
22
50
 
@@ -101,7 +129,7 @@ void Sensor::internal_send_state_to_frontend(float state) {
101
129
  this->set_has_state(true);
102
130
  this->state = state;
103
131
  ESP_LOGD(TAG, "'%s': Sending state %.5f %s with %d decimals of accuracy", this->get_name().c_str(), state,
104
- this->get_unit_of_measurement().c_str(), this->get_accuracy_decimals());
132
+ this->get_unit_of_measurement_ref().c_str(), this->get_accuracy_decimals());
105
133
  this->callback_.call(state);
106
134
  }
107
135
 
@@ -12,26 +12,9 @@
12
12
  namespace esphome {
13
13
  namespace sensor {
14
14
 
15
- #define LOG_SENSOR(prefix, type, obj) \
16
- if ((obj) != nullptr) { \
17
- ESP_LOGCONFIG(TAG, \
18
- "%s%s '%s'\n" \
19
- "%s State Class: '%s'\n" \
20
- "%s Unit of Measurement: '%s'\n" \
21
- "%s Accuracy Decimals: %d", \
22
- prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str(), prefix, \
23
- state_class_to_string((obj)->get_state_class()).c_str(), prefix, \
24
- (obj)->get_unit_of_measurement().c_str(), prefix, (obj)->get_accuracy_decimals()); \
25
- if (!(obj)->get_device_class().empty()) { \
26
- ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class().c_str()); \
27
- } \
28
- if (!(obj)->get_icon().empty()) { \
29
- ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon().c_str()); \
30
- } \
31
- if ((obj)->get_force_update()) { \
32
- ESP_LOGV(TAG, "%s Force Update: YES", prefix); \
33
- } \
34
- }
15
+ void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *obj);
16
+
17
+ #define LOG_SENSOR(prefix, type, obj) log_sensor(TAG, prefix, LOG_STR_LITERAL(type), obj)
35
18
 
36
19
  #define SUB_SENSOR(name) \
37
20
  protected: \
@@ -50,7 +33,7 @@ enum StateClass : uint8_t {
50
33
  STATE_CLASS_TOTAL = 3,
51
34
  };
52
35
 
53
- std::string state_class_to_string(StateClass state_class);
36
+ const LogString *state_class_to_string(StateClass state_class);
54
37
 
55
38
  /** Base-class for all sensors.
56
39
  *