esphome 2025.7.4__py3-none-any.whl → 2025.8.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.

Potentially problematic release.


This version of esphome might be problematic. Click here for more details.

Files changed (754) hide show
  1. esphome/__main__.py +189 -82
  2. esphome/automation.py +2 -4
  3. esphome/build_gen/__init__.py +0 -0
  4. esphome/build_gen/platformio.py +102 -0
  5. esphome/components/a4988/a4988.cpp +0 -1
  6. esphome/components/absolute_humidity/absolute_humidity.cpp +0 -2
  7. esphome/components/absolute_humidity/sensor.py +2 -2
  8. esphome/components/adc/__init__.py +123 -85
  9. esphome/components/adc/adc_sensor.h +98 -35
  10. esphome/components/adc/adc_sensor_common.cpp +10 -4
  11. esphome/components/adc/adc_sensor_esp32.cpp +291 -123
  12. esphome/components/adc/adc_sensor_esp8266.cpp +1 -4
  13. esphome/components/adc/adc_sensor_libretiny.cpp +1 -2
  14. esphome/components/adc/adc_sensor_rp2040.cpp +1 -2
  15. esphome/components/adc/adc_sensor_zephyr.cpp +207 -0
  16. esphome/components/adc/sensor.py +61 -27
  17. esphome/components/adc128s102/adc128s102.cpp +1 -4
  18. esphome/components/ade7880/sensor.py +75 -49
  19. esphome/components/ads1115/ads1115.cpp +0 -1
  20. esphome/components/ads1118/ads1118.cpp +0 -1
  21. esphome/components/ags10/ags10.cpp +0 -4
  22. esphome/components/aht10/aht10.cpp +0 -4
  23. esphome/components/aic3204/aic3204.cpp +0 -2
  24. esphome/components/airthings_wave_plus/__init__.py +1 -1
  25. esphome/components/airthings_wave_plus/airthings_wave_plus.cpp +22 -4
  26. esphome/components/airthings_wave_plus/airthings_wave_plus.h +10 -1
  27. esphome/components/airthings_wave_plus/sensor.py +55 -28
  28. esphome/components/alarm_control_panel/__init__.py +4 -9
  29. esphome/components/am2315c/am2315c.cpp +0 -2
  30. esphome/components/am2320/am2320.cpp +0 -1
  31. esphome/components/animation/__init__.py +14 -11
  32. esphome/components/apds9306/apds9306.cpp +0 -4
  33. esphome/components/apds9960/apds9960.cpp +0 -1
  34. esphome/components/api/__init__.py +29 -4
  35. esphome/components/api/api_connection.cpp +378 -401
  36. esphome/components/api/api_connection.h +112 -56
  37. esphome/components/api/api_frame_helper.cpp +69 -896
  38. esphome/components/api/api_frame_helper.h +31 -126
  39. esphome/components/api/api_frame_helper_noise.cpp +583 -0
  40. esphome/components/api/api_frame_helper_noise.h +68 -0
  41. esphome/components/api/api_frame_helper_plaintext.cpp +290 -0
  42. esphome/components/api/api_frame_helper_plaintext.h +53 -0
  43. esphome/components/api/api_noise_context.h +2 -4
  44. esphome/components/api/api_pb2.cpp +1601 -1808
  45. esphome/components/api/api_pb2.h +367 -323
  46. esphome/components/api/api_pb2_dump.cpp +1137 -3466
  47. esphome/components/api/api_pb2_includes.h +34 -0
  48. esphome/components/api/api_pb2_service.cpp +94 -105
  49. esphome/components/api/api_pb2_service.h +27 -16
  50. esphome/components/api/api_server.cpp +18 -17
  51. esphome/components/api/api_server.h +8 -5
  52. esphome/components/api/client.py +16 -8
  53. esphome/components/api/custom_api_device.h +68 -14
  54. esphome/components/api/homeassistant_service.h +24 -19
  55. esphome/components/api/list_entities.cpp +3 -5
  56. esphome/components/api/list_entities.h +2 -4
  57. esphome/components/api/proto.cpp +3 -5
  58. esphome/components/api/proto.h +239 -274
  59. esphome/components/api/subscribe_state.cpp +2 -4
  60. esphome/components/api/subscribe_state.h +2 -4
  61. esphome/components/api/user_services.cpp +2 -4
  62. esphome/components/api/user_services.h +8 -8
  63. esphome/components/as3935/as3935.cpp +0 -2
  64. esphome/components/as3935_spi/as3935_spi.cpp +0 -2
  65. esphome/components/as5600/__init__.py +1 -1
  66. esphome/components/as5600/as5600.cpp +0 -2
  67. esphome/components/as5600/sensor/__init__.py +0 -1
  68. esphome/components/as7341/as7341.cpp +0 -1
  69. esphome/components/async_tcp/__init__.py +1 -1
  70. esphome/components/at581x/at581x.cpp +1 -1
  71. esphome/components/atm90e26/atm90e26.cpp +0 -1
  72. esphome/components/atm90e32/atm90e32.cpp +488 -118
  73. esphome/components/atm90e32/atm90e32.h +44 -5
  74. esphome/components/audio/audio.h +2 -2
  75. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +0 -2
  76. esphome/components/beken_spi_led_strip/led_strip.cpp +0 -2
  77. esphome/components/bh1750/bh1750.cpp +0 -1
  78. esphome/components/binary_sensor/__init__.py +14 -12
  79. esphome/components/ble_client/__init__.py +4 -7
  80. esphome/components/bluetooth_proxy/__init__.py +40 -3
  81. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +387 -82
  82. esphome/components/bluetooth_proxy/bluetooth_connection.h +16 -5
  83. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +102 -311
  84. esphome/components/bluetooth_proxy/bluetooth_proxy.h +30 -14
  85. esphome/components/bme280_base/bme280_base.cpp +15 -16
  86. esphome/components/bme680/bme680.cpp +2 -3
  87. esphome/components/bme680_bsec/bme680_bsec.cpp +0 -2
  88. esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +0 -2
  89. esphome/components/bmi160/bmi160.cpp +0 -1
  90. esphome/components/bmp085/bmp085.cpp +0 -1
  91. esphome/components/bmp280_base/bmp280_base.cpp +13 -14
  92. esphome/components/bmp3xx_base/bmp3xx_base.cpp +0 -1
  93. esphome/components/bmp581/bmp581.cpp +0 -2
  94. esphome/components/bp1658cj/bp1658cj.cpp +0 -1
  95. esphome/components/bp5758d/bp5758d.cpp +0 -1
  96. esphome/components/button/__init__.py +0 -1
  97. esphome/components/canbus/__init__.py +2 -3
  98. esphome/components/canbus/canbus.cpp +0 -1
  99. esphome/components/cap1188/cap1188.cpp +0 -2
  100. esphome/components/captive_portal/__init__.py +1 -1
  101. esphome/components/cd74hc4067/cd74hc4067.cpp +0 -2
  102. esphome/components/ch422g/ch422g.cpp +0 -1
  103. esphome/components/chsc6x/chsc6x_touchscreen.cpp +0 -3
  104. esphome/components/climate/__init__.py +0 -1
  105. esphome/components/climate/climate_traits.h +24 -0
  106. esphome/components/cm1106/cm1106.cpp +0 -1
  107. esphome/components/const/__init__.py +6 -0
  108. esphome/components/cover/__init__.py +0 -1
  109. esphome/components/cover/cover.cpp +9 -13
  110. esphome/components/cs5460a/cs5460a.cpp +0 -2
  111. esphome/components/cse7761/cse7761.cpp +0 -1
  112. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +0 -2
  113. esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +0 -2
  114. esphome/components/dac7678/dac7678_output.cpp +0 -2
  115. esphome/components/dallas_temp/dallas_temp.cpp +0 -1
  116. esphome/components/datetime/__init__.py +0 -2
  117. esphome/components/debug/__init__.py +15 -1
  118. esphome/components/debug/debug_zephyr.cpp +281 -0
  119. esphome/components/debug/sensor.py +2 -1
  120. esphome/components/deep_sleep/deep_sleep_component.cpp +0 -1
  121. esphome/components/deep_sleep/deep_sleep_esp32.cpp +20 -1
  122. esphome/components/dfrobot_sen0395/__init__.py +1 -2
  123. esphome/components/dht/dht.cpp +0 -1
  124. esphome/components/dht12/dht12.cpp +0 -1
  125. esphome/components/display/__init__.py +16 -3
  126. esphome/components/display_menu_base/__init__.py +1 -1
  127. esphome/components/dps310/dps310.cpp +0 -2
  128. esphome/components/ds1307/ds1307.cpp +0 -1
  129. esphome/components/ds2484/ds2484.cpp +0 -1
  130. esphome/components/duty_cycle/duty_cycle_sensor.cpp +0 -1
  131. esphome/components/ee895/ee895.cpp +0 -1
  132. esphome/components/ektf2232/touchscreen/ektf2232.cpp +0 -1
  133. esphome/components/emc2101/emc2101.cpp +0 -2
  134. esphome/components/ens160_base/ens160_base.cpp +0 -2
  135. esphome/components/ens210/ens210.cpp +0 -1
  136. esphome/components/es7210/es7210.cpp +0 -2
  137. esphome/components/es7243e/es7243e.cpp +0 -2
  138. esphome/components/es8156/es8156.cpp +0 -2
  139. esphome/components/es8311/es8311.cpp +0 -2
  140. esphome/components/es8388/es8388.cpp +0 -2
  141. esphome/components/esp32/__init__.py +199 -58
  142. esphome/components/esp32/boards.py +17 -0
  143. esphome/components/esp32/gpio.cpp +0 -1
  144. esphome/components/esp32/gpio.py +1 -2
  145. esphome/components/esp32/gpio_esp32_h2.py +2 -7
  146. esphome/components/esp32/gpio_esp32_p4.py +2 -7
  147. esphome/components/esp32/post_build.py.script +112 -61
  148. esphome/components/esp32_ble/__init__.py +40 -2
  149. esphome/components/esp32_ble/ble.cpp +12 -8
  150. esphome/components/esp32_ble/ble.h +18 -18
  151. esphome/components/esp32_ble/ble_advertising.cpp +5 -5
  152. esphome/components/esp32_ble/ble_advertising.h +7 -5
  153. esphome/components/esp32_ble/ble_event.h +2 -4
  154. esphome/components/esp32_ble/ble_scan_result.h +2 -4
  155. esphome/components/esp32_ble/ble_uuid.cpp +5 -5
  156. esphome/components/esp32_ble/ble_uuid.h +6 -5
  157. esphome/components/esp32_ble_beacon/__init__.py +4 -0
  158. esphome/components/esp32_ble_client/__init__.py +1 -1
  159. esphome/components/esp32_ble_client/ble_characteristic.cpp +4 -4
  160. esphome/components/esp32_ble_client/ble_characteristic.h +6 -4
  161. esphome/components/esp32_ble_client/ble_client_base.cpp +155 -104
  162. esphome/components/esp32_ble_client/ble_client_base.h +17 -6
  163. esphome/components/esp32_ble_client/ble_descriptor.h +6 -4
  164. esphome/components/esp32_ble_client/ble_service.cpp +4 -4
  165. esphome/components/esp32_ble_client/ble_service.h +6 -4
  166. esphome/components/esp32_ble_server/__init__.py +15 -12
  167. esphome/components/esp32_ble_tracker/__init__.py +79 -11
  168. esphome/components/esp32_ble_tracker/automation.h +4 -4
  169. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +264 -261
  170. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +103 -37
  171. esphome/components/esp32_camera/__init__.py +13 -1
  172. esphome/components/esp32_camera/esp32_camera.cpp +7 -2
  173. esphome/components/esp32_camera/esp32_camera.h +1 -0
  174. esphome/components/esp32_dac/esp32_dac.cpp +3 -19
  175. esphome/components/esp32_dac/esp32_dac.h +4 -8
  176. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -6
  177. esphome/components/esp32_rmt_led_strip/light.py +1 -1
  178. esphome/components/esp32_touch/__init__.py +2 -3
  179. esphome/components/esp32_touch/esp32_touch.h +9 -6
  180. esphome/components/esp32_touch/esp32_touch_common.cpp +2 -0
  181. esphome/components/esp32_touch/esp32_touch_v1.cpp +7 -9
  182. esphome/components/esp32_touch/esp32_touch_v2.cpp +10 -6
  183. esphome/components/esp8266/__init__.py +3 -1
  184. esphome/components/esp8266_pwm/esp8266_pwm.cpp +0 -1
  185. esphome/components/esphome/ota/__init__.py +1 -2
  186. esphome/components/esphome/ota/ota_esphome.cpp +150 -77
  187. esphome/components/esphome/ota/ota_esphome.h +8 -1
  188. esphome/components/espnow/__init__.py +309 -0
  189. esphome/components/espnow/automation.h +175 -0
  190. esphome/components/espnow/espnow_component.cpp +468 -0
  191. esphome/components/espnow/espnow_component.h +183 -0
  192. esphome/components/espnow/espnow_err.h +19 -0
  193. esphome/components/espnow/espnow_packet.h +166 -0
  194. esphome/components/ethernet/__init__.py +7 -1
  195. esphome/components/ethernet/esp_eth_phy_jl1101.c +5 -0
  196. esphome/components/ethernet/ethernet_component.cpp +0 -1
  197. esphome/components/ethernet/ethernet_component.h +4 -0
  198. esphome/components/ethernet_info/ethernet_info_text_sensor.h +0 -3
  199. esphome/components/event/__init__.py +0 -1
  200. esphome/components/factory_reset/__init__.py +92 -0
  201. esphome/components/factory_reset/factory_reset.cpp +76 -0
  202. esphome/components/factory_reset/factory_reset.h +43 -0
  203. esphome/components/fan/__init__.py +0 -1
  204. esphome/components/fan/fan_traits.h +16 -0
  205. esphome/components/fastled_base/fastled_light.cpp +0 -1
  206. esphome/components/fastled_spi/light.py +1 -3
  207. esphome/components/fingerprint_grow/fingerprint_grow.cpp +0 -2
  208. esphome/components/font/__init__.py +9 -1
  209. esphome/components/fs3000/fs3000.cpp +0 -2
  210. esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp +0 -2
  211. esphome/components/ft63x6/ft63x6.cpp +0 -1
  212. esphome/components/gdk101/gdk101.cpp +0 -1
  213. esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +0 -1
  214. esphome/components/gl_r01_i2c/sensor.py +1 -1
  215. esphome/components/gpio/one_wire/gpio_one_wire.cpp +0 -1
  216. esphome/components/gpio/switch/gpio_switch.cpp +0 -2
  217. esphome/components/gpio_expander/cached_gpio.h +24 -15
  218. esphome/components/gps/__init__.py +6 -2
  219. esphome/components/gps/gps.cpp +50 -49
  220. esphome/components/gps/gps.h +4 -8
  221. esphome/components/gps/time/gps_time.cpp +3 -9
  222. esphome/components/gps/time/gps_time.h +4 -7
  223. esphome/components/graph/__init__.py +1 -1
  224. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +0 -1
  225. esphome/components/grove_tb6612fng/grove_tb6612fng.cpp +0 -1
  226. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +21 -12
  227. esphome/components/gt911/touchscreen/gt911_touchscreen.h +26 -2
  228. esphome/components/haier/climate.py +5 -10
  229. esphome/components/haier/haier_base.cpp +0 -1
  230. esphome/components/hbridge/switch/hbridge_switch.cpp +0 -2
  231. esphome/components/hdc1080/hdc1080.cpp +0 -2
  232. esphome/components/heatpumpir/climate.py +2 -2
  233. esphome/components/hlw8012/hlw8012.cpp +0 -1
  234. esphome/components/hm3301/hm3301.cpp +0 -1
  235. esphome/components/hmc5883l/hmc5883l.cpp +0 -1
  236. esphome/components/homeassistant/__init__.py +1 -0
  237. esphome/components/homeassistant/number/__init__.py +1 -0
  238. esphome/components/homeassistant/number/homeassistant_number.cpp +11 -7
  239. esphome/components/homeassistant/switch/__init__.py +1 -0
  240. esphome/components/homeassistant/switch/homeassistant_switch.cpp +9 -5
  241. esphome/components/honeywellabp/honeywellabp.cpp +1 -4
  242. esphome/components/host/__init__.py +2 -0
  243. esphome/components/hte501/hte501.cpp +0 -1
  244. esphome/components/http_request/__init__.py +2 -3
  245. esphome/components/http_request/http_request_idf.cpp +2 -2
  246. esphome/components/htu21d/htu21d.cpp +0 -2
  247. esphome/components/htu31d/htu31d.cpp +0 -2
  248. esphome/components/hx711/hx711.cpp +0 -1
  249. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +0 -1
  250. esphome/components/hydreon_rgxx/sensor.py +4 -5
  251. esphome/components/i2c/i2c_bus.h +1 -1
  252. esphome/components/i2c/i2c_bus_arduino.cpp +1 -2
  253. esphome/components/i2c/i2c_bus_esp_idf.cpp +192 -17
  254. esphome/components/i2c/i2c_bus_esp_idf.h +11 -1
  255. esphome/components/i2s_audio/__init__.py +6 -5
  256. esphome/components/i2s_audio/i2s_audio.cpp +0 -2
  257. esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +1 -4
  258. esphome/components/i2s_audio/microphone/__init__.py +4 -6
  259. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +46 -19
  260. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +4 -3
  261. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +273 -269
  262. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +19 -34
  263. esphome/components/ili9xxx/display.py +4 -3
  264. esphome/components/ili9xxx/ili9xxx_display.cpp +0 -2
  265. esphome/components/image/__init__.py +123 -92
  266. esphome/components/improv_serial/__init__.py +7 -8
  267. esphome/components/ina219/ina219.cpp +0 -1
  268. esphome/components/ina226/ina226.cpp +0 -2
  269. esphome/components/ina260/ina260.cpp +0 -2
  270. esphome/components/ina2xx_base/__init__.py +2 -5
  271. esphome/components/ina2xx_base/ina2xx_base.cpp +0 -2
  272. esphome/components/ina3221/ina3221.cpp +0 -1
  273. esphome/components/internal_temperature/internal_temperature.cpp +0 -2
  274. esphome/components/interval/interval.h +5 -9
  275. esphome/components/json/__init__.py +1 -1
  276. esphome/components/kmeteriso/kmeteriso.cpp +0 -2
  277. esphome/components/lc709203f/lc709203f.cpp +0 -2
  278. esphome/components/lcd_gpio/display.py +1 -3
  279. esphome/components/lcd_gpio/gpio_lcd_display.cpp +0 -1
  280. esphome/components/lcd_pcf8574/pcf8574_display.cpp +0 -1
  281. esphome/components/ld2410/__init__.py +4 -6
  282. esphome/components/ld2410/binary_sensor.py +4 -0
  283. esphome/components/ld2410/ld2410.cpp +56 -100
  284. esphome/components/ld2410/ld2410.h +17 -15
  285. esphome/components/ld2410/sensor.py +24 -10
  286. esphome/components/ld2412/__init__.py +46 -0
  287. esphome/components/ld2412/binary_sensor.py +70 -0
  288. esphome/components/ld2412/button/__init__.py +74 -0
  289. esphome/components/ld2412/button/factory_reset_button.cpp +9 -0
  290. esphome/components/ld2412/button/factory_reset_button.h +18 -0
  291. esphome/components/ld2412/button/query_button.cpp +9 -0
  292. esphome/components/ld2412/button/query_button.h +18 -0
  293. esphome/components/ld2412/button/restart_button.cpp +9 -0
  294. esphome/components/ld2412/button/restart_button.h +18 -0
  295. esphome/components/ld2412/button/start_dynamic_background_correction_button.cpp +11 -0
  296. esphome/components/ld2412/button/start_dynamic_background_correction_button.h +18 -0
  297. esphome/components/ld2412/ld2412.cpp +861 -0
  298. esphome/components/ld2412/ld2412.h +141 -0
  299. esphome/components/ld2412/number/__init__.py +126 -0
  300. esphome/components/ld2412/number/gate_threshold_number.cpp +14 -0
  301. esphome/components/ld2412/number/gate_threshold_number.h +19 -0
  302. esphome/components/ld2412/number/light_threshold_number.cpp +12 -0
  303. esphome/components/ld2412/number/light_threshold_number.h +18 -0
  304. esphome/components/ld2412/number/max_distance_timeout_number.cpp +12 -0
  305. esphome/components/ld2412/number/max_distance_timeout_number.h +18 -0
  306. esphome/components/ld2412/select/__init__.py +82 -0
  307. esphome/components/ld2412/select/baud_rate_select.cpp +12 -0
  308. esphome/components/ld2412/select/baud_rate_select.h +18 -0
  309. esphome/components/ld2412/select/distance_resolution_select.cpp +12 -0
  310. esphome/components/ld2412/select/distance_resolution_select.h +18 -0
  311. esphome/components/ld2412/select/light_out_control_select.cpp +12 -0
  312. esphome/components/ld2412/select/light_out_control_select.h +18 -0
  313. esphome/components/ld2412/sensor.py +124 -0
  314. esphome/components/ld2412/switch/__init__.py +45 -0
  315. esphome/components/ld2412/switch/bluetooth_switch.cpp +12 -0
  316. esphome/components/ld2412/switch/bluetooth_switch.h +18 -0
  317. esphome/components/ld2412/switch/engineering_mode_switch.cpp +12 -0
  318. esphome/components/ld2412/switch/engineering_mode_switch.h +18 -0
  319. esphome/components/ld2412/text_sensor.py +34 -0
  320. esphome/components/ld2420/ld2420.cpp +0 -1
  321. esphome/components/ld2450/__init__.py +3 -4
  322. esphome/components/ld2450/binary_sensor.py +3 -0
  323. esphome/components/ld2450/ld2450.cpp +77 -165
  324. esphome/components/ld2450/ld2450.h +26 -54
  325. esphome/components/ld2450/sensor.py +120 -6
  326. esphome/components/ld2450/text_sensor.py +5 -4
  327. esphome/components/ld24xx/__init__.py +1 -0
  328. esphome/components/ld24xx/ld24xx.h +65 -0
  329. esphome/components/ledc/ledc_output.cpp +0 -1
  330. esphome/components/libretiny/__init__.py +2 -0
  331. esphome/components/light/__init__.py +0 -1
  332. esphome/components/light/effects.py +70 -45
  333. esphome/components/light/light_call.cpp +101 -66
  334. esphome/components/light/light_color_values.h +16 -11
  335. esphome/components/light/light_json_schema.cpp +46 -44
  336. esphome/components/light/light_state.cpp +8 -11
  337. esphome/components/light/light_traits.h +17 -0
  338. esphome/components/lightwaverf/lightwaverf.cpp +0 -2
  339. esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp +0 -1
  340. esphome/components/lock/__init__.py +0 -1
  341. esphome/components/logger/__init__.py +31 -9
  342. esphome/components/logger/logger.cpp +12 -7
  343. esphome/components/logger/logger.h +25 -14
  344. esphome/components/logger/logger_esp32.cpp +2 -7
  345. esphome/components/logger/logger_esp8266.cpp +2 -4
  346. esphome/components/logger/logger_host.cpp +2 -4
  347. esphome/components/logger/logger_libretiny.cpp +2 -4
  348. esphome/components/logger/logger_rp2040.cpp +2 -4
  349. esphome/components/logger/logger_zephyr.cpp +86 -0
  350. esphome/components/logger/select/logger_level_select.cpp +2 -4
  351. esphome/components/logger/select/logger_level_select.h +2 -4
  352. esphome/components/logger/task_log_buffer.cpp +2 -4
  353. esphome/components/logger/task_log_buffer.h +2 -4
  354. esphome/components/lps22/sensor.py +5 -5
  355. esphome/components/ltr390/ltr390.cpp +0 -2
  356. esphome/components/ltr501/ltr501.cpp +0 -1
  357. esphome/components/ltr_als_ps/ltr_als_ps.cpp +0 -1
  358. esphome/components/lvgl/__init__.py +14 -13
  359. esphome/components/lvgl/automation.py +2 -4
  360. esphome/components/lvgl/defines.py +0 -2
  361. esphome/components/lvgl/helpers.py +1 -1
  362. esphome/components/lvgl/lv_validation.py +7 -4
  363. esphome/components/lvgl/lvgl_esphome.cpp +2 -3
  364. esphome/components/lvgl/styles.py +2 -2
  365. esphome/components/lvgl/types.py +1 -1
  366. esphome/components/lvgl/widgets/__init__.py +2 -2
  367. esphome/components/lvgl/widgets/arc.py +14 -11
  368. esphome/components/lvgl/widgets/buttonmatrix.py +1 -1
  369. esphome/components/lvgl/widgets/qrcode.py +7 -7
  370. esphome/components/lvgl/widgets/spinner.py +6 -6
  371. esphome/components/lvgl/widgets/switch.py +2 -2
  372. esphome/components/lvgl/widgets/tabview.py +3 -3
  373. esphome/components/lvgl/widgets/tileview.py +15 -7
  374. esphome/components/m5stack_8angle/m5stack_8angle.cpp +0 -1
  375. esphome/components/matrix_keypad/__init__.py +4 -3
  376. esphome/components/max17043/max17043.cpp +0 -2
  377. esphome/components/max31855/max31855.cpp +1 -4
  378. esphome/components/max31856/max31856.cpp +0 -4
  379. esphome/components/max31865/max31865.cpp +0 -1
  380. esphome/components/max44009/max44009.cpp +0 -1
  381. esphome/components/max6675/max6675.cpp +1 -4
  382. esphome/components/max6956/max6956.cpp +0 -1
  383. esphome/components/max7219/max7219.cpp +0 -1
  384. esphome/components/max7219digit/display.py +1 -1
  385. esphome/components/max7219digit/max7219digit.cpp +0 -1
  386. esphome/components/max9611/max9611.cpp +0 -1
  387. esphome/components/mcp23008/__init__.py +1 -1
  388. esphome/components/mcp23008/mcp23008.cpp +0 -1
  389. esphome/components/mcp23016/mcp23016.cpp +0 -1
  390. esphome/components/mcp23017/__init__.py +1 -1
  391. esphome/components/mcp23017/mcp23017.cpp +0 -1
  392. esphome/components/mcp23s08/__init__.py +1 -1
  393. esphome/components/mcp23s08/mcp23s08.cpp +0 -1
  394. esphome/components/mcp23s17/__init__.py +1 -1
  395. esphome/components/mcp23s17/mcp23s17.cpp +0 -1
  396. esphome/components/mcp23x08_base/__init__.py +2 -0
  397. esphome/components/mcp23x08_base/mcp23x08_base.cpp +9 -7
  398. esphome/components/mcp23x08_base/mcp23x08_base.h +9 -4
  399. esphome/components/mcp23x17_base/__init__.py +2 -0
  400. esphome/components/mcp23x17_base/mcp23x17_base.cpp +20 -7
  401. esphome/components/mcp23x17_base/mcp23x17_base.h +9 -4
  402. esphome/components/mcp23xxx_base/__init__.py +11 -5
  403. esphome/components/mcp23xxx_base/mcp23xxx_base.cpp +15 -12
  404. esphome/components/mcp23xxx_base/mcp23xxx_base.h +8 -7
  405. esphome/components/mcp3008/mcp3008.cpp +1 -4
  406. esphome/components/mcp3204/mcp3204.cpp +1 -4
  407. esphome/components/mcp4461/mcp4461.cpp +0 -1
  408. esphome/components/mcp4725/mcp4725.cpp +0 -1
  409. esphome/components/mcp4728/mcp4728.cpp +0 -1
  410. esphome/components/mcp9600/mcp9600.cpp +0 -2
  411. esphome/components/mcp9808/mcp9808.cpp +0 -2
  412. esphome/components/mdns/__init__.py +3 -0
  413. esphome/components/mdns/mdns_component.cpp +2 -0
  414. esphome/components/mdns/mdns_component.h +4 -0
  415. esphome/components/media_player/__init__.py +40 -0
  416. esphome/components/media_player/automation.h +16 -0
  417. esphome/components/media_player/media_player.cpp +13 -0
  418. esphome/components/media_player/media_player.h +50 -3
  419. esphome/components/micro_wake_word/micro_wake_word.cpp +0 -3
  420. esphome/components/mics_4514/mics_4514.cpp +1 -6
  421. esphome/components/midea/ir_transmitter.h +4 -4
  422. esphome/components/mipi/__init__.py +416 -0
  423. esphome/components/mipi_dsi/__init__.py +5 -0
  424. esphome/components/mipi_dsi/display.py +233 -0
  425. esphome/components/mipi_dsi/mipi_dsi.cpp +379 -0
  426. esphome/components/mipi_dsi/mipi_dsi.h +123 -0
  427. esphome/components/mipi_dsi/models/__init__.py +0 -0
  428. esphome/components/mipi_dsi/models/guition.py +38 -0
  429. esphome/components/mipi_dsi/models/m5stack.py +57 -0
  430. esphome/components/mipi_dsi/models/waveshare.py +105 -0
  431. esphome/components/mipi_rgb/models/lilygo.py +0 -0
  432. esphome/components/mipi_spi/__init__.py +0 -9
  433. esphome/components/mipi_spi/display.py +220 -256
  434. esphome/components/mipi_spi/mipi_spi.cpp +1 -485
  435. esphome/components/mipi_spi/mipi_spi.h +556 -108
  436. esphome/components/mipi_spi/models/__init__.py +0 -65
  437. esphome/components/mipi_spi/models/adafruit.py +30 -0
  438. esphome/components/mipi_spi/models/amoled.py +41 -5
  439. esphome/components/mipi_spi/models/ili.py +5 -5
  440. esphome/components/mipi_spi/models/jc.py +1 -3
  441. esphome/components/mipi_spi/models/lilygo.py +1 -1
  442. esphome/components/mipi_spi/models/waveshare.py +16 -1
  443. esphome/components/mixer/speaker/__init__.py +4 -5
  444. esphome/components/mlx90393/sensor.py +7 -5
  445. esphome/components/mlx90393/sensor_mlx90393.cpp +0 -1
  446. esphome/components/mlx90614/mlx90614.cpp +0 -1
  447. esphome/components/mmc5603/mmc5603.cpp +0 -1
  448. esphome/components/mmc5983/mmc5983.cpp +0 -2
  449. esphome/components/mpl3115a2/mpl3115a2.cpp +0 -2
  450. esphome/components/mpr121/__init__.py +7 -6
  451. esphome/components/mpr121/mpr121.cpp +0 -1
  452. esphome/components/mpu6050/mpu6050.cpp +0 -1
  453. esphome/components/mpu6886/mpu6886.cpp +0 -1
  454. esphome/components/mqtt/__init__.py +1 -2
  455. esphome/components/mqtt/mqtt_button.cpp +1 -1
  456. esphome/components/mqtt/mqtt_client.cpp +0 -1
  457. esphome/components/mqtt/mqtt_component.cpp +8 -14
  458. esphome/components/mqtt/mqtt_component.h +0 -7
  459. esphome/components/mqtt/mqtt_sensor.cpp +0 -1
  460. esphome/components/mqtt/mqtt_sensor.h +0 -1
  461. esphome/components/mqtt/mqtt_text_sensor.cpp +0 -1
  462. esphome/components/mqtt/mqtt_text_sensor.h +0 -1
  463. esphome/components/ms5611/ms5611.cpp +0 -1
  464. esphome/components/ms8607/ms8607.cpp +0 -1
  465. esphome/components/msa3xx/msa3xx.cpp +0 -2
  466. esphome/components/my9231/my9231.cpp +0 -2
  467. esphome/components/nau7802/nau7802.cpp +0 -1
  468. esphome/components/neopixelbus/light.py +3 -0
  469. esphome/components/network/util.cpp +29 -0
  470. esphome/components/nextion/nextion.cpp +0 -1
  471. esphome/components/nfc/binary_sensor/{binary_sensor.cpp → nfc_binary_sensor.cpp} +1 -1
  472. esphome/components/npi19/npi19.cpp +0 -2
  473. esphome/components/nrf52/__init__.py +223 -0
  474. esphome/components/nrf52/boards.py +34 -0
  475. esphome/components/nrf52/const.py +18 -0
  476. esphome/components/nrf52/gpio.py +79 -0
  477. esphome/components/number/__init__.py +2 -1
  478. esphome/components/one_wire/__init__.py +1 -2
  479. esphome/components/one_wire/one_wire.cpp +0 -2
  480. esphome/components/one_wire/one_wire.h +0 -2
  481. esphome/components/opentherm/hub.cpp +0 -1
  482. esphome/components/opentherm/number/__init__.py +2 -2
  483. esphome/components/openthread/__init__.py +2 -3
  484. esphome/components/openthread/openthread.cpp +30 -13
  485. esphome/components/openthread/openthread.h +3 -0
  486. esphome/components/openthread/openthread_esp.cpp +3 -1
  487. esphome/components/opt3001/sensor.py +2 -6
  488. esphome/components/output/__init__.py +38 -0
  489. esphome/components/output/automation.h +24 -0
  490. esphome/components/output/switch/output_switch.cpp +0 -2
  491. esphome/components/packages/__init__.py +1 -2
  492. esphome/components/packet_transport/__init__.py +4 -3
  493. esphome/components/pca6416a/pca6416a.cpp +0 -1
  494. esphome/components/pca9554/pca9554.cpp +0 -1
  495. esphome/components/pca9685/pca9685_output.cpp +0 -2
  496. esphome/components/pcf85063/pcf85063.cpp +0 -1
  497. esphome/components/pcf8563/pcf8563.cpp +0 -1
  498. esphome/components/pcf8574/pcf8574.cpp +0 -1
  499. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +0 -1
  500. esphome/components/pipsolar/sensor/__init__.py +1 -1
  501. esphome/components/pm2005/pm2005.cpp +0 -1
  502. esphome/components/pmsa003i/pmsa003i.cpp +0 -2
  503. esphome/components/pmwcs3/sensor.py +1 -2
  504. esphome/components/pn532/pn532.cpp +0 -2
  505. esphome/components/pn532_spi/pn532_spi.cpp +0 -2
  506. esphome/components/power_supply/power_supply.cpp +7 -10
  507. esphome/components/power_supply/power_supply.h +1 -1
  508. esphome/components/psram/__init__.py +2 -1
  509. esphome/components/pulse_counter/pulse_counter_sensor.cpp +0 -1
  510. esphome/components/pulse_counter/sensor.py +9 -6
  511. esphome/components/pylontech/pylontech.cpp +0 -1
  512. esphome/components/qmc5883l/qmc5883l.cpp +0 -1
  513. esphome/components/qmp6988/qmp6988.cpp +0 -2
  514. esphome/components/qspi_dbi/display.py +2 -3
  515. esphome/components/qspi_dbi/qspi_dbi.cpp +0 -2
  516. esphome/components/qwiic_pir/binary_sensor.py +2 -3
  517. esphome/components/qwiic_pir/qwiic_pir.cpp +0 -2
  518. esphome/components/rc522/rc522.cpp +9 -31
  519. esphome/components/rc522_spi/rc522_spi.cpp +0 -1
  520. esphome/components/remote_base/__init__.py +5 -6
  521. esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -1
  522. esphome/components/remote_receiver/remote_receiver_esp8266.cpp +0 -1
  523. esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -1
  524. esphome/components/remote_transmitter/__init__.py +26 -0
  525. esphome/components/remote_transmitter/automation.h +18 -0
  526. esphome/components/remote_transmitter/remote_transmitter.h +2 -1
  527. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -1
  528. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
  529. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
  530. esphome/components/resampler/speaker/__init__.py +4 -5
  531. esphome/components/rf_bridge/__init__.py +4 -8
  532. esphome/components/rotary_encoder/rotary_encoder.cpp +0 -2
  533. esphome/components/rp2040/__init__.py +3 -1
  534. esphome/components/rp2040_pio_led_strip/led_strip.cpp +0 -2
  535. esphome/components/rp2040_pio_led_strip/light.py +1 -2
  536. esphome/components/rp2040_pwm/rp2040_pwm.cpp +1 -5
  537. esphome/components/rpi_dpi_rgb/display.py +13 -15
  538. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -3
  539. esphome/components/runtime_stats/__init__.py +34 -0
  540. esphome/components/runtime_stats/runtime_stats.cpp +102 -0
  541. esphome/components/runtime_stats/runtime_stats.h +132 -0
  542. esphome/components/scd30/scd30.cpp +0 -2
  543. esphome/components/scd30/sensor.py +1 -2
  544. esphome/components/scd4x/scd4x.cpp +0 -1
  545. esphome/components/scd4x/sensor.py +1 -3
  546. esphome/components/sdl/display.py +3 -1
  547. esphome/components/sdl/sdl_esphome.cpp +0 -2
  548. esphome/components/sdp3x/sdp3x.cpp +0 -2
  549. esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +0 -2
  550. esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +0 -3
  551. esphome/components/select/__init__.py +2 -3
  552. esphome/components/select/select_traits.cpp +1 -1
  553. esphome/components/select/select_traits.h +1 -1
  554. esphome/components/sen0321/sen0321.cpp +0 -1
  555. esphome/components/sen5x/sen5x.cpp +0 -2
  556. esphome/components/sensor/__init__.py +36 -4
  557. esphome/components/sensor/filter.cpp +49 -10
  558. esphome/components/sensor/filter.h +22 -7
  559. esphome/components/sensor/sensor.cpp +0 -1
  560. esphome/components/sensor/sensor.h +0 -9
  561. esphome/components/sfa30/sfa30.cpp +0 -4
  562. esphome/components/sgp30/sgp30.cpp +0 -2
  563. esphome/components/sgp4x/sensor.py +1 -1
  564. esphome/components/sgp4x/sgp4x.cpp +0 -2
  565. esphome/components/shelly_dimmer/shelly_dimmer.cpp +0 -2
  566. esphome/components/sht3xd/sht3xd.cpp +0 -2
  567. esphome/components/sht4x/sht4x.cpp +0 -2
  568. esphome/components/shtcx/shtcx.cpp +0 -1
  569. esphome/components/sim800l/__init__.py +2 -4
  570. esphome/components/sm16716/sm16716.cpp +0 -1
  571. esphome/components/sm2135/sm2135.cpp +0 -1
  572. esphome/components/sm2235/sm2235.cpp +0 -1
  573. esphome/components/sm2335/sm2335.cpp +0 -1
  574. esphome/components/sn74hc165/sn74hc165.cpp +0 -1
  575. esphome/components/sn74hc595/sn74hc595.cpp +0 -1
  576. esphome/components/sntp/sntp_component.cpp +0 -1
  577. esphome/components/sound_level/sensor.py +1 -1
  578. esphome/components/speaker/media_player/__init__.py +21 -33
  579. esphome/components/speaker/media_player/audio_pipeline.cpp +4 -7
  580. esphome/components/spi/__init__.py +29 -13
  581. esphome/components/spi/spi.cpp +0 -2
  582. esphome/components/spi_device/spi_device.cpp +1 -4
  583. esphome/components/sprinkler/__init__.py +4 -4
  584. esphome/components/sps30/sps30.cpp +0 -1
  585. esphome/components/ssd1306_base/__init__.py +11 -11
  586. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  587. esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +0 -1
  588. esphome/components/ssd1306_spi/ssd1306_spi.cpp +0 -1
  589. esphome/components/ssd1322_spi/ssd1322_spi.cpp +0 -1
  590. esphome/components/ssd1325_spi/ssd1325_spi.cpp +0 -1
  591. esphome/components/ssd1327_i2c/ssd1327_i2c.cpp +0 -1
  592. esphome/components/ssd1327_spi/ssd1327_spi.cpp +0 -1
  593. esphome/components/ssd1331_spi/ssd1331_spi.cpp +0 -1
  594. esphome/components/ssd1351_spi/ssd1351_spi.cpp +0 -1
  595. esphome/components/st7567_i2c/st7567_i2c.cpp +0 -1
  596. esphome/components/st7567_spi/st7567_spi.cpp +0 -1
  597. esphome/components/st7701s/display.py +10 -14
  598. esphome/components/st7701s/st7701s.cpp +0 -3
  599. esphome/components/st7735/st7735.cpp +0 -1
  600. esphome/components/st7789v/st7789v.cpp +0 -1
  601. esphome/components/st7920/st7920.cpp +0 -1
  602. esphome/components/status_led/light/status_led_light.cpp +0 -2
  603. esphome/components/status_led/status_led.cpp +0 -1
  604. esphome/components/stepper/__init__.py +2 -4
  605. esphome/components/sts3x/sts3x.cpp +0 -1
  606. esphome/components/substitutions/__init__.py +10 -16
  607. esphome/components/substitutions/jinja.py +24 -1
  608. esphome/components/sun/__init__.py +2 -3
  609. esphome/components/switch/__init__.py +31 -1
  610. esphome/components/switch/automation.h +24 -0
  611. esphome/components/switch/switch.cpp +8 -0
  612. esphome/components/switch/switch.h +8 -0
  613. esphome/components/sx126x/sx126x.cpp +0 -2
  614. esphome/components/sx127x/sx127x.cpp +0 -2
  615. esphome/components/sx1509/__init__.py +7 -5
  616. esphome/components/sx1509/output/sx1509_float_output.cpp +1 -1
  617. esphome/components/sx1509/sx1509.cpp +0 -2
  618. esphome/components/syslog/esphome_syslog.cpp +1 -1
  619. esphome/components/tc74/tc74.cpp +0 -1
  620. esphome/components/tca9548a/tca9548a.cpp +0 -1
  621. esphome/components/tca9555/tca9555.cpp +0 -1
  622. esphome/components/tcs34725/tcs34725.cpp +0 -1
  623. esphome/components/tee501/tee501.cpp +0 -1
  624. esphome/components/tem3200/tem3200.cpp +0 -2
  625. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +0 -1
  626. esphome/components/template/cover/template_cover.cpp +0 -1
  627. esphome/components/template/select/template_select.cpp +0 -1
  628. esphome/components/template/text/template_text.cpp +0 -2
  629. esphome/components/template/valve/template_valve.cpp +0 -1
  630. esphome/components/text/__init__.py +0 -1
  631. esphome/components/text/text_traits.h +2 -0
  632. esphome/components/text_sensor/__init__.py +2 -1
  633. esphome/components/text_sensor/text_sensor.cpp +0 -2
  634. esphome/components/text_sensor/text_sensor.h +0 -8
  635. esphome/components/thermostat/climate.py +4 -4
  636. esphome/components/time/__init__.py +7 -4
  637. esphome/components/time/real_time_clock.cpp +16 -3
  638. esphome/components/tlc59208f/tlc59208f_output.cpp +0 -2
  639. esphome/components/tlc5947/tlc5947.cpp +0 -2
  640. esphome/components/tlc5971/tlc5971.cpp +0 -2
  641. esphome/components/tm1621/tm1621.cpp +0 -2
  642. esphome/components/tm1637/tm1637.cpp +0 -2
  643. esphome/components/tm1638/tm1638.cpp +0 -2
  644. esphome/components/tm1651/__init__.py +45 -48
  645. esphome/components/tm1651/tm1651.cpp +213 -47
  646. esphome/components/tm1651/tm1651.h +37 -32
  647. esphome/components/tmp117/tmp117.cpp +0 -2
  648. esphome/components/tsl2561/tsl2561.cpp +0 -1
  649. esphome/components/tsl2591/tsl2591.cpp +0 -1
  650. esphome/components/tt21100/touchscreen/tt21100.cpp +0 -2
  651. esphome/components/ttp229_bsf/ttp229_bsf.cpp +0 -1
  652. esphome/components/ttp229_lsf/ttp229_lsf.cpp +0 -1
  653. esphome/components/tuya/climate/__init__.py +9 -10
  654. esphome/components/tuya/number/__init__.py +8 -6
  655. esphome/components/tx20/tx20.cpp +0 -1
  656. esphome/components/uart/uart_component_esp32_arduino.cpp +0 -1
  657. esphome/components/uart/uart_component_esp8266.cpp +0 -1
  658. esphome/components/uart/uart_component_esp_idf.cpp +0 -2
  659. esphome/components/uart/uart_component_libretiny.cpp +0 -2
  660. esphome/components/uart/uart_component_rp2040.cpp +0 -2
  661. esphome/components/udp/__init__.py +1 -1
  662. esphome/components/ufire_ec/sensor.py +1 -2
  663. esphome/components/ufire_ec/ufire_ec.cpp +0 -2
  664. esphome/components/ufire_ise/sensor.py +1 -2
  665. esphome/components/ufire_ise/ufire_ise.cpp +0 -2
  666. esphome/components/ultrasonic/ultrasonic_sensor.cpp +0 -1
  667. esphome/components/update/__init__.py +0 -1
  668. esphome/components/uptime/sensor/uptime_seconds_sensor.cpp +0 -1
  669. esphome/components/uptime/sensor/uptime_seconds_sensor.h +0 -2
  670. esphome/components/usb_host/usb_host_client.cpp +0 -1
  671. esphome/components/usb_host/usb_host_component.cpp +0 -1
  672. esphome/components/valve/__init__.py +0 -1
  673. esphome/components/veml3235/veml3235.cpp +0 -3
  674. esphome/components/veml7700/veml7700.cpp +0 -2
  675. esphome/components/version/version_text_sensor.cpp +0 -1
  676. esphome/components/version/version_text_sensor.h +0 -1
  677. esphome/components/vl53l0x/vl53l0x_sensor.cpp +0 -4
  678. esphome/components/voice_assistant/voice_assistant.cpp +9 -8
  679. esphome/components/web_server/__init__.py +13 -0
  680. esphome/components/web_server/web_server.cpp +187 -352
  681. esphome/components/web_server/web_server.h +61 -1
  682. esphome/components/web_server_base/__init__.py +1 -1
  683. esphome/components/web_server_base/web_server_base.cpp +2 -0
  684. esphome/components/web_server_base/web_server_base.h +6 -0
  685. esphome/components/web_server_idf/web_server_idf.cpp +10 -8
  686. esphome/components/web_server_idf/web_server_idf.h +2 -0
  687. esphome/components/weikai_i2c/weikai_i2c.cpp +1 -2
  688. esphome/components/weikai_spi/weikai_spi.cpp +1 -1
  689. esphome/components/wifi/__init__.py +8 -43
  690. esphome/components/wifi/wifi_component.cpp +100 -36
  691. esphome/components/wifi/wifi_component.h +5 -1
  692. esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -0
  693. esphome/components/wifi/wifi_component_esp_idf.cpp +30 -0
  694. esphome/components/wifi_info/wifi_info_text_sensor.h +0 -6
  695. esphome/components/wifi_signal/wifi_signal_sensor.h +0 -1
  696. esphome/components/wireguard/wireguard.cpp +0 -2
  697. esphome/components/x9c/x9c.cpp +0 -2
  698. esphome/components/xgzp68xx/xgzp68xx.cpp +0 -1
  699. esphome/components/xl9535/xl9535.cpp +0 -2
  700. esphome/components/zephyr/__init__.py +252 -0
  701. esphome/components/zephyr/const.py +16 -0
  702. esphome/components/zephyr/core.cpp +90 -0
  703. esphome/components/zephyr/gpio.cpp +120 -0
  704. esphome/components/zephyr/gpio.h +38 -0
  705. esphome/components/zephyr/pre_build.py.script +4 -0
  706. esphome/components/zephyr/preferences.cpp +156 -0
  707. esphome/components/zephyr/preferences.h +13 -0
  708. esphome/config.py +38 -16
  709. esphome/config_helpers.py +1 -2
  710. esphome/config_validation.py +8 -15
  711. esphome/const.py +26 -1
  712. esphome/core/__init__.py +88 -51
  713. esphome/core/application.cpp +75 -21
  714. esphome/core/application.h +106 -171
  715. esphome/core/color.h +10 -0
  716. esphome/core/component.cpp +41 -25
  717. esphome/core/component.h +9 -6
  718. esphome/core/component_iterator.cpp +61 -261
  719. esphome/core/component_iterator.h +15 -0
  720. esphome/core/config.py +26 -11
  721. esphome/core/defines.h +40 -2
  722. esphome/core/entity_base.h +18 -0
  723. esphome/core/entity_helpers.py +41 -6
  724. esphome/core/helpers.cpp +8 -15
  725. esphome/core/helpers.h +60 -6
  726. esphome/core/lock_free_queue.h +1 -1
  727. esphome/core/scheduler.cpp +277 -74
  728. esphome/core/scheduler.h +89 -27
  729. esphome/cpp_generator.py +2 -6
  730. esphome/cpp_helpers.py +1 -1
  731. esphome/dashboard/dashboard.py +2 -3
  732. esphome/dashboard/dns.py +2 -8
  733. esphome/dashboard/web_server.py +34 -19
  734. esphome/espota2.py +1 -4
  735. esphome/git.py +3 -1
  736. esphome/helpers.py +23 -4
  737. esphome/log.py +3 -1
  738. esphome/mqtt.py +3 -5
  739. esphome/platformio_api.py +7 -4
  740. esphome/types.py +12 -0
  741. esphome/util.py +20 -8
  742. esphome/voluptuous_schema.py +4 -3
  743. esphome/vscode.py +1 -2
  744. esphome/wizard.py +1 -4
  745. esphome/writer.py +5 -107
  746. esphome/yaml_util.py +7 -5
  747. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/METADATA +12 -13
  748. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/RECORD +753 -673
  749. esphome/components/mipi_spi/models/commands.py +0 -82
  750. /esphome/components/nfc/binary_sensor/{binary_sensor.h → nfc_binary_sensor.h} +0 -0
  751. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/WHEEL +0 -0
  752. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/entry_points.txt +0 -0
  753. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/licenses/LICENSE +0 -0
  754. {esphome-2025.7.4.dist-info → esphome-2025.8.0b1.dist-info}/top_level.txt +0 -0
@@ -109,8 +109,9 @@ void ATM90E32Component::update() {
109
109
  }
110
110
 
111
111
  void ATM90E32Component::setup() {
112
- ESP_LOGCONFIG(TAG, "Running setup");
113
112
  this->spi_setup();
113
+ this->cs_summary_ = this->cs_->dump_summary();
114
+ const char *cs = this->cs_summary_.c_str();
114
115
 
115
116
  uint16_t mmode0 = 0x87; // 3P4W 50Hz
116
117
  uint16_t high_thresh = 0;
@@ -131,9 +132,9 @@ void ATM90E32Component::setup() {
131
132
  mmode0 |= 0 << 1; // sets 1st bit to 0, phase b is not counted into the all-phase sum energy/power (P/Q/S)
132
133
  }
133
134
 
134
- this->write16_(ATM90E32_REGISTER_SOFTRESET, 0x789A); // Perform soft reset
135
- delay(6); // Wait for the minimum 5ms + 1ms
136
- this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x55AA); // enable register config access
135
+ this->write16_(ATM90E32_REGISTER_SOFTRESET, 0x789A, false); // Perform soft reset
136
+ delay(6); // Wait for the minimum 5ms + 1ms
137
+ this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x55AA); // enable register config access
137
138
  if (!this->validate_spi_read_(0x55AA, "setup()")) {
138
139
  ESP_LOGW(TAG, "Could not initialize ATM90E32 IC, check SPI settings");
139
140
  this->mark_failed();
@@ -157,16 +158,17 @@ void ATM90E32Component::setup() {
157
158
 
158
159
  if (this->enable_offset_calibration_) {
159
160
  // Initialize flash storage for offset calibrations
160
- uint32_t o_hash = fnv1_hash(std::string("_offset_calibration_") + this->cs_->dump_summary());
161
+ uint32_t o_hash = fnv1_hash(std::string("_offset_calibration_") + this->cs_summary_);
161
162
  this->offset_pref_ = global_preferences->make_preference<OffsetCalibration[3]>(o_hash, true);
162
163
  this->restore_offset_calibrations_();
163
164
 
164
165
  // Initialize flash storage for power offset calibrations
165
- uint32_t po_hash = fnv1_hash(std::string("_power_offset_calibration_") + this->cs_->dump_summary());
166
+ uint32_t po_hash = fnv1_hash(std::string("_power_offset_calibration_") + this->cs_summary_);
166
167
  this->power_offset_pref_ = global_preferences->make_preference<PowerOffsetCalibration[3]>(po_hash, true);
167
168
  this->restore_power_offset_calibrations_();
168
169
  } else {
169
- ESP_LOGI(TAG, "[CALIBRATION] Power & Voltage/Current offset calibration is disabled. Using config file values.");
170
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Power & Voltage/Current offset calibration is disabled. Using config file values.",
171
+ cs);
170
172
  for (uint8_t phase = 0; phase < 3; ++phase) {
171
173
  this->write16_(this->voltage_offset_registers[phase],
172
174
  static_cast<uint16_t>(this->offset_phase_[phase].voltage_offset_));
@@ -181,21 +183,18 @@ void ATM90E32Component::setup() {
181
183
 
182
184
  if (this->enable_gain_calibration_) {
183
185
  // Initialize flash storage for gain calibration
184
- uint32_t g_hash = fnv1_hash(std::string("_gain_calibration_") + this->cs_->dump_summary());
186
+ uint32_t g_hash = fnv1_hash(std::string("_gain_calibration_") + this->cs_summary_);
185
187
  this->gain_calibration_pref_ = global_preferences->make_preference<GainCalibration[3]>(g_hash, true);
186
188
  this->restore_gain_calibrations_();
187
189
 
188
- if (this->using_saved_calibrations_) {
189
- ESP_LOGI(TAG, "[CALIBRATION] Successfully restored gain calibration from memory.");
190
- } else {
190
+ if (!this->using_saved_calibrations_) {
191
191
  for (uint8_t phase = 0; phase < 3; ++phase) {
192
192
  this->write16_(voltage_gain_registers[phase], this->phase_[phase].voltage_gain_);
193
193
  this->write16_(current_gain_registers[phase], this->phase_[phase].ct_gain_);
194
194
  }
195
195
  }
196
196
  } else {
197
- ESP_LOGI(TAG, "[CALIBRATION] Gain calibration is disabled. Using config file values.");
198
-
197
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Gain calibration is disabled. Using config file values.", cs);
199
198
  for (uint8_t phase = 0; phase < 3; ++phase) {
200
199
  this->write16_(voltage_gain_registers[phase], this->phase_[phase].voltage_gain_);
201
200
  this->write16_(current_gain_registers[phase], this->phase_[phase].ct_gain_);
@@ -214,6 +213,122 @@ void ATM90E32Component::setup() {
214
213
  this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x0000); // end configuration
215
214
  }
216
215
 
216
+ void ATM90E32Component::log_calibration_status_() {
217
+ const char *cs = this->cs_summary_.c_str();
218
+
219
+ bool offset_mismatch = false;
220
+ bool power_mismatch = false;
221
+ bool gain_mismatch = false;
222
+
223
+ for (uint8_t phase = 0; phase < 3; ++phase) {
224
+ offset_mismatch |= this->offset_calibration_mismatch_[phase];
225
+ power_mismatch |= this->power_offset_calibration_mismatch_[phase];
226
+ gain_mismatch |= this->gain_calibration_mismatch_[phase];
227
+ }
228
+
229
+ if (offset_mismatch) {
230
+ ESP_LOGW(TAG, "[CALIBRATION][%s] ", cs);
231
+ ESP_LOGW(TAG,
232
+ "[CALIBRATION][%s] ===================== Offset mismatch: using flash values =====================", cs);
233
+ ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
234
+ cs);
235
+ ESP_LOGW(TAG, "[CALIBRATION][%s] | Phase | offset_voltage | offset_current |", cs);
236
+ ESP_LOGW(TAG, "[CALIBRATION][%s] | | config | flash | config | flash |", cs);
237
+ ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
238
+ cs);
239
+ for (uint8_t phase = 0; phase < 3; ++phase) {
240
+ ESP_LOGW(TAG, "[CALIBRATION][%s] | %c | %6d | %6d | %6d | %6d |", cs, 'A' + phase,
241
+ this->config_offset_phase_[phase].voltage_offset_, this->offset_phase_[phase].voltage_offset_,
242
+ this->config_offset_phase_[phase].current_offset_, this->offset_phase_[phase].current_offset_);
243
+ }
244
+ ESP_LOGW(TAG,
245
+ "[CALIBRATION][%s] ===============================================================================", cs);
246
+ }
247
+ if (power_mismatch) {
248
+ ESP_LOGW(TAG, "[CALIBRATION][%s] ", cs);
249
+ ESP_LOGW(TAG,
250
+ "[CALIBRATION][%s] ================= Power offset mismatch: using flash values =================", cs);
251
+ ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
252
+ cs);
253
+ ESP_LOGW(TAG, "[CALIBRATION][%s] | Phase | offset_active_power|offset_reactive_power|", cs);
254
+ ESP_LOGW(TAG, "[CALIBRATION][%s] | | config | flash | config | flash |", cs);
255
+ ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
256
+ cs);
257
+ for (uint8_t phase = 0; phase < 3; ++phase) {
258
+ ESP_LOGW(TAG, "[CALIBRATION][%s] | %c | %6d | %6d | %6d | %6d |", cs, 'A' + phase,
259
+ this->config_power_offset_phase_[phase].active_power_offset,
260
+ this->power_offset_phase_[phase].active_power_offset,
261
+ this->config_power_offset_phase_[phase].reactive_power_offset,
262
+ this->power_offset_phase_[phase].reactive_power_offset);
263
+ }
264
+ ESP_LOGW(TAG,
265
+ "[CALIBRATION][%s] ===============================================================================", cs);
266
+ }
267
+ if (gain_mismatch) {
268
+ ESP_LOGW(TAG, "[CALIBRATION][%s] ", cs);
269
+ ESP_LOGW(TAG,
270
+ "[CALIBRATION][%s] ====================== Gain mismatch: using flash values =====================", cs);
271
+ ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
272
+ cs);
273
+ ESP_LOGW(TAG, "[CALIBRATION][%s] | Phase | voltage_gain | current_gain |", cs);
274
+ ESP_LOGW(TAG, "[CALIBRATION][%s] | | config | flash | config | flash |", cs);
275
+ ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
276
+ cs);
277
+ for (uint8_t phase = 0; phase < 3; ++phase) {
278
+ ESP_LOGW(TAG, "[CALIBRATION][%s] | %c | %6u | %6u | %6u | %6u |", cs, 'A' + phase,
279
+ this->config_gain_phase_[phase].voltage_gain, this->gain_phase_[phase].voltage_gain,
280
+ this->config_gain_phase_[phase].current_gain, this->gain_phase_[phase].current_gain);
281
+ }
282
+ ESP_LOGW(TAG,
283
+ "[CALIBRATION][%s] ===============================================================================", cs);
284
+ }
285
+ if (!this->enable_offset_calibration_) {
286
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Power & Voltage/Current offset calibration is disabled. Using config file values.",
287
+ cs);
288
+ } else if (this->restored_offset_calibration_ && !offset_mismatch) {
289
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
290
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ============== Restored offset calibration from memory ==============", cs);
291
+ ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
292
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_voltage | offset_current |", cs);
293
+ ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
294
+ for (uint8_t phase = 0; phase < 3; phase++) {
295
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase,
296
+ this->offset_phase_[phase].voltage_offset_, this->offset_phase_[phase].current_offset_);
297
+ }
298
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ==============================================================\\n", cs);
299
+ }
300
+
301
+ if (this->restored_power_offset_calibration_ && !power_mismatch) {
302
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
303
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ============ Restored power offset calibration from memory ============", cs);
304
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
305
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_active_power | offset_reactive_power |", cs);
306
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
307
+ for (uint8_t phase = 0; phase < 3; phase++) {
308
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase,
309
+ this->power_offset_phase_[phase].active_power_offset,
310
+ this->power_offset_phase_[phase].reactive_power_offset);
311
+ }
312
+ ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\n", cs);
313
+ }
314
+ if (!this->enable_gain_calibration_) {
315
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Gain calibration is disabled. Using config file values.", cs);
316
+ } else if (this->restored_gain_calibration_ && !gain_mismatch) {
317
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
318
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ============ Restoring saved gain calibrations to registers ============", cs);
319
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
320
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | voltage_gain | current_gain |", cs);
321
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
322
+ for (uint8_t phase = 0; phase < 3; phase++) {
323
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6u | %6u |", cs, 'A' + phase,
324
+ this->gain_phase_[phase].voltage_gain, this->gain_phase_[phase].current_gain);
325
+ }
326
+ ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\\n", cs);
327
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Gain calibration loaded and verified successfully.\n", cs);
328
+ }
329
+ this->calibration_message_printed_ = true;
330
+ }
331
+
217
332
  void ATM90E32Component::dump_config() {
218
333
  ESP_LOGCONFIG("", "ATM90E32:");
219
334
  LOG_PIN(" CS Pin: ", this->cs_);
@@ -256,6 +371,10 @@ void ATM90E32Component::dump_config() {
256
371
  LOG_SENSOR(" ", "Peak Current C", this->phase_[PHASEC].peak_current_sensor_);
257
372
  LOG_SENSOR(" ", "Frequency", this->freq_sensor_);
258
373
  LOG_SENSOR(" ", "Chip Temp", this->chip_temperature_sensor_);
374
+ if (this->restored_offset_calibration_ || this->restored_power_offset_calibration_ ||
375
+ this->restored_gain_calibration_ || !this->enable_offset_calibration_ || !this->enable_gain_calibration_) {
376
+ this->log_calibration_status_();
377
+ }
259
378
  }
260
379
 
261
380
  float ATM90E32Component::get_setup_priority() const { return setup_priority::IO; }
@@ -263,26 +382,35 @@ float ATM90E32Component::get_setup_priority() const { return setup_priority::IO;
263
382
  // R/C registers can conly be cleared after the LastSPIData register is updated (register 78H)
264
383
  // Peakdetect period: 05H. Bit 15:8 are PeakDet_period in ms. 7:0 are Sag_period
265
384
  // Default is 143FH (20ms, 63ms)
266
- uint16_t ATM90E32Component::read16_(uint16_t a_register) {
385
+ uint16_t ATM90E32Component::read16_transaction_(uint16_t a_register) {
267
386
  uint8_t addrh = (1 << 7) | ((a_register >> 8) & 0x03);
268
387
  uint8_t addrl = (a_register & 0xFF);
269
- uint8_t data[2];
270
- uint16_t output;
388
+ uint8_t data[4] = {addrh, addrl, 0x00, 0x00};
389
+ this->transfer_array(data, 4);
390
+ uint16_t output = encode_uint16(data[2], data[3]);
391
+ ESP_LOGVV(TAG, "read16_ 0x%04" PRIX16 " output 0x%04" PRIX16, a_register, output);
392
+ return output;
393
+ }
394
+
395
+ uint16_t ATM90E32Component::read16_(uint16_t a_register) {
271
396
  this->enable();
272
- delay_microseconds_safe(1); // min delay between CS low and first SCK is 200ns - 1ms is plenty
273
- this->write_byte(addrh);
274
- this->write_byte(addrl);
275
- this->read_array(data, 2);
397
+ delay_microseconds_safe(1); // min delay between CS low and first SCK is 200ns - 1us is plenty
398
+ uint16_t output = this->read16_transaction_(a_register);
399
+ delay_microseconds_safe(1); // allow the last clock to propagate before releasing CS
276
400
  this->disable();
277
-
278
- output = (uint16_t(data[0] & 0xFF) << 8) | (data[1] & 0xFF);
279
- ESP_LOGVV(TAG, "read16_ 0x%04" PRIX16 " output 0x%04" PRIX16, a_register, output);
401
+ delay_microseconds_safe(1); // meet minimum CS high time before next transaction
280
402
  return output;
281
403
  }
282
404
 
283
405
  int ATM90E32Component::read32_(uint16_t addr_h, uint16_t addr_l) {
284
- const uint16_t val_h = this->read16_(addr_h);
285
- const uint16_t val_l = this->read16_(addr_l);
406
+ this->enable();
407
+ delay_microseconds_safe(1);
408
+ const uint16_t val_h = this->read16_transaction_(addr_h);
409
+ delay_microseconds_safe(1);
410
+ const uint16_t val_l = this->read16_transaction_(addr_l);
411
+ delay_microseconds_safe(1);
412
+ this->disable();
413
+ delay_microseconds_safe(1);
286
414
  const int32_t val = (val_h << 16) | val_l;
287
415
 
288
416
  ESP_LOGVV(TAG,
@@ -293,13 +421,19 @@ int ATM90E32Component::read32_(uint16_t addr_h, uint16_t addr_l) {
293
421
  return val;
294
422
  }
295
423
 
296
- void ATM90E32Component::write16_(uint16_t a_register, uint16_t val) {
424
+ void ATM90E32Component::write16_(uint16_t a_register, uint16_t val, bool validate) {
297
425
  ESP_LOGVV(TAG, "write16_ 0x%04" PRIX16 " val 0x%04" PRIX16, a_register, val);
426
+ uint8_t addrh = ((a_register >> 8) & 0x03);
427
+ uint8_t addrl = (a_register & 0xFF);
428
+ uint8_t data[4] = {addrh, addrl, uint8_t((val >> 8) & 0xFF), uint8_t(val & 0xFF)};
298
429
  this->enable();
299
- this->write_byte16(a_register);
300
- this->write_byte16(val);
430
+ delay_microseconds_safe(1); // ensure CS setup time
431
+ this->write_array(data, 4);
432
+ delay_microseconds_safe(1); // allow clock to settle before raising CS
301
433
  this->disable();
302
- this->validate_spi_read_(val, "write16()");
434
+ delay_microseconds_safe(1); // ensure minimum CS high time
435
+ if (validate)
436
+ this->validate_spi_read_(val, "write16()");
303
437
  }
304
438
 
305
439
  float ATM90E32Component::get_local_phase_voltage_(uint8_t phase) { return this->phase_[phase].voltage_; }
@@ -442,8 +576,10 @@ float ATM90E32Component::get_chip_temperature_() {
442
576
  }
443
577
 
444
578
  void ATM90E32Component::run_gain_calibrations() {
579
+ const char *cs = this->cs_summary_.c_str();
445
580
  if (!this->enable_gain_calibration_) {
446
- ESP_LOGW(TAG, "[CALIBRATION] Gain calibration is disabled! Enable it first with enable_gain_calibration: true");
581
+ ESP_LOGW(TAG, "[CALIBRATION][%s] Gain calibration is disabled! Enable it first with enable_gain_calibration: true",
582
+ cs);
447
583
  return;
448
584
  }
449
585
 
@@ -455,12 +591,14 @@ void ATM90E32Component::run_gain_calibrations() {
455
591
  float ref_currents[3] = {this->get_reference_current(0), this->get_reference_current(1),
456
592
  this->get_reference_current(2)};
457
593
 
458
- ESP_LOGI(TAG, "[CALIBRATION] ");
459
- ESP_LOGI(TAG, "[CALIBRATION] ========================= Gain Calibration =========================");
460
- ESP_LOGI(TAG, "[CALIBRATION] ---------------------------------------------------------------------");
461
- ESP_LOGI(TAG,
462
- "[CALIBRATION] | Phase | V_meas (V) | I_meas (A) | V_ref | I_ref | V_gain (old→new) | I_gain (old→new) |");
463
- ESP_LOGI(TAG, "[CALIBRATION] ---------------------------------------------------------------------");
594
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
595
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ========================= Gain Calibration =========================", cs);
596
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
597
+ ESP_LOGI(
598
+ TAG,
599
+ "[CALIBRATION][%s] | Phase | V_meas (V) | I_meas (A) | V_ref | I_ref | V_gain (old→new) | I_gain (old→new) |",
600
+ cs);
601
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
464
602
 
465
603
  for (uint8_t phase = 0; phase < 3; phase++) {
466
604
  float measured_voltage = this->get_phase_voltage_avg_(phase);
@@ -477,22 +615,22 @@ void ATM90E32Component::run_gain_calibrations() {
477
615
 
478
616
  // Voltage calibration
479
617
  if (ref_voltage <= 0.0f) {
480
- ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Skipping voltage calibration: reference voltage is 0.",
618
+ ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Skipping voltage calibration: reference voltage is 0.", cs,
481
619
  phase_labels[phase]);
482
620
  } else if (measured_voltage == 0.0f) {
483
- ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Skipping voltage calibration: measured voltage is 0.",
621
+ ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Skipping voltage calibration: measured voltage is 0.", cs,
484
622
  phase_labels[phase]);
485
623
  } else {
486
624
  uint32_t new_voltage_gain = static_cast<uint16_t>((ref_voltage / measured_voltage) * current_voltage_gain);
487
625
  if (new_voltage_gain == 0) {
488
- ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Voltage gain would be 0. Check reference and measured voltage.",
626
+ ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Voltage gain would be 0. Check reference and measured voltage.", cs,
489
627
  phase_labels[phase]);
490
628
  } else {
491
629
  if (new_voltage_gain >= 65535) {
492
- ESP_LOGW(
493
- TAG,
494
- "[CALIBRATION] Phase %s - Voltage gain exceeds 65535. You may need a higher output voltage transformer.",
495
- phase_labels[phase]);
630
+ ESP_LOGW(TAG,
631
+ "[CALIBRATION][%s] Phase %s - Voltage gain exceeds 65535. You may need a higher output voltage "
632
+ "transformer.",
633
+ cs, phase_labels[phase]);
496
634
  new_voltage_gain = 65535;
497
635
  }
498
636
  this->gain_phase_[phase].voltage_gain = static_cast<uint16_t>(new_voltage_gain);
@@ -502,20 +640,20 @@ void ATM90E32Component::run_gain_calibrations() {
502
640
 
503
641
  // Current calibration
504
642
  if (ref_current == 0.0f) {
505
- ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Skipping current calibration: reference current is 0.",
643
+ ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Skipping current calibration: reference current is 0.", cs,
506
644
  phase_labels[phase]);
507
645
  } else if (measured_current == 0.0f) {
508
- ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Skipping current calibration: measured current is 0.",
646
+ ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Skipping current calibration: measured current is 0.", cs,
509
647
  phase_labels[phase]);
510
648
  } else {
511
649
  uint32_t new_current_gain = static_cast<uint16_t>((ref_current / measured_current) * current_current_gain);
512
650
  if (new_current_gain == 0) {
513
- ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Current gain would be 0. Check reference and measured current.",
651
+ ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Current gain would be 0. Check reference and measured current.", cs,
514
652
  phase_labels[phase]);
515
653
  } else {
516
654
  if (new_current_gain >= 65535) {
517
- ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Current gain exceeds 65535. You may need to turn up pga gain.",
518
- phase_labels[phase]);
655
+ ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Current gain exceeds 65535. You may need to turn up pga gain.",
656
+ cs, phase_labels[phase]);
519
657
  new_current_gain = 65535;
520
658
  }
521
659
  this->gain_phase_[phase].current_gain = static_cast<uint16_t>(new_current_gain);
@@ -524,13 +662,13 @@ void ATM90E32Component::run_gain_calibrations() {
524
662
  }
525
663
 
526
664
  // Final row output
527
- ESP_LOGI(TAG, "[CALIBRATION] | %c | %9.2f | %9.4f | %5.2f | %6.4f | %5u → %-5u | %5u → %-5u |",
665
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %9.2f | %9.4f | %5.2f | %6.4f | %5u → %-5u | %5u → %-5u |", cs,
528
666
  'A' + phase, measured_voltage, measured_current, ref_voltage, ref_current, current_voltage_gain,
529
667
  did_voltage ? this->gain_phase_[phase].voltage_gain : current_voltage_gain, current_current_gain,
530
668
  did_current ? this->gain_phase_[phase].current_gain : current_current_gain);
531
669
  }
532
670
 
533
- ESP_LOGI(TAG, "[CALIBRATION] =====================================================================\n");
671
+ ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\n", cs);
534
672
 
535
673
  this->save_gain_calibration_to_memory_();
536
674
  this->write_gains_to_registers_();
@@ -538,54 +676,108 @@ void ATM90E32Component::run_gain_calibrations() {
538
676
  }
539
677
 
540
678
  void ATM90E32Component::save_gain_calibration_to_memory_() {
679
+ const char *cs = this->cs_summary_.c_str();
541
680
  bool success = this->gain_calibration_pref_.save(&this->gain_phase_);
681
+ global_preferences->sync();
542
682
  if (success) {
543
683
  this->using_saved_calibrations_ = true;
544
- ESP_LOGI(TAG, "[CALIBRATION] Gain calibration saved to memory.");
684
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Gain calibration saved to memory.", cs);
545
685
  } else {
546
686
  this->using_saved_calibrations_ = false;
547
- ESP_LOGE(TAG, "[CALIBRATION] Failed to save gain calibration to memory!");
687
+ ESP_LOGE(TAG, "[CALIBRATION][%s] Failed to save gain calibration to memory!", cs);
688
+ }
689
+ }
690
+
691
+ void ATM90E32Component::save_offset_calibration_to_memory_() {
692
+ const char *cs = this->cs_summary_.c_str();
693
+ bool success = this->offset_pref_.save(&this->offset_phase_);
694
+ global_preferences->sync();
695
+ if (success) {
696
+ this->using_saved_calibrations_ = true;
697
+ this->restored_offset_calibration_ = true;
698
+ for (bool &phase : this->offset_calibration_mismatch_)
699
+ phase = false;
700
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Offset calibration saved to memory.", cs);
701
+ } else {
702
+ this->using_saved_calibrations_ = false;
703
+ ESP_LOGE(TAG, "[CALIBRATION][%s] Failed to save offset calibration to memory!", cs);
704
+ }
705
+ }
706
+
707
+ void ATM90E32Component::save_power_offset_calibration_to_memory_() {
708
+ const char *cs = this->cs_summary_.c_str();
709
+ bool success = this->power_offset_pref_.save(&this->power_offset_phase_);
710
+ global_preferences->sync();
711
+ if (success) {
712
+ this->using_saved_calibrations_ = true;
713
+ this->restored_power_offset_calibration_ = true;
714
+ for (bool &phase : this->power_offset_calibration_mismatch_)
715
+ phase = false;
716
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Power offset calibration saved to memory.", cs);
717
+ } else {
718
+ this->using_saved_calibrations_ = false;
719
+ ESP_LOGE(TAG, "[CALIBRATION][%s] Failed to save power offset calibration to memory!", cs);
548
720
  }
549
721
  }
550
722
 
551
723
  void ATM90E32Component::run_offset_calibrations() {
724
+ const char *cs = this->cs_summary_.c_str();
552
725
  if (!this->enable_offset_calibration_) {
553
- ESP_LOGW(TAG, "[CALIBRATION] Offset calibration is disabled! Enable it first with enable_offset_calibration: true");
726
+ ESP_LOGW(TAG,
727
+ "[CALIBRATION][%s] Offset calibration is disabled! Enable it first with enable_offset_calibration: true",
728
+ cs);
554
729
  return;
555
730
  }
556
731
 
732
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
733
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ======================== Offset Calibration ========================", cs);
734
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------", cs);
735
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_voltage | offset_current |", cs);
736
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------", cs);
737
+
557
738
  for (uint8_t phase = 0; phase < 3; phase++) {
558
739
  int16_t voltage_offset = calibrate_offset(phase, true);
559
740
  int16_t current_offset = calibrate_offset(phase, false);
560
741
 
561
742
  this->write_offsets_to_registers_(phase, voltage_offset, current_offset);
562
743
 
563
- ESP_LOGI(TAG, "[CALIBRATION] Phase %c - offset_voltage: %d, offset_current: %d", 'A' + phase, voltage_offset,
744
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase, voltage_offset,
564
745
  current_offset);
565
746
  }
566
747
 
567
- this->offset_pref_.save(&this->offset_phase_); // Save to flash
748
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ==================================================================\n", cs);
749
+
750
+ this->save_offset_calibration_to_memory_();
568
751
  }
569
752
 
570
753
  void ATM90E32Component::run_power_offset_calibrations() {
754
+ const char *cs = this->cs_summary_.c_str();
571
755
  if (!this->enable_offset_calibration_) {
572
756
  ESP_LOGW(
573
757
  TAG,
574
- "[CALIBRATION] Offset power calibration is disabled! Enable it first with enable_offset_calibration: true");
758
+ "[CALIBRATION][%s] Offset power calibration is disabled! Enable it first with enable_offset_calibration: true",
759
+ cs);
575
760
  return;
576
761
  }
577
762
 
763
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
764
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ===================== Power Offset Calibration =====================", cs);
765
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
766
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_active_power | offset_reactive_power |", cs);
767
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
768
+
578
769
  for (uint8_t phase = 0; phase < 3; ++phase) {
579
770
  int16_t active_offset = calibrate_power_offset(phase, false);
580
771
  int16_t reactive_offset = calibrate_power_offset(phase, true);
581
772
 
582
773
  this->write_power_offsets_to_registers_(phase, active_offset, reactive_offset);
583
774
 
584
- ESP_LOGI(TAG, "[CALIBRATION] Phase %c - offset_active_power: %d, offset_reactive_power: %d", 'A' + phase,
585
- active_offset, reactive_offset);
775
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase, active_offset,
776
+ reactive_offset);
586
777
  }
778
+ ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\n", cs);
587
779
 
588
- this->power_offset_pref_.save(&this->power_offset_phase_); // Save to flash
780
+ this->save_power_offset_calibration_to_memory_();
589
781
  }
590
782
 
591
783
  void ATM90E32Component::write_gains_to_registers_() {
@@ -632,102 +824,276 @@ void ATM90E32Component::write_power_offsets_to_registers_(uint8_t phase, int16_t
632
824
  }
633
825
 
634
826
  void ATM90E32Component::restore_gain_calibrations_() {
635
- if (this->gain_calibration_pref_.load(&this->gain_phase_)) {
636
- ESP_LOGI(TAG, "[CALIBRATION] Restoring saved gain calibrations to registers:");
827
+ const char *cs = this->cs_summary_.c_str();
828
+ for (uint8_t i = 0; i < 3; ++i) {
829
+ this->config_gain_phase_[i].voltage_gain = this->phase_[i].voltage_gain_;
830
+ this->config_gain_phase_[i].current_gain = this->phase_[i].ct_gain_;
831
+ this->gain_phase_[i] = this->config_gain_phase_[i];
832
+ }
637
833
 
638
- for (uint8_t phase = 0; phase < 3; phase++) {
639
- uint16_t v_gain = this->gain_phase_[phase].voltage_gain;
640
- uint16_t i_gain = this->gain_phase_[phase].current_gain;
641
- ESP_LOGI(TAG, "[CALIBRATION] Phase %c - Voltage Gain: %u, Current Gain: %u", 'A' + phase, v_gain, i_gain);
834
+ if (this->gain_calibration_pref_.load(&this->gain_phase_)) {
835
+ bool all_zero = true;
836
+ bool same_as_config = true;
837
+ for (uint8_t phase = 0; phase < 3; ++phase) {
838
+ const auto &cfg = this->config_gain_phase_[phase];
839
+ const auto &saved = this->gain_phase_[phase];
840
+ if (saved.voltage_gain != 0 || saved.current_gain != 0)
841
+ all_zero = false;
842
+ if (saved.voltage_gain != cfg.voltage_gain || saved.current_gain != cfg.current_gain)
843
+ same_as_config = false;
642
844
  }
643
845
 
644
- this->write_gains_to_registers_();
846
+ if (!all_zero && !same_as_config) {
847
+ for (uint8_t phase = 0; phase < 3; ++phase) {
848
+ bool mismatch = false;
849
+ if (this->has_config_voltage_gain_[phase] &&
850
+ this->gain_phase_[phase].voltage_gain != this->config_gain_phase_[phase].voltage_gain)
851
+ mismatch = true;
852
+ if (this->has_config_current_gain_[phase] &&
853
+ this->gain_phase_[phase].current_gain != this->config_gain_phase_[phase].current_gain)
854
+ mismatch = true;
855
+ if (mismatch)
856
+ this->gain_calibration_mismatch_[phase] = true;
857
+ }
858
+
859
+ this->write_gains_to_registers_();
860
+
861
+ if (this->verify_gain_writes_()) {
862
+ this->using_saved_calibrations_ = true;
863
+ this->restored_gain_calibration_ = true;
864
+ return;
865
+ }
645
866
 
646
- if (this->verify_gain_writes_()) {
647
- this->using_saved_calibrations_ = true;
648
- ESP_LOGI(TAG, "[CALIBRATION] Gain calibration loaded and verified successfully.");
649
- } else {
650
867
  this->using_saved_calibrations_ = false;
651
- ESP_LOGE(TAG, "[CALIBRATION] Gain verification failed! Calibration may not be applied correctly.");
868
+ ESP_LOGE(TAG, "[CALIBRATION][%s] Gain verification failed! Calibration may not be applied correctly.", cs);
652
869
  }
653
- } else {
654
- this->using_saved_calibrations_ = false;
655
- ESP_LOGW(TAG, "[CALIBRATION] No stored gain calibrations found. Using config file values.");
656
870
  }
871
+
872
+ this->using_saved_calibrations_ = false;
873
+ for (uint8_t i = 0; i < 3; ++i)
874
+ this->gain_phase_[i] = this->config_gain_phase_[i];
875
+ this->write_gains_to_registers_();
876
+
877
+ ESP_LOGW(TAG, "[CALIBRATION][%s] No stored gain calibrations found. Using config file values.", cs);
657
878
  }
658
879
 
659
880
  void ATM90E32Component::restore_offset_calibrations_() {
660
- if (this->offset_pref_.load(&this->offset_phase_)) {
661
- ESP_LOGI(TAG, "[CALIBRATION] Successfully restored offset calibration from memory.");
881
+ const char *cs = this->cs_summary_.c_str();
882
+ for (uint8_t i = 0; i < 3; ++i)
883
+ this->config_offset_phase_[i] = this->offset_phase_[i];
884
+
885
+ bool have_data = this->offset_pref_.load(&this->offset_phase_);
886
+ bool all_zero = true;
887
+ if (have_data) {
888
+ for (auto &phase : this->offset_phase_) {
889
+ if (phase.voltage_offset_ != 0 || phase.current_offset_ != 0) {
890
+ all_zero = false;
891
+ break;
892
+ }
893
+ }
894
+ }
662
895
 
896
+ if (have_data && !all_zero) {
897
+ this->restored_offset_calibration_ = true;
663
898
  for (uint8_t phase = 0; phase < 3; phase++) {
664
899
  auto &offset = this->offset_phase_[phase];
665
- write_offsets_to_registers_(phase, offset.voltage_offset_, offset.current_offset_);
666
- ESP_LOGI(TAG, "[CALIBRATION] Phase %c - offset_voltage:: %d, offset_current: %d", 'A' + phase,
667
- offset.voltage_offset_, offset.current_offset_);
900
+ bool mismatch = false;
901
+ if (this->has_config_voltage_offset_[phase] &&
902
+ offset.voltage_offset_ != this->config_offset_phase_[phase].voltage_offset_)
903
+ mismatch = true;
904
+ if (this->has_config_current_offset_[phase] &&
905
+ offset.current_offset_ != this->config_offset_phase_[phase].current_offset_)
906
+ mismatch = true;
907
+ if (mismatch)
908
+ this->offset_calibration_mismatch_[phase] = true;
668
909
  }
669
910
  } else {
670
- ESP_LOGW(TAG, "[CALIBRATION] No stored offset calibrations found. Using default values.");
911
+ for (uint8_t phase = 0; phase < 3; phase++)
912
+ this->offset_phase_[phase] = this->config_offset_phase_[phase];
913
+ ESP_LOGW(TAG, "[CALIBRATION][%s] No stored offset calibrations found. Using default values.", cs);
914
+ }
915
+
916
+ for (uint8_t phase = 0; phase < 3; phase++) {
917
+ write_offsets_to_registers_(phase, this->offset_phase_[phase].voltage_offset_,
918
+ this->offset_phase_[phase].current_offset_);
671
919
  }
672
920
  }
673
921
 
674
922
  void ATM90E32Component::restore_power_offset_calibrations_() {
675
- if (this->power_offset_pref_.load(&this->power_offset_phase_)) {
676
- ESP_LOGI(TAG, "[CALIBRATION] Successfully restored power offset calibration from memory.");
923
+ const char *cs = this->cs_summary_.c_str();
924
+ for (uint8_t i = 0; i < 3; ++i)
925
+ this->config_power_offset_phase_[i] = this->power_offset_phase_[i];
926
+
927
+ bool have_data = this->power_offset_pref_.load(&this->power_offset_phase_);
928
+ bool all_zero = true;
929
+ if (have_data) {
930
+ for (auto &phase : this->power_offset_phase_) {
931
+ if (phase.active_power_offset != 0 || phase.reactive_power_offset != 0) {
932
+ all_zero = false;
933
+ break;
934
+ }
935
+ }
936
+ }
677
937
 
938
+ if (have_data && !all_zero) {
939
+ this->restored_power_offset_calibration_ = true;
678
940
  for (uint8_t phase = 0; phase < 3; ++phase) {
679
941
  auto &offset = this->power_offset_phase_[phase];
680
- write_power_offsets_to_registers_(phase, offset.active_power_offset, offset.reactive_power_offset);
681
- ESP_LOGI(TAG, "[CALIBRATION] Phase %c - offset_active_power: %d, offset_reactive_power: %d", 'A' + phase,
682
- offset.active_power_offset, offset.reactive_power_offset);
942
+ bool mismatch = false;
943
+ if (this->has_config_active_power_offset_[phase] &&
944
+ offset.active_power_offset != this->config_power_offset_phase_[phase].active_power_offset)
945
+ mismatch = true;
946
+ if (this->has_config_reactive_power_offset_[phase] &&
947
+ offset.reactive_power_offset != this->config_power_offset_phase_[phase].reactive_power_offset)
948
+ mismatch = true;
949
+ if (mismatch)
950
+ this->power_offset_calibration_mismatch_[phase] = true;
683
951
  }
684
952
  } else {
685
- ESP_LOGW(TAG, "[CALIBRATION] No stored power offsets found. Using default values.");
953
+ for (uint8_t phase = 0; phase < 3; ++phase)
954
+ this->power_offset_phase_[phase] = this->config_power_offset_phase_[phase];
955
+ ESP_LOGW(TAG, "[CALIBRATION][%s] No stored power offsets found. Using default values.", cs);
956
+ }
957
+
958
+ for (uint8_t phase = 0; phase < 3; ++phase) {
959
+ write_power_offsets_to_registers_(phase, this->power_offset_phase_[phase].active_power_offset,
960
+ this->power_offset_phase_[phase].reactive_power_offset);
686
961
  }
687
962
  }
688
963
 
689
964
  void ATM90E32Component::clear_gain_calibrations() {
690
- ESP_LOGI(TAG, "[CALIBRATION] Clearing stored gain calibrations and restoring config-defined values");
965
+ const char *cs = this->cs_summary_.c_str();
966
+ if (!this->using_saved_calibrations_) {
967
+ ESP_LOGI(TAG, "[CALIBRATION][%s] No stored gain calibrations to clear. Current values:", cs);
968
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ----------------------------------------------------------", cs);
969
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | voltage_gain | current_gain |", cs);
970
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ----------------------------------------------------------", cs);
971
+ for (int phase = 0; phase < 3; phase++) {
972
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6u | %6u |", cs, 'A' + phase,
973
+ this->gain_phase_[phase].voltage_gain, this->gain_phase_[phase].current_gain);
974
+ }
975
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ==========================================================\n", cs);
976
+ return;
977
+ }
978
+
979
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Clearing stored gain calibrations and restoring config-defined values", cs);
980
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ----------------------------------------------------------", cs);
981
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | voltage_gain | current_gain |", cs);
982
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ----------------------------------------------------------", cs);
691
983
 
692
984
  for (int phase = 0; phase < 3; phase++) {
693
- gain_phase_[phase].voltage_gain = this->phase_[phase].voltage_gain_;
694
- gain_phase_[phase].current_gain = this->phase_[phase].ct_gain_;
985
+ uint16_t voltage_gain = this->phase_[phase].voltage_gain_;
986
+ uint16_t current_gain = this->phase_[phase].ct_gain_;
987
+
988
+ this->config_gain_phase_[phase].voltage_gain = voltage_gain;
989
+ this->config_gain_phase_[phase].current_gain = current_gain;
990
+ this->gain_phase_[phase].voltage_gain = voltage_gain;
991
+ this->gain_phase_[phase].current_gain = current_gain;
992
+
993
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6u | %6u |", cs, 'A' + phase, voltage_gain, current_gain);
695
994
  }
995
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ==========================================================\n", cs);
996
+
997
+ GainCalibration zero_gains[3]{{0, 0}, {0, 0}, {0, 0}};
998
+ bool success = this->gain_calibration_pref_.save(&zero_gains);
999
+ global_preferences->sync();
696
1000
 
697
- bool success = this->gain_calibration_pref_.save(&this->gain_phase_);
698
1001
  this->using_saved_calibrations_ = false;
1002
+ this->restored_gain_calibration_ = false;
1003
+ for (bool &phase : this->gain_calibration_mismatch_)
1004
+ phase = false;
699
1005
 
700
- if (success) {
701
- ESP_LOGI(TAG, "[CALIBRATION] Gain calibrations cleared. Config values restored:");
702
- for (int phase = 0; phase < 3; phase++) {
703
- ESP_LOGI(TAG, "[CALIBRATION] Phase %c - Voltage Gain: %u, Current Gain: %u", 'A' + phase,
704
- gain_phase_[phase].voltage_gain, gain_phase_[phase].current_gain);
705
- }
706
- } else {
707
- ESP_LOGE(TAG, "[CALIBRATION] Failed to clear gain calibrations!");
1006
+ if (!success) {
1007
+ ESP_LOGE(TAG, "[CALIBRATION][%s] Failed to clear gain calibrations!", cs);
708
1008
  }
709
1009
 
710
1010
  this->write_gains_to_registers_(); // Apply them to the chip immediately
711
1011
  }
712
1012
 
713
1013
  void ATM90E32Component::clear_offset_calibrations() {
1014
+ const char *cs = this->cs_summary_.c_str();
1015
+ if (!this->restored_offset_calibration_) {
1016
+ ESP_LOGI(TAG, "[CALIBRATION][%s] No stored offset calibrations to clear. Current values:", cs);
1017
+ ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
1018
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_voltage | offset_current |", cs);
1019
+ ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
1020
+ for (uint8_t phase = 0; phase < 3; phase++) {
1021
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase,
1022
+ this->offset_phase_[phase].voltage_offset_, this->offset_phase_[phase].current_offset_);
1023
+ }
1024
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ==============================================================\n", cs);
1025
+ return;
1026
+ }
1027
+
1028
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Clearing stored offset calibrations and restoring config-defined values", cs);
1029
+ ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
1030
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_voltage | offset_current |", cs);
1031
+ ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
1032
+
714
1033
  for (uint8_t phase = 0; phase < 3; phase++) {
715
- this->write_offsets_to_registers_(phase, 0, 0);
1034
+ int16_t voltage_offset =
1035
+ this->has_config_voltage_offset_[phase] ? this->config_offset_phase_[phase].voltage_offset_ : 0;
1036
+ int16_t current_offset =
1037
+ this->has_config_current_offset_[phase] ? this->config_offset_phase_[phase].current_offset_ : 0;
1038
+ this->write_offsets_to_registers_(phase, voltage_offset, current_offset);
1039
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase, voltage_offset,
1040
+ current_offset);
716
1041
  }
1042
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ==============================================================\n", cs);
717
1043
 
718
- this->offset_pref_.save(&this->offset_phase_); // Save cleared values to flash memory
1044
+ OffsetCalibration zero_offsets[3]{{0, 0}, {0, 0}, {0, 0}};
1045
+ this->offset_pref_.save(&zero_offsets); // Clear stored values in flash
1046
+ global_preferences->sync();
719
1047
 
720
- ESP_LOGI(TAG, "[CALIBRATION] Offsets cleared.");
1048
+ this->restored_offset_calibration_ = false;
1049
+ for (bool &phase : this->offset_calibration_mismatch_)
1050
+ phase = false;
1051
+
1052
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Offsets cleared.", cs);
721
1053
  }
722
1054
 
723
1055
  void ATM90E32Component::clear_power_offset_calibrations() {
1056
+ const char *cs = this->cs_summary_.c_str();
1057
+ if (!this->restored_power_offset_calibration_) {
1058
+ ESP_LOGI(TAG, "[CALIBRATION][%s] No stored power offsets to clear. Current values:", cs);
1059
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
1060
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_active_power | offset_reactive_power |", cs);
1061
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
1062
+ for (uint8_t phase = 0; phase < 3; phase++) {
1063
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase,
1064
+ this->power_offset_phase_[phase].active_power_offset,
1065
+ this->power_offset_phase_[phase].reactive_power_offset);
1066
+ }
1067
+ ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\n", cs);
1068
+ return;
1069
+ }
1070
+
1071
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Clearing stored power offsets and restoring config-defined values", cs);
1072
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
1073
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_active_power | offset_reactive_power |", cs);
1074
+ ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
1075
+
724
1076
  for (uint8_t phase = 0; phase < 3; phase++) {
725
- this->write_power_offsets_to_registers_(phase, 0, 0);
1077
+ int16_t active_offset =
1078
+ this->has_config_active_power_offset_[phase] ? this->config_power_offset_phase_[phase].active_power_offset : 0;
1079
+ int16_t reactive_offset = this->has_config_reactive_power_offset_[phase]
1080
+ ? this->config_power_offset_phase_[phase].reactive_power_offset
1081
+ : 0;
1082
+ this->write_power_offsets_to_registers_(phase, active_offset, reactive_offset);
1083
+ ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase, active_offset,
1084
+ reactive_offset);
726
1085
  }
1086
+ ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\n", cs);
727
1087
 
728
- this->power_offset_pref_.save(&this->power_offset_phase_);
1088
+ PowerOffsetCalibration zero_power_offsets[3]{{0, 0}, {0, 0}, {0, 0}};
1089
+ this->power_offset_pref_.save(&zero_power_offsets);
1090
+ global_preferences->sync();
729
1091
 
730
- ESP_LOGI(TAG, "[CALIBRATION] Power offsets cleared.");
1092
+ this->restored_power_offset_calibration_ = false;
1093
+ for (bool &phase : this->power_offset_calibration_mismatch_)
1094
+ phase = false;
1095
+
1096
+ ESP_LOGI(TAG, "[CALIBRATION][%s] Power offsets cleared.", cs);
731
1097
  }
732
1098
 
733
1099
  int16_t ATM90E32Component::calibrate_offset(uint8_t phase, bool voltage) {
@@ -748,20 +1114,21 @@ int16_t ATM90E32Component::calibrate_offset(uint8_t phase, bool voltage) {
748
1114
 
749
1115
  int16_t ATM90E32Component::calibrate_power_offset(uint8_t phase, bool reactive) {
750
1116
  const uint8_t num_reads = 5;
751
- uint64_t total_value = 0;
1117
+ int64_t total_value = 0;
752
1118
 
753
1119
  for (uint8_t i = 0; i < num_reads; ++i) {
754
- uint32_t reading = reactive ? this->read32_(ATM90E32_REGISTER_QMEAN + phase, ATM90E32_REGISTER_QMEANLSB + phase)
755
- : this->read32_(ATM90E32_REGISTER_PMEAN + phase, ATM90E32_REGISTER_PMEANLSB + phase);
1120
+ int32_t reading = reactive ? this->read32_(ATM90E32_REGISTER_QMEAN + phase, ATM90E32_REGISTER_QMEANLSB + phase)
1121
+ : this->read32_(ATM90E32_REGISTER_PMEAN + phase, ATM90E32_REGISTER_PMEANLSB + phase);
756
1122
  total_value += reading;
757
1123
  }
758
1124
 
759
- const uint32_t average_value = total_value / num_reads;
760
- const uint32_t power_offset = ~average_value + 1;
1125
+ int32_t average_value = total_value / num_reads;
1126
+ int32_t power_offset = -average_value;
761
1127
  return static_cast<int16_t>(power_offset); // Takes the lower 16 bits
762
1128
  }
763
1129
 
764
1130
  bool ATM90E32Component::verify_gain_writes_() {
1131
+ const char *cs = this->cs_summary_.c_str();
765
1132
  bool success = true;
766
1133
  for (uint8_t phase = 0; phase < 3; phase++) {
767
1134
  uint16_t read_voltage = this->read16_(voltage_gain_registers[phase]);
@@ -769,7 +1136,7 @@ bool ATM90E32Component::verify_gain_writes_() {
769
1136
 
770
1137
  if (read_voltage != this->gain_phase_[phase].voltage_gain ||
771
1138
  read_current != this->gain_phase_[phase].current_gain) {
772
- ESP_LOGE(TAG, "[CALIBRATION] Mismatch detected for Phase %s!", phase_labels[phase]);
1139
+ ESP_LOGE(TAG, "[CALIBRATION][%s] Mismatch detected for Phase %s!", cs, phase_labels[phase]);
773
1140
  success = false;
774
1141
  }
775
1142
  }
@@ -792,16 +1159,16 @@ void ATM90E32Component::check_phase_status() {
792
1159
  status += "Phase Loss; ";
793
1160
 
794
1161
  auto *sensor = this->phase_status_text_sensor_[phase];
795
- const char *phase_name = sensor ? sensor->get_name().c_str() : "Unknown Phase";
1162
+ if (sensor == nullptr)
1163
+ continue;
1164
+
796
1165
  if (!status.empty()) {
797
1166
  status.pop_back(); // remove space
798
1167
  status.pop_back(); // remove semicolon
799
- ESP_LOGW(TAG, "%s: %s", phase_name, status.c_str());
800
- if (sensor != nullptr)
801
- sensor->publish_state(status);
1168
+ ESP_LOGW(TAG, "%s: %s", sensor->get_name().c_str(), status.c_str());
1169
+ sensor->publish_state(status);
802
1170
  } else {
803
- if (sensor != nullptr)
804
- sensor->publish_state("Okay");
1171
+ sensor->publish_state("Okay");
805
1172
  }
806
1173
  }
807
1174
  }
@@ -818,9 +1185,12 @@ void ATM90E32Component::check_freq_status() {
818
1185
  } else {
819
1186
  freq_status = "Normal";
820
1187
  }
821
- ESP_LOGW(TAG, "Frequency status: %s", freq_status.c_str());
822
-
823
1188
  if (this->freq_status_text_sensor_ != nullptr) {
1189
+ if (freq_status == "Normal") {
1190
+ ESP_LOGD(TAG, "Frequency status: %s", freq_status.c_str());
1191
+ } else {
1192
+ ESP_LOGW(TAG, "Frequency status: %s", freq_status.c_str());
1193
+ }
824
1194
  this->freq_status_text_sensor_->publish_state(freq_status);
825
1195
  }
826
1196
  }