esphome 2025.8.4__py3-none-any.whl → 2025.9.0__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 (369) hide show
  1. esphome/__main__.py +177 -105
  2. esphome/components/absolute_humidity/absolute_humidity.cpp +3 -5
  3. esphome/components/adc/__init__.py +1 -26
  4. esphome/components/adc/adc_sensor_esp32.cpp +29 -6
  5. esphome/components/adc/sensor.py +20 -0
  6. esphome/components/ade7880/ade7880.cpp +1 -1
  7. esphome/components/ags10/ags10.cpp +3 -18
  8. esphome/components/ags10/ags10.h +2 -12
  9. esphome/components/aht10/aht10.cpp +3 -3
  10. esphome/components/airthings_ble/__init__.py +2 -2
  11. esphome/components/alarm_control_panel/__init__.py +2 -2
  12. esphome/components/am2315c/am2315c.cpp +1 -17
  13. esphome/components/am2315c/am2315c.h +2 -3
  14. esphome/components/api/__init__.py +2 -2
  15. esphome/components/api/api_connection.cpp +38 -34
  16. esphome/components/api/api_connection.h +20 -40
  17. esphome/components/api/api_frame_helper.cpp +25 -25
  18. esphome/components/api/api_frame_helper.h +3 -3
  19. esphome/components/api/api_frame_helper_noise.cpp +75 -40
  20. esphome/components/api/api_frame_helper_noise.h +3 -7
  21. esphome/components/api/api_frame_helper_plaintext.cpp +17 -4
  22. esphome/components/api/api_frame_helper_plaintext.h +1 -4
  23. esphome/components/api/api_pb2.cpp +12 -2
  24. esphome/components/api/api_pb2.h +144 -143
  25. esphome/components/api/api_pb2_dump.cpp +6 -1
  26. esphome/components/api/api_pb2_service.cpp +0 -14
  27. esphome/components/api/api_pb2_service.h +1 -3
  28. esphome/components/api/client.py +5 -3
  29. esphome/components/api/proto.cpp +33 -37
  30. esphome/components/async_tcp/__init__.py +2 -2
  31. esphome/components/atm90e26/sensor.py +2 -0
  32. esphome/components/atm90e32/sensor.py +4 -2
  33. esphome/components/audio_adc/__init__.py +2 -2
  34. esphome/components/audio_dac/__init__.py +2 -2
  35. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +1 -1
  36. esphome/components/bedjet/bedjet_hub.cpp +1 -1
  37. esphome/components/binary_sensor/__init__.py +2 -2
  38. esphome/components/binary_sensor/binary_sensor.cpp +13 -0
  39. esphome/components/binary_sensor/binary_sensor.h +4 -7
  40. esphome/components/bl0940/__init__.py +6 -1
  41. esphome/components/bl0940/bl0940.cpp +178 -41
  42. esphome/components/bl0940/bl0940.h +121 -76
  43. esphome/components/bl0940/button/__init__.py +27 -0
  44. esphome/components/bl0940/button/calibration_reset_button.cpp +20 -0
  45. esphome/components/bl0940/button/calibration_reset_button.h +19 -0
  46. esphome/components/bl0940/number/__init__.py +94 -0
  47. esphome/components/bl0940/number/calibration_number.cpp +29 -0
  48. esphome/components/bl0940/number/calibration_number.h +26 -0
  49. esphome/components/bl0940/sensor.py +151 -2
  50. esphome/components/bl0942/bl0942.cpp +1 -1
  51. esphome/components/ble_client/output/__init__.py +4 -4
  52. esphome/components/bluetooth_proxy/__init__.py +1 -1
  53. esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -1
  54. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +15 -7
  55. esphome/components/bluetooth_proxy/bluetooth_proxy.h +6 -3
  56. esphome/components/button/__init__.py +2 -2
  57. esphome/components/button/button.cpp +13 -0
  58. esphome/components/button/button.h +4 -7
  59. esphome/components/camera/buffer.h +18 -0
  60. esphome/components/camera/buffer_impl.cpp +20 -0
  61. esphome/components/camera/buffer_impl.h +26 -0
  62. esphome/components/camera/camera.h +43 -0
  63. esphome/components/camera/encoder.h +69 -0
  64. esphome/components/camera_encoder/__init__.py +62 -0
  65. esphome/components/camera_encoder/encoder_buffer_impl.cpp +23 -0
  66. esphome/components/camera_encoder/encoder_buffer_impl.h +25 -0
  67. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +82 -0
  68. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +39 -0
  69. esphome/components/captive_portal/__init__.py +2 -2
  70. esphome/components/captive_portal/captive_index.h +77 -97
  71. esphome/components/captive_portal/captive_portal.cpp +35 -12
  72. esphome/components/captive_portal/captive_portal.h +3 -3
  73. esphome/components/ccs811/ccs811.cpp +3 -3
  74. esphome/components/climate/__init__.py +2 -2
  75. esphome/components/climate/climate.cpp +1 -1
  76. esphome/components/cover/__init__.py +5 -5
  77. esphome/components/cover/cover.cpp +1 -1
  78. esphome/components/cover/cover.h +2 -2
  79. esphome/components/dallas_temp/dallas_temp.cpp +2 -2
  80. esphome/components/datetime/__init__.py +2 -2
  81. esphome/components/datetime/date_entity.h +2 -2
  82. esphome/components/datetime/datetime_entity.h +2 -2
  83. esphome/components/datetime/time_entity.h +2 -2
  84. esphome/components/debug/debug_esp32.cpp +1 -1
  85. esphome/components/display/__init__.py +4 -4
  86. esphome/components/duty_time/duty_time_sensor.cpp +1 -1
  87. esphome/components/esp32/__init__.py +0 -5
  88. esphome/components/esp32/gpio.cpp +27 -23
  89. esphome/components/esp32/gpio.h +26 -11
  90. esphome/components/esp32/preferences.cpp +8 -4
  91. esphome/components/esp32_ble/__init__.py +7 -2
  92. esphome/components/esp32_ble/ble_uuid.cpp +30 -9
  93. esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +4 -3
  94. esphome/components/esp32_ble_client/ble_client_base.cpp +7 -3
  95. esphome/components/esp32_ble_client/ble_client_base.h +8 -5
  96. esphome/components/esp32_ble_tracker/__init__.py +2 -2
  97. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +11 -47
  98. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -14
  99. esphome/components/esp8266/__init__.py +2 -2
  100. esphome/components/esp8266/core.cpp +2 -2
  101. esphome/components/esp8266/gpio.py +4 -4
  102. esphome/components/esp8266/preferences.cpp +30 -28
  103. esphome/components/esphome/ota/__init__.py +2 -2
  104. esphome/components/esphome/ota/ota_esphome.cpp +21 -19
  105. esphome/components/esphome/ota/ota_esphome.h +6 -5
  106. esphome/components/ethernet/__init__.py +18 -2
  107. esphome/components/ethernet/ethernet_component.cpp +53 -3
  108. esphome/components/ethernet/ethernet_component.h +4 -0
  109. esphome/components/event/__init__.py +2 -2
  110. esphome/components/event/event.h +4 -4
  111. esphome/components/factory_reset/button/factory_reset_button.cpp +18 -1
  112. esphome/components/factory_reset/button/factory_reset_button.h +6 -1
  113. esphome/components/factory_reset/switch/factory_reset_switch.cpp +18 -1
  114. esphome/components/factory_reset/switch/factory_reset_switch.h +5 -1
  115. esphome/components/fan/__init__.py +2 -2
  116. esphome/components/fan/fan.cpp +2 -1
  117. esphome/components/gdk101/gdk101.cpp +4 -4
  118. esphome/components/globals/__init__.py +2 -2
  119. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +19 -18
  120. esphome/components/gpio_expander/cached_gpio.h +36 -16
  121. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +5 -5
  122. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +1 -1
  123. esphome/components/haier/haier_base.cpp +1 -1
  124. esphome/components/haier/hon_climate.cpp +1 -1
  125. esphome/components/hlw8012/hlw8012.cpp +5 -5
  126. esphome/components/honeywellabp2_i2c/honeywellabp2.cpp +4 -4
  127. esphome/components/host/preferences.h +3 -2
  128. esphome/components/hte501/hte501.cpp +3 -21
  129. esphome/components/hte501/hte501.h +2 -3
  130. esphome/components/http_request/ota/__init__.py +2 -2
  131. esphome/components/i2c/__init__.py +2 -2
  132. esphome/components/i2c/i2c.cpp +13 -9
  133. esphome/components/i2c/i2c_bus.h +36 -6
  134. esphome/components/i2s_audio/__init__.py +8 -2
  135. esphome/components/i2s_audio/media_player/__init__.py +1 -1
  136. esphome/components/i2s_audio/microphone/__init__.py +1 -1
  137. esphome/components/i2s_audio/speaker/__init__.py +1 -1
  138. esphome/components/ina2xx_base/__init__.py +4 -2
  139. esphome/components/inkplate/__init__.py +1 -0
  140. esphome/components/inkplate/const.py +105 -0
  141. esphome/components/inkplate/display.py +238 -0
  142. esphome/components/{inkplate6 → inkplate}/inkplate.cpp +156 -74
  143. esphome/components/{inkplate6 → inkplate}/inkplate.h +28 -68
  144. esphome/components/inkplate6/__init__.py +0 -1
  145. esphome/components/inkplate6/display.py +2 -211
  146. esphome/components/integration/integration_sensor.cpp +1 -1
  147. esphome/components/json/__init__.py +2 -2
  148. esphome/components/lc709203f/lc709203f.cpp +4 -17
  149. esphome/components/lc709203f/lc709203f.h +2 -3
  150. esphome/components/ld2420/text_sensor/{text_sensor.cpp → ld2420_text_sensor.cpp} +1 -1
  151. esphome/components/ld2450/ld2450.cpp +1 -1
  152. esphome/components/libretiny/preferences.cpp +13 -5
  153. esphome/components/light/__init__.py +2 -2
  154. esphome/components/light/addressable_light_effect.h +7 -0
  155. esphome/components/light/base_light_effects.h +8 -0
  156. esphome/components/light/light_call.cpp +22 -20
  157. esphome/components/light/light_effect.cpp +36 -0
  158. esphome/components/light/light_effect.h +14 -0
  159. esphome/components/light/light_json_schema.cpp +9 -1
  160. esphome/components/light/light_state.cpp +2 -2
  161. esphome/components/light/light_state.h +38 -0
  162. esphome/components/lock/__init__.py +2 -2
  163. esphome/components/lock/lock.h +2 -2
  164. esphome/components/logger/__init__.py +2 -2
  165. esphome/components/logger/logger.cpp +25 -4
  166. esphome/components/logger/logger.h +1 -1
  167. esphome/components/logger/logger_esp32.cpp +16 -8
  168. esphome/components/logger/logger_esp8266.cpp +11 -3
  169. esphome/components/logger/logger_libretiny.cpp +13 -3
  170. esphome/components/logger/logger_rp2040.cpp +14 -3
  171. esphome/components/logger/logger_zephyr.cpp +15 -4
  172. esphome/components/lvgl/defines.py +1 -0
  173. esphome/components/lvgl/hello_world.py +96 -33
  174. esphome/components/lvgl/number/lvgl_number.h +1 -1
  175. esphome/components/lvgl/select/lvgl_select.h +1 -1
  176. esphome/components/lvgl/widgets/__init__.py +0 -1
  177. esphome/components/lvgl/widgets/spinbox.py +20 -11
  178. esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp +1 -1
  179. esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp +1 -1
  180. esphome/components/mapping/__init__.py +13 -5
  181. esphome/components/mapping/mapping.h +69 -0
  182. esphome/components/max17043/max17043.cpp +2 -2
  183. esphome/components/mcp23016/__init__.py +1 -0
  184. esphome/components/mcp23016/mcp23016.cpp +20 -5
  185. esphome/components/mcp23016/mcp23016.h +10 -4
  186. esphome/components/mcp23x08_base/mcp23x08_base.cpp +1 -1
  187. esphome/components/mcp23x17_base/mcp23x17_base.cpp +2 -2
  188. esphome/components/md5/md5.cpp +3 -2
  189. esphome/components/mdns/__init__.py +2 -2
  190. esphome/components/mdns/mdns_component.cpp +145 -54
  191. esphome/components/media_player/__init__.py +2 -2
  192. esphome/components/micro_wake_word/__init__.py +2 -2
  193. esphome/components/microphone/__init__.py +2 -2
  194. esphome/components/mipi/__init__.py +77 -33
  195. esphome/components/mipi_rgb/__init__.py +2 -0
  196. esphome/components/mipi_rgb/display.py +321 -0
  197. esphome/components/mipi_rgb/mipi_rgb.cpp +388 -0
  198. esphome/components/mipi_rgb/mipi_rgb.h +127 -0
  199. esphome/components/mipi_rgb/models/guition.py +24 -0
  200. esphome/components/mipi_rgb/models/lilygo.py +228 -0
  201. esphome/components/mipi_rgb/models/rpi.py +9 -0
  202. esphome/components/mipi_rgb/models/st7701s.py +214 -0
  203. esphome/components/mipi_rgb/models/waveshare.py +64 -0
  204. esphome/components/mipi_spi/models/jc.py +229 -0
  205. esphome/components/mlx90614/mlx90614.cpp +1 -16
  206. esphome/components/mlx90614/mlx90614.h +0 -1
  207. esphome/components/mqtt/__init__.py +2 -2
  208. esphome/components/mqtt/mqtt_client.cpp +1 -1
  209. esphome/components/mqtt/mqtt_sensor.cpp +7 -2
  210. esphome/components/ms5611/ms5611.cpp +7 -6
  211. esphome/components/network/__init__.py +2 -2
  212. esphome/components/nextion/nextion_upload.cpp +4 -1
  213. esphome/components/nrf52/__init__.py +49 -6
  214. esphome/components/nrf52/const.py +1 -0
  215. esphome/components/nrf52/dfu.cpp +51 -0
  216. esphome/components/nrf52/dfu.h +24 -0
  217. esphome/components/ntc/ntc.cpp +1 -1
  218. esphome/components/number/__init__.py +2 -2
  219. esphome/components/number/automation.cpp +1 -1
  220. esphome/components/number/number.cpp +21 -0
  221. esphome/components/number/number.h +4 -13
  222. esphome/components/opentherm/hub.h +6 -6
  223. esphome/components/opentherm/number/{number.cpp → opentherm_number.cpp} +2 -2
  224. esphome/components/opentherm/output/{output.cpp → opentherm_output.cpp} +1 -1
  225. esphome/components/opentherm/switch/{switch.cpp → opentherm_switch.cpp} +1 -1
  226. esphome/components/openthread/openthread.cpp +41 -7
  227. esphome/components/openthread/openthread.h +11 -0
  228. esphome/components/ota/__init__.py +2 -2
  229. esphome/components/pca6416a/__init__.py +1 -0
  230. esphome/components/pca6416a/pca6416a.cpp +20 -5
  231. esphome/components/pca6416a/pca6416a.h +12 -5
  232. esphome/components/pca9554/__init__.py +2 -1
  233. esphome/components/pca9554/pca9554.cpp +12 -18
  234. esphome/components/pca9554/pca9554.h +10 -9
  235. esphome/components/pcf8574/__init__.py +1 -0
  236. esphome/components/pcf8574/pcf8574.cpp +14 -5
  237. esphome/components/pcf8574/pcf8574.h +13 -6
  238. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +7 -7
  239. esphome/components/pipsolar/__init__.py +3 -3
  240. esphome/components/pipsolar/output/__init__.py +4 -4
  241. esphome/components/pulse_width/pulse_width.cpp +2 -2
  242. esphome/components/qmp6988/qmp6988.cpp +81 -126
  243. esphome/components/qmp6988/qmp6988.h +31 -37
  244. esphome/components/radon_eye_ble/__init__.py +2 -2
  245. esphome/components/remote_base/__init__.py +6 -8
  246. esphome/components/rotary_encoder/rotary_encoder.cpp +1 -1
  247. esphome/components/rp2040/__init__.py +2 -2
  248. esphome/components/runtime_stats/runtime_stats.cpp +10 -23
  249. esphome/components/runtime_stats/runtime_stats.h +4 -10
  250. esphome/components/safe_mode/__init__.py +2 -2
  251. esphome/components/safe_mode/safe_mode.cpp +33 -31
  252. esphome/components/script/script.cpp +6 -0
  253. esphome/components/script/script.h +19 -5
  254. esphome/components/sdm_meter/sensor.py +3 -1
  255. esphome/components/select/__init__.py +2 -2
  256. esphome/components/select/select.cpp +3 -3
  257. esphome/components/select/select.h +2 -2
  258. esphome/components/select/select_call.cpp +1 -1
  259. esphome/components/sen5x/sen5x.cpp +57 -55
  260. esphome/components/sen5x/sen5x.h +21 -15
  261. esphome/components/sen5x/sensor.py +67 -44
  262. esphome/components/sensirion_common/i2c_sensirion.cpp +18 -47
  263. esphome/components/sensirion_common/i2c_sensirion.h +39 -55
  264. esphome/components/sensor/__init__.py +2 -2
  265. esphome/components/sensor/automation.h +1 -1
  266. esphome/components/sensor/sensor.cpp +34 -6
  267. esphome/components/sensor/sensor.h +4 -21
  268. esphome/components/sgp30/sgp30.cpp +34 -35
  269. esphome/components/sgp30/sgp30.h +11 -10
  270. esphome/components/sgp4x/sgp4x.cpp +2 -2
  271. esphome/components/shelly_dimmer/light.py +7 -7
  272. esphome/components/sht4x/sht4x.cpp +1 -1
  273. esphome/components/sntp/sntp_component.cpp +36 -9
  274. esphome/components/sntp/sntp_component.h +7 -0
  275. esphome/components/sound_level/sound_level.cpp +1 -1
  276. esphome/components/speaker/__init__.py +2 -2
  277. esphome/components/speaker/media_player/__init__.py +2 -2
  278. esphome/components/speaker/media_player/speaker_media_player.cpp +1 -1
  279. esphome/components/spi/__init__.py +2 -2
  280. esphome/components/sprinkler/sprinkler.cpp +1 -1
  281. esphome/components/sps30/sps30.cpp +18 -23
  282. esphome/components/sps30/sps30.h +3 -3
  283. esphome/components/status_led/__init__.py +2 -2
  284. esphome/components/stepper/__init__.py +2 -2
  285. esphome/components/switch/__init__.py +2 -2
  286. esphome/components/switch/switch.cpp +5 -5
  287. esphome/components/sx1509/__init__.py +1 -1
  288. esphome/components/sx1509/sx1509.cpp +12 -7
  289. esphome/components/sx1509/sx1509.h +11 -4
  290. esphome/components/tca9555/tca9555.cpp +5 -5
  291. esphome/components/tee501/tee501.cpp +2 -21
  292. esphome/components/tee501/tee501.h +2 -4
  293. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +1 -1
  294. esphome/components/template/datetime/template_date.cpp +1 -1
  295. esphome/components/template/datetime/template_datetime.cpp +2 -2
  296. esphome/components/template/datetime/template_time.cpp +1 -1
  297. esphome/components/template/number/template_number.cpp +1 -1
  298. esphome/components/template/select/template_select.cpp +1 -1
  299. esphome/components/template/text/template_text.cpp +1 -1
  300. esphome/components/text/__init__.py +2 -2
  301. esphome/components/text/text.h +2 -2
  302. esphome/components/text_sensor/__init__.py +2 -2
  303. esphome/components/text_sensor/text_sensor.h +4 -4
  304. esphome/components/thermostat/climate.py +11 -7
  305. esphome/components/thermostat/thermostat_climate.cpp +237 -206
  306. esphome/components/thermostat/thermostat_climate.h +52 -41
  307. esphome/components/time/__init__.py +2 -2
  308. esphome/components/tmp1075/tmp1075.cpp +1 -1
  309. esphome/components/total_daily_energy/total_daily_energy.cpp +1 -1
  310. esphome/components/touchscreen/__init__.py +2 -2
  311. esphome/components/tuya/number/tuya_number.cpp +1 -1
  312. esphome/components/udp/udp_component.cpp +3 -3
  313. esphome/components/ufire_ec/ufire_ec.cpp +4 -4
  314. esphome/components/ufire_ise/ufire_ise.cpp +4 -4
  315. esphome/components/update/__init__.py +2 -2
  316. esphome/components/usb_uart/usb_uart.cpp +1 -1
  317. esphome/components/valve/__init__.py +5 -5
  318. esphome/components/valve/valve.cpp +1 -1
  319. esphome/components/valve/valve.h +2 -2
  320. esphome/components/wake_on_lan/wake_on_lan.cpp +2 -2
  321. esphome/components/waveshare_epaper/waveshare_213v3.cpp +1 -1
  322. esphome/components/web_server/__init__.py +2 -2
  323. esphome/components/web_server/ota/__init__.py +2 -2
  324. esphome/components/web_server/ota/ota_web_server.cpp +11 -0
  325. esphome/components/web_server/server_index_v2.h +149 -149
  326. esphome/components/web_server/web_server.cpp +58 -12
  327. esphome/components/web_server_base/__init__.py +2 -2
  328. esphome/components/wifi/__init__.py +5 -5
  329. esphome/components/wifi/wifi_component.cpp +4 -4
  330. esphome/components/wifi/wifi_component_esp_idf.cpp +2 -0
  331. esphome/components/wifi_info/wifi_info_text_sensor.h +3 -2
  332. esphome/config_validation.py +2 -2
  333. esphome/const.py +3 -1
  334. esphome/core/__init__.py +1 -0
  335. esphome/core/application.cpp +89 -51
  336. esphome/core/application.h +1 -0
  337. esphome/core/component.cpp +41 -19
  338. esphome/core/component.h +17 -13
  339. esphome/core/config.py +7 -7
  340. esphome/core/defines.h +5 -0
  341. esphome/core/entity_base.cpp +22 -8
  342. esphome/core/entity_base.h +43 -0
  343. esphome/core/helpers.cpp +34 -20
  344. esphome/core/helpers.h +33 -3
  345. esphome/core/ring_buffer.cpp +6 -2
  346. esphome/core/ring_buffer.h +2 -1
  347. esphome/core/scheduler.cpp +178 -97
  348. esphome/core/scheduler.h +67 -36
  349. esphome/core/time.cpp +6 -20
  350. esphome/coroutine.py +80 -3
  351. esphome/cpp_generator.py +13 -0
  352. esphome/cpp_helpers.py +2 -2
  353. esphome/dashboard/web_server.py +69 -15
  354. esphome/espota2.py +13 -6
  355. esphome/helpers.py +68 -83
  356. esphome/resolver.py +67 -0
  357. esphome/util.py +9 -6
  358. esphome/wizard.py +81 -34
  359. esphome/writer.py +13 -0
  360. {esphome-2025.8.4.dist-info → esphome-2025.9.0.dist-info}/METADATA +9 -9
  361. {esphome-2025.8.4.dist-info → esphome-2025.9.0.dist-info}/RECORD +369 -338
  362. /esphome/components/ld2420/text_sensor/{text_sensor.h → ld2420_text_sensor.h} +0 -0
  363. /esphome/components/opentherm/number/{number.h → opentherm_number.h} +0 -0
  364. /esphome/components/opentherm/output/{output.h → opentherm_output.h} +0 -0
  365. /esphome/components/opentherm/switch/{switch.h → opentherm_switch.h} +0 -0
  366. {esphome-2025.8.4.dist-info → esphome-2025.9.0.dist-info}/WHEEL +0 -0
  367. {esphome-2025.8.4.dist-info → esphome-2025.9.0.dist-info}/entry_points.txt +0 -0
  368. {esphome-2025.8.4.dist-info → esphome-2025.9.0.dist-info}/licenses/LICENSE +0 -0
  369. {esphome-2025.8.4.dist-info → esphome-2025.9.0.dist-info}/top_level.txt +0 -0
esphome/__main__.py CHANGED
@@ -15,9 +15,11 @@ import argcomplete
15
15
 
16
16
  from esphome import const, writer, yaml_util
17
17
  import esphome.codegen as cg
18
+ from esphome.components.mqtt import CONF_DISCOVER_IP
18
19
  from esphome.config import iter_component_configs, read_config, strip_default_ids
19
20
  from esphome.const import (
20
21
  ALLOWED_NAME_CHARS,
22
+ CONF_API,
21
23
  CONF_BAUD_RATE,
22
24
  CONF_BROKER,
23
25
  CONF_DEASSERT_RTS_DTR,
@@ -43,6 +45,7 @@ from esphome.const import (
43
45
  SECRETS_FILES,
44
46
  )
45
47
  from esphome.core import CORE, EsphomeError, coroutine
48
+ from esphome.enum import StrEnum
46
49
  from esphome.helpers import get_bool_env, indent, is_ip_address
47
50
  from esphome.log import AnsiFore, color, setup_log
48
51
  from esphome.types import ConfigType
@@ -106,13 +109,15 @@ def choose_prompt(options, purpose: str = None):
106
109
  return options[opt - 1][1]
107
110
 
108
111
 
112
+ class Purpose(StrEnum):
113
+ UPLOADING = "uploading"
114
+ LOGGING = "logging"
115
+
116
+
109
117
  def choose_upload_log_host(
110
118
  default: list[str] | str | None,
111
119
  check_default: str | None,
112
- show_ota: bool,
113
- show_mqtt: bool,
114
- show_api: bool,
115
- purpose: str | None = None,
120
+ purpose: Purpose,
116
121
  ) -> list[str]:
117
122
  # Convert to list for uniform handling
118
123
  defaults = [default] if isinstance(default, str) else default or []
@@ -132,13 +137,30 @@ def choose_upload_log_host(
132
137
  ]
133
138
  resolved.append(choose_prompt(options, purpose=purpose))
134
139
  elif device == "OTA":
135
- if CORE.address and (
136
- (show_ota and "ota" in CORE.config)
137
- or (show_api and "api" in CORE.config)
140
+ # ensure IP adresses are used first
141
+ if is_ip_address(CORE.address) and (
142
+ (purpose == Purpose.LOGGING and has_api())
143
+ or (purpose == Purpose.UPLOADING and has_ota())
138
144
  ):
139
145
  resolved.append(CORE.address)
140
- elif show_mqtt and has_mqtt_logging():
141
- resolved.append("MQTT")
146
+
147
+ if purpose == Purpose.LOGGING:
148
+ if has_api() and has_mqtt_ip_lookup():
149
+ resolved.append("MQTTIP")
150
+
151
+ if has_mqtt_logging():
152
+ resolved.append("MQTT")
153
+
154
+ if has_api() and has_non_ip_address():
155
+ resolved.append(CORE.address)
156
+
157
+ elif purpose == Purpose.UPLOADING:
158
+ if has_ota() and has_mqtt_ip_lookup():
159
+ resolved.append("MQTTIP")
160
+
161
+ if has_ota() and has_non_ip_address():
162
+ resolved.append(CORE.address)
163
+
142
164
  else:
143
165
  resolved.append(device)
144
166
  if not resolved:
@@ -149,39 +171,111 @@ def choose_upload_log_host(
149
171
  options = [
150
172
  (f"{port.path} ({port.description})", port.path) for port in get_serial_ports()
151
173
  ]
152
- if (show_ota and "ota" in CORE.config) or (show_api and "api" in CORE.config):
153
- options.append((f"Over The Air ({CORE.address})", CORE.address))
154
- if show_mqtt and has_mqtt_logging():
155
- mqtt_config = CORE.config[CONF_MQTT]
156
- options.append((f"MQTT ({mqtt_config[CONF_BROKER]})", "MQTT"))
174
+
175
+ if purpose == Purpose.LOGGING:
176
+ if has_mqtt_logging():
177
+ mqtt_config = CORE.config[CONF_MQTT]
178
+ options.append((f"MQTT ({mqtt_config[CONF_BROKER]})", "MQTT"))
179
+
180
+ if has_api():
181
+ if has_resolvable_address():
182
+ options.append((f"Over The Air ({CORE.address})", CORE.address))
183
+ if has_mqtt_ip_lookup():
184
+ options.append(("Over The Air (MQTT IP lookup)", "MQTTIP"))
185
+
186
+ elif purpose == Purpose.UPLOADING and has_ota():
187
+ if has_resolvable_address():
188
+ options.append((f"Over The Air ({CORE.address})", CORE.address))
189
+ if has_mqtt_ip_lookup():
190
+ options.append(("Over The Air (MQTT IP lookup)", "MQTTIP"))
157
191
 
158
192
  if check_default is not None and check_default in [opt[1] for opt in options]:
159
193
  return [check_default]
160
194
  return [choose_prompt(options, purpose=purpose)]
161
195
 
162
196
 
163
- def mqtt_logging_enabled(mqtt_config):
197
+ def has_mqtt_logging() -> bool:
198
+ """Check if MQTT logging is available."""
199
+ if CONF_MQTT not in CORE.config:
200
+ return False
201
+
202
+ mqtt_config = CORE.config[CONF_MQTT]
203
+
204
+ # enabled by default
205
+ if CONF_LOG_TOPIC not in mqtt_config:
206
+ return True
207
+
164
208
  log_topic = mqtt_config[CONF_LOG_TOPIC]
165
209
  if log_topic is None:
166
210
  return False
211
+
167
212
  if CONF_TOPIC not in log_topic:
168
213
  return False
169
- return log_topic.get(CONF_LEVEL, None) != "NONE"
170
214
 
215
+ return log_topic[CONF_LEVEL] != "NONE"
171
216
 
172
- def has_mqtt_logging() -> bool:
173
- """Check if MQTT logging is available."""
174
- return (mqtt_config := CORE.config.get(CONF_MQTT)) and mqtt_logging_enabled(
175
- mqtt_config
176
- )
217
+
218
+ def has_mqtt() -> bool:
219
+ """Check if MQTT is available."""
220
+ return CONF_MQTT in CORE.config
221
+
222
+
223
+ def has_api() -> bool:
224
+ """Check if API is available."""
225
+ return CONF_API in CORE.config
226
+
227
+
228
+ def has_ota() -> bool:
229
+ """Check if OTA is available."""
230
+ return CONF_OTA in CORE.config
231
+
232
+
233
+ def has_mqtt_ip_lookup() -> bool:
234
+ """Check if MQTT is available and IP lookup is supported."""
235
+ if CONF_MQTT not in CORE.config:
236
+ return False
237
+ # Default Enabled
238
+ if CONF_DISCOVER_IP not in CORE.config[CONF_MQTT]:
239
+ return True
240
+ return CORE.config[CONF_MQTT][CONF_DISCOVER_IP]
241
+
242
+
243
+ def has_mdns() -> bool:
244
+ """Check if MDNS is available."""
245
+ return CONF_MDNS not in CORE.config or not CORE.config[CONF_MDNS][CONF_DISABLED]
246
+
247
+
248
+ def has_non_ip_address() -> bool:
249
+ """Check if CORE.address is set and is not an IP address."""
250
+ return CORE.address is not None and not is_ip_address(CORE.address)
251
+
252
+
253
+ def has_ip_address() -> bool:
254
+ """Check if CORE.address is a valid IP address."""
255
+ return CORE.address is not None and is_ip_address(CORE.address)
256
+
257
+
258
+ def has_resolvable_address() -> bool:
259
+ """Check if CORE.address is resolvable (via mDNS or is an IP address)."""
260
+ return has_mdns() or has_ip_address()
261
+
262
+
263
+ def mqtt_get_ip(config: ConfigType, username: str, password: str, client_id: str):
264
+ from esphome import mqtt
265
+
266
+ return mqtt.get_esphome_device_ip(config, username, password, client_id)
267
+
268
+
269
+ _PORT_TO_PORT_TYPE = {
270
+ "MQTT": "MQTT",
271
+ "MQTTIP": "MQTTIP",
272
+ }
177
273
 
178
274
 
179
275
  def get_port_type(port: str) -> str:
180
276
  if port.startswith("/") or port.startswith("COM"):
181
277
  return "SERIAL"
182
- if port == "MQTT":
183
- return "MQTT"
184
- return "NETWORK"
278
+ return _PORT_TO_PORT_TYPE.get(port, "NETWORK")
185
279
 
186
280
 
187
281
  def run_miniterm(config: ConfigType, port: str, args) -> int:
@@ -226,7 +320,9 @@ def run_miniterm(config: ConfigType, port: str, args) -> int:
226
320
  .replace(b"\n", b"")
227
321
  .decode("utf8", "backslashreplace")
228
322
  )
229
- time_str = datetime.now().time().strftime("[%H:%M:%S]")
323
+ time_ = datetime.now()
324
+ nanoseconds = time_.microsecond // 1000
325
+ time_str = f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}.{nanoseconds:03}]"
230
326
  safe_print(parser.parse_line(line, time_str))
231
327
 
232
328
  backtrace_state = platformio_api.process_stacktrace(
@@ -396,27 +492,29 @@ def check_permissions(port: str):
396
492
  )
397
493
 
398
494
 
399
- def upload_program(config: ConfigType, args: ArgsProtocol, host: str) -> int | str:
495
+ def upload_program(
496
+ config: ConfigType, args: ArgsProtocol, devices: list[str]
497
+ ) -> tuple[int, str | None]:
498
+ host = devices[0]
400
499
  try:
401
500
  module = importlib.import_module("esphome.components." + CORE.target_platform)
402
501
  if getattr(module, "upload_program")(config, args, host):
403
- return 0
502
+ return 0, host
404
503
  except AttributeError:
405
504
  pass
406
505
 
407
506
  if get_port_type(host) == "SERIAL":
408
507
  check_permissions(host)
508
+
509
+ exit_code = 1
409
510
  if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266):
410
511
  file = getattr(args, "file", None)
411
- return upload_using_esptool(config, host, file, args.upload_speed)
412
-
413
- if CORE.target_platform in (PLATFORM_RP2040):
414
- return upload_using_platformio(config, host)
415
-
416
- if CORE.is_libretiny:
417
- return upload_using_platformio(config, host)
512
+ exit_code = upload_using_esptool(config, host, file, args.upload_speed)
513
+ elif CORE.target_platform == PLATFORM_RP2040 or CORE.is_libretiny:
514
+ exit_code = upload_using_platformio(config, host)
515
+ # else: Unknown target platform, exit_code remains 1
418
516
 
419
- return 1 # Unknown target platform
517
+ return exit_code, host if exit_code == 0 else None
420
518
 
421
519
  ota_conf = {}
422
520
  for ota_item in config.get(CONF_OTA, []):
@@ -433,31 +531,23 @@ def upload_program(config: ConfigType, args: ArgsProtocol, host: str) -> int | s
433
531
 
434
532
  remote_port = int(ota_conf[CONF_PORT])
435
533
  password = ota_conf.get(CONF_PASSWORD, "")
534
+ binary = args.file if getattr(args, "file", None) is not None else CORE.firmware_bin
436
535
 
437
- # Check if we should use MQTT for address resolution
438
- # This happens when no device was specified, or the current host is "MQTT"/"OTA"
439
- devices: list[str] = args.device or []
440
- if (
441
- CONF_MQTT in config # pylint: disable=too-many-boolean-expressions
442
- and (not devices or host in ("MQTT", "OTA"))
443
- and (
444
- ((config[CONF_MDNS][CONF_DISABLED]) and not is_ip_address(CORE.address))
445
- or get_port_type(host) == "MQTT"
446
- )
447
- ):
448
- from esphome import mqtt
449
-
450
- host = mqtt.get_esphome_device_ip(
451
- config, args.username, args.password, args.client_id
452
- )
453
-
454
- if getattr(args, "file", None) is not None:
455
- return espota2.run_ota(host, remote_port, password, args.file)
536
+ # MQTT address resolution
537
+ if get_port_type(host) in ("MQTT", "MQTTIP"):
538
+ devices = mqtt_get_ip(config, args.username, args.password, args.client_id)
456
539
 
457
- return espota2.run_ota(host, remote_port, password, CORE.firmware_bin)
540
+ return espota2.run_ota(devices, remote_port, password, binary)
458
541
 
459
542
 
460
543
  def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int | None:
544
+ try:
545
+ module = importlib.import_module("esphome.components." + CORE.target_platform)
546
+ if getattr(module, "show_logs")(config, args, devices):
547
+ return 0
548
+ except AttributeError:
549
+ pass
550
+
461
551
  if "logger" not in config:
462
552
  raise EsphomeError("Logger is not configured!")
463
553
 
@@ -466,20 +556,28 @@ def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int
466
556
  if get_port_type(port) == "SERIAL":
467
557
  check_permissions(port)
468
558
  return run_miniterm(config, port, args)
469
- if get_port_type(port) == "NETWORK" and "api" in config:
470
- addresses_to_use = devices
471
- if config[CONF_MDNS][CONF_DISABLED] and CONF_MQTT in config:
472
- from esphome import mqtt
473
559
 
474
- mqtt_address = mqtt.get_esphome_device_ip(
560
+ port_type = get_port_type(port)
561
+
562
+ # Check if we should use API for logging
563
+ if has_api():
564
+ addresses_to_use: list[str] | None = None
565
+
566
+ if port_type == "NETWORK" and (has_mdns() or is_ip_address(port)):
567
+ addresses_to_use = devices
568
+ elif port_type in ("NETWORK", "MQTT", "MQTTIP") and has_mqtt_ip_lookup():
569
+ # Only use MQTT IP lookup if the first condition didn't match
570
+ # (for MQTT/MQTTIP types, or for NETWORK when mdns/ip check fails)
571
+ addresses_to_use = mqtt_get_ip(
475
572
  config, args.username, args.password, args.client_id
476
- )[0]
477
- addresses_to_use = [mqtt_address]
573
+ )
574
+
575
+ if addresses_to_use is not None:
576
+ from esphome.components.api.client import run_logs
478
577
 
479
- from esphome.components.api.client import run_logs
578
+ return run_logs(config, addresses_to_use)
480
579
 
481
- return run_logs(config, addresses_to_use)
482
- if get_port_type(port) in ("NETWORK", "MQTT") and "mqtt" in config:
580
+ if port_type in ("NETWORK", "MQTT") and has_mqtt_logging():
483
581
  from esphome import mqtt
484
582
 
485
583
  return mqtt.show_logs(
@@ -545,23 +643,14 @@ def command_upload(args: ArgsProtocol, config: ConfigType) -> int | None:
545
643
  devices = choose_upload_log_host(
546
644
  default=args.device,
547
645
  check_default=None,
548
- show_ota=True,
549
- show_mqtt=False,
550
- show_api=False,
551
- purpose="uploading",
646
+ purpose=Purpose.UPLOADING,
552
647
  )
553
648
 
554
- # Try each device until one succeeds
555
- exit_code = 1
556
- for device in devices:
557
- _LOGGER.info("Uploading to %s", device)
558
- exit_code = upload_program(config, args, device)
559
- if exit_code == 0:
560
- _LOGGER.info("Successfully uploaded program.")
561
- return 0
562
- if len(devices) > 1:
563
- _LOGGER.warning("Failed to upload to %s", device)
564
-
649
+ exit_code, _ = upload_program(config, args, devices)
650
+ if exit_code == 0:
651
+ _LOGGER.info("Successfully uploaded program.")
652
+ else:
653
+ _LOGGER.warning("Failed to upload to %s", devices)
565
654
  return exit_code
566
655
 
567
656
 
@@ -579,10 +668,7 @@ def command_logs(args: ArgsProtocol, config: ConfigType) -> int | None:
579
668
  devices = choose_upload_log_host(
580
669
  default=args.device,
581
670
  check_default=None,
582
- show_ota=False,
583
- show_mqtt=True,
584
- show_api=True,
585
- purpose="logging",
671
+ purpose=Purpose.LOGGING,
586
672
  )
587
673
  return show_logs(config, args, devices)
588
674
 
@@ -608,25 +694,14 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None:
608
694
  devices = choose_upload_log_host(
609
695
  default=args.device,
610
696
  check_default=None,
611
- show_ota=True,
612
- show_mqtt=False,
613
- show_api=True,
614
- purpose="uploading",
697
+ purpose=Purpose.UPLOADING,
615
698
  )
616
699
 
617
- # Try each device for upload until one succeeds
618
- successful_device: str | None = None
619
- for device in devices:
620
- _LOGGER.info("Uploading to %s", device)
621
- exit_code = upload_program(config, args, device)
622
- if exit_code == 0:
623
- _LOGGER.info("Successfully uploaded program.")
624
- successful_device = device
625
- break
626
- if len(devices) > 1:
627
- _LOGGER.warning("Failed to upload to %s", device)
628
-
629
- if successful_device is None:
700
+ exit_code, successful_device = upload_program(config, args, devices)
701
+ if exit_code == 0:
702
+ _LOGGER.info("Successfully uploaded program.")
703
+ else:
704
+ _LOGGER.warning("Failed to upload to %s", devices)
630
705
  return exit_code
631
706
 
632
707
  if args.no_logs:
@@ -636,10 +711,7 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None:
636
711
  devices = choose_upload_log_host(
637
712
  default=successful_device,
638
713
  check_default=successful_device,
639
- show_ota=False,
640
- show_mqtt=True,
641
- show_api=True,
642
- purpose="logging",
714
+ purpose=Purpose.LOGGING,
643
715
  )
644
716
  return show_logs(config, args, devices)
645
717
 
@@ -61,11 +61,10 @@ void AbsoluteHumidityComponent::loop() {
61
61
  ESP_LOGW(TAG, "No valid state from temperature sensor!");
62
62
  }
63
63
  if (no_humidity) {
64
- ESP_LOGW(TAG, "No valid state from temperature sensor!");
64
+ ESP_LOGW(TAG, "No valid state from humidity sensor!");
65
65
  }
66
- ESP_LOGW(TAG, "Unable to calculate absolute humidity.");
67
66
  this->publish_state(NAN);
68
- this->status_set_warning();
67
+ this->status_set_warning(LOG_STR("Unable to calculate absolute humidity."));
69
68
  return;
70
69
  }
71
70
 
@@ -87,9 +86,8 @@ void AbsoluteHumidityComponent::loop() {
87
86
  es = es_wobus(temperature_c);
88
87
  break;
89
88
  default:
90
- ESP_LOGE(TAG, "Invalid saturation vapor pressure equation selection!");
91
89
  this->publish_state(NAN);
92
- this->status_set_error();
90
+ this->status_set_error("Invalid saturation vapor pressure equation selection!");
93
91
  return;
94
92
  }
95
93
  ESP_LOGD(TAG, "Saturation vapor pressure %f kPa", es);
@@ -11,15 +11,8 @@ from esphome.components.esp32.const import (
11
11
  VARIANT_ESP32S2,
12
12
  VARIANT_ESP32S3,
13
13
  )
14
- from esphome.config_helpers import filter_source_files_from_platform
15
14
  import esphome.config_validation as cv
16
- from esphome.const import (
17
- CONF_ANALOG,
18
- CONF_INPUT,
19
- CONF_NUMBER,
20
- PLATFORM_ESP8266,
21
- PlatformFramework,
22
- )
15
+ from esphome.const import CONF_ANALOG, CONF_INPUT, CONF_NUMBER, PLATFORM_ESP8266
23
16
  from esphome.core import CORE
24
17
 
25
18
  CODEOWNERS = ["@esphome/core"]
@@ -273,21 +266,3 @@ def validate_adc_pin(value):
273
266
  )(value)
274
267
 
275
268
  raise NotImplementedError
276
-
277
-
278
- FILTER_SOURCE_FILES = filter_source_files_from_platform(
279
- {
280
- "adc_sensor_esp32.cpp": {
281
- PlatformFramework.ESP32_ARDUINO,
282
- PlatformFramework.ESP32_IDF,
283
- },
284
- "adc_sensor_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO},
285
- "adc_sensor_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO},
286
- "adc_sensor_libretiny.cpp": {
287
- PlatformFramework.BK72XX_ARDUINO,
288
- PlatformFramework.RTL87XX_ARDUINO,
289
- PlatformFramework.LN882X_ARDUINO,
290
- },
291
- "adc_sensor_zephyr.cpp": {PlatformFramework.NRF52_ZEPHYR},
292
- }
293
- )
@@ -241,6 +241,8 @@ float ADCSensor::sample_autorange_() {
241
241
  cali_config.bitwidth = ADC_BITWIDTH_DEFAULT;
242
242
 
243
243
  err = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
244
+ ESP_LOGVV(TAG, "Autorange atten=%d: Calibration handle creation %s (err=%d)", atten,
245
+ (err == ESP_OK) ? "SUCCESS" : "FAILED", err);
244
246
  #else
245
247
  adc_cali_line_fitting_config_t cali_config = {
246
248
  .unit_id = this->adc_unit_,
@@ -251,10 +253,14 @@ float ADCSensor::sample_autorange_() {
251
253
  #endif
252
254
  };
253
255
  err = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
256
+ ESP_LOGVV(TAG, "Autorange atten=%d: Calibration handle creation %s (err=%d)", atten,
257
+ (err == ESP_OK) ? "SUCCESS" : "FAILED", err);
254
258
  #endif
255
259
 
256
260
  int raw;
257
261
  err = adc_oneshot_read(this->adc_handle_, this->channel_, &raw);
262
+ ESP_LOGVV(TAG, "Autorange atten=%d: Raw ADC read %s, value=%d (err=%d)", atten,
263
+ (err == ESP_OK) ? "SUCCESS" : "FAILED", raw, err);
258
264
 
259
265
  if (err != ESP_OK) {
260
266
  ESP_LOGW(TAG, "ADC read failed in autorange with error %d", err);
@@ -275,8 +281,10 @@ float ADCSensor::sample_autorange_() {
275
281
  err = adc_cali_raw_to_voltage(handle, raw, &voltage_mv);
276
282
  if (err == ESP_OK) {
277
283
  voltage = voltage_mv / 1000.0f;
284
+ ESP_LOGVV(TAG, "Autorange atten=%d: CALIBRATED - raw=%d -> %dmV -> %.6fV", atten, raw, voltage_mv, voltage);
278
285
  } else {
279
286
  voltage = raw * 3.3f / 4095.0f;
287
+ ESP_LOGVV(TAG, "Autorange atten=%d: UNCALIBRATED FALLBACK - raw=%d -> %.6fV (3.3V ref)", atten, raw, voltage);
280
288
  }
281
289
  // Clean up calibration handle
282
290
  #if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \
@@ -287,6 +295,7 @@ float ADCSensor::sample_autorange_() {
287
295
  #endif
288
296
  } else {
289
297
  voltage = raw * 3.3f / 4095.0f;
298
+ ESP_LOGVV(TAG, "Autorange atten=%d: NO CALIBRATION - raw=%d -> %.6fV (3.3V ref)", atten, raw, voltage);
290
299
  }
291
300
 
292
301
  return {raw, voltage};
@@ -324,18 +333,32 @@ float ADCSensor::sample_autorange_() {
324
333
  }
325
334
 
326
335
  const int adc_half = 2048;
327
- uint32_t c12 = std::min(raw12, adc_half);
328
- uint32_t c6 = adc_half - std::abs(raw6 - adc_half);
329
- uint32_t c2 = adc_half - std::abs(raw2 - adc_half);
330
- uint32_t c0 = std::min(4095 - raw0, adc_half);
331
- uint32_t csum = c12 + c6 + c2 + c0;
336
+ const uint32_t c12 = std::min(raw12, adc_half);
337
+
338
+ const int32_t c6_signed = adc_half - std::abs(raw6 - adc_half);
339
+ const uint32_t c6 = (c6_signed > 0) ? c6_signed : 0; // Clamp to prevent underflow
340
+
341
+ const int32_t c2_signed = adc_half - std::abs(raw2 - adc_half);
342
+ const uint32_t c2 = (c2_signed > 0) ? c2_signed : 0; // Clamp to prevent underflow
343
+
344
+ const uint32_t c0 = std::min(4095 - raw0, adc_half);
345
+ const uint32_t csum = c12 + c6 + c2 + c0;
346
+
347
+ ESP_LOGVV(TAG, "Autorange summary:");
348
+ ESP_LOGVV(TAG, " Raw readings: 12db=%d, 6db=%d, 2.5db=%d, 0db=%d", raw12, raw6, raw2, raw0);
349
+ ESP_LOGVV(TAG, " Voltages: 12db=%.6f, 6db=%.6f, 2.5db=%.6f, 0db=%.6f", mv12, mv6, mv2, mv0);
350
+ ESP_LOGVV(TAG, " Coefficients: c12=%u, c6=%u, c2=%u, c0=%u, sum=%u", c12, c6, c2, c0, csum);
332
351
 
333
352
  if (csum == 0) {
334
353
  ESP_LOGE(TAG, "Invalid weight sum in autorange calculation");
335
354
  return NAN;
336
355
  }
337
356
 
338
- return (mv12 * c12 + mv6 * c6 + mv2 * c2 + mv0 * c0) / csum;
357
+ const float final_result = (mv12 * c12 + mv6 * c6 + mv2 * c2 + mv0 * c0) / csum;
358
+ ESP_LOGV(TAG, "Autorange final: (%.6f*%u + %.6f*%u + %.6f*%u + %.6f*%u)/%u = %.6fV", mv12, c12, mv6, c6, mv2, c2, mv0,
359
+ c0, csum, final_result);
360
+
361
+ return final_result;
339
362
  }
340
363
 
341
364
  } // namespace adc
@@ -9,6 +9,7 @@ from esphome.components.zephyr import (
9
9
  zephyr_add_prj_conf,
10
10
  zephyr_add_user,
11
11
  )
12
+ from esphome.config_helpers import filter_source_files_from_platform
12
13
  import esphome.config_validation as cv
13
14
  from esphome.const import (
14
15
  CONF_ATTENUATION,
@@ -20,6 +21,7 @@ from esphome.const import (
20
21
  PLATFORM_NRF52,
21
22
  STATE_CLASS_MEASUREMENT,
22
23
  UNIT_VOLT,
24
+ PlatformFramework,
23
25
  )
24
26
  from esphome.core import CORE
25
27
 
@@ -174,3 +176,21 @@ async def to_code(config):
174
176
  }};
175
177
  """
176
178
  )
179
+
180
+
181
+ FILTER_SOURCE_FILES = filter_source_files_from_platform(
182
+ {
183
+ "adc_sensor_esp32.cpp": {
184
+ PlatformFramework.ESP32_ARDUINO,
185
+ PlatformFramework.ESP32_IDF,
186
+ },
187
+ "adc_sensor_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO},
188
+ "adc_sensor_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO},
189
+ "adc_sensor_libretiny.cpp": {
190
+ PlatformFramework.BK72XX_ARDUINO,
191
+ PlatformFramework.RTL87XX_ARDUINO,
192
+ PlatformFramework.LN882X_ARDUINO,
193
+ },
194
+ "adc_sensor_zephyr.cpp": {PlatformFramework.NRF52_ZEPHYR},
195
+ }
196
+ )
@@ -113,7 +113,7 @@ void ADE7880::update() {
113
113
  if (this->channel_a_ != nullptr) {
114
114
  auto *chan = this->channel_a_;
115
115
  this->update_sensor_from_s24zp_register16_(chan->current, AIRMS, [](float val) { return val / 100000.0f; });
116
- this->update_sensor_from_s24zp_register16_(chan->voltage, BVRMS, [](float val) { return val / 10000.0f; });
116
+ this->update_sensor_from_s24zp_register16_(chan->voltage, AVRMS, [](float val) { return val / 10000.0f; });
117
117
  this->update_sensor_from_s24zp_register16_(chan->active_power, AWATT, [](float val) { return val / 100.0f; });
118
118
  this->update_sensor_from_s24zp_register16_(chan->apparent_power, AVA, [](float val) { return val / 100.0f; });
119
119
  this->update_sensor_from_s16_register16_(chan->power_factor, APF,
@@ -89,7 +89,7 @@ void AGS10Component::dump_config() {
89
89
  bool AGS10Component::new_i2c_address(uint8_t newaddress) {
90
90
  uint8_t rev_newaddress = ~newaddress;
91
91
  std::array<uint8_t, 5> data{newaddress, rev_newaddress, newaddress, rev_newaddress, 0};
92
- data[4] = calc_crc8_(data, 4);
92
+ data[4] = crc8(data.data(), 4, 0xFF, 0x31, true);
93
93
  if (!this->write_bytes(REG_ADDRESS, data)) {
94
94
  this->error_code_ = COMMUNICATION_FAILED;
95
95
  this->status_set_warning();
@@ -109,7 +109,7 @@ bool AGS10Component::set_zero_point_with_current_resistance() { return this->set
109
109
 
110
110
  bool AGS10Component::set_zero_point_with(uint16_t value) {
111
111
  std::array<uint8_t, 5> data{0x00, 0x0C, (uint8_t) ((value >> 8) & 0xFF), (uint8_t) (value & 0xFF), 0};
112
- data[4] = calc_crc8_(data, 4);
112
+ data[4] = crc8(data.data(), 4, 0xFF, 0x31, true);
113
113
  if (!this->write_bytes(REG_CALIBRATION, data)) {
114
114
  this->error_code_ = COMMUNICATION_FAILED;
115
115
  this->status_set_warning();
@@ -184,7 +184,7 @@ template<size_t N> optional<std::array<uint8_t, N>> AGS10Component::read_and_che
184
184
  auto res = *data;
185
185
  auto crc_byte = res[len];
186
186
 
187
- if (crc_byte != calc_crc8_(res, len)) {
187
+ if (crc_byte != crc8(res.data(), len, 0xFF, 0x31, true)) {
188
188
  this->error_code_ = CRC_CHECK_FAILED;
189
189
  ESP_LOGE(TAG, "Reading AGS10 version failed: crc error!");
190
190
  return optional<std::array<uint8_t, N>>();
@@ -192,20 +192,5 @@ template<size_t N> optional<std::array<uint8_t, N>> AGS10Component::read_and_che
192
192
 
193
193
  return data;
194
194
  }
195
-
196
- template<size_t N> uint8_t AGS10Component::calc_crc8_(std::array<uint8_t, N> dat, uint8_t num) {
197
- uint8_t i, byte1, crc = 0xFF;
198
- for (byte1 = 0; byte1 < num; byte1++) {
199
- crc ^= (dat[byte1]);
200
- for (i = 0; i < 8; i++) {
201
- if (crc & 0x80) {
202
- crc = (crc << 1) ^ 0x31;
203
- } else {
204
- crc = (crc << 1);
205
- }
206
- }
207
- }
208
- return crc;
209
- }
210
195
  } // namespace ags10
211
196
  } // namespace esphome