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
@@ -7,28 +7,26 @@ namespace bl0940 {
7
7
 
8
8
  static const char *const TAG = "bl0940";
9
9
 
10
- static const uint8_t BL0940_READ_COMMAND = 0x50; // 0x58 according to documentation
11
10
  static const uint8_t BL0940_FULL_PACKET = 0xAA;
12
- static const uint8_t BL0940_PACKET_HEADER = 0x55; // 0x58 according to documentation
11
+ static const uint8_t BL0940_PACKET_HEADER = 0x55; // 0x58 according to en doc but 0x55 in cn doc
13
12
 
14
- static const uint8_t BL0940_WRITE_COMMAND = 0xA0; // 0xA8 according to documentation
15
13
  static const uint8_t BL0940_REG_I_FAST_RMS_CTRL = 0x10;
16
14
  static const uint8_t BL0940_REG_MODE = 0x18;
17
15
  static const uint8_t BL0940_REG_SOFT_RESET = 0x19;
18
16
  static const uint8_t BL0940_REG_USR_WRPROT = 0x1A;
19
17
  static const uint8_t BL0940_REG_TPS_CTRL = 0x1B;
20
18
 
21
- const uint8_t BL0940_INIT[5][6] = {
19
+ static const uint8_t BL0940_INIT[5][5] = {
22
20
  // Reset to default
23
- {BL0940_WRITE_COMMAND, BL0940_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A, 0x38},
21
+ {BL0940_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A, 0x38},
24
22
  // Enable User Operation Write
25
- {BL0940_WRITE_COMMAND, BL0940_REG_USR_WRPROT, 0x55, 0x00, 0x00, 0xF0},
23
+ {BL0940_REG_USR_WRPROT, 0x55, 0x00, 0x00, 0xF0},
26
24
  // 0x0100 = CF_UNABLE energy pulse, AC_FREQ_SEL 50Hz, RMS_UPDATE_SEL 800mS
27
- {BL0940_WRITE_COMMAND, BL0940_REG_MODE, 0x00, 0x10, 0x00, 0x37},
25
+ {BL0940_REG_MODE, 0x00, 0x10, 0x00, 0x37},
28
26
  // 0x47FF = Over-current and leakage alarm on, Automatic temperature measurement, Interval 100mS
29
- {BL0940_WRITE_COMMAND, BL0940_REG_TPS_CTRL, 0xFF, 0x47, 0x00, 0xFE},
27
+ {BL0940_REG_TPS_CTRL, 0xFF, 0x47, 0x00, 0xFE},
30
28
  // 0x181C = Half cycle, Fast RMS threshold 6172
31
- {BL0940_WRITE_COMMAND, BL0940_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00, 0x1B}};
29
+ {BL0940_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00, 0x1B}};
32
30
 
33
31
  void BL0940::loop() {
34
32
  DataPacket buffer;
@@ -36,8 +34,8 @@ void BL0940::loop() {
36
34
  return;
37
35
  }
38
36
  if (read_array((uint8_t *) &buffer, sizeof(buffer))) {
39
- if (validate_checksum(&buffer)) {
40
- received_package_(&buffer);
37
+ if (this->validate_checksum_(&buffer)) {
38
+ this->received_package_(&buffer);
41
39
  }
42
40
  } else {
43
41
  ESP_LOGW(TAG, "Junk on wire. Throwing away partial message");
@@ -46,35 +44,151 @@ void BL0940::loop() {
46
44
  }
47
45
  }
48
46
 
49
- bool BL0940::validate_checksum(const DataPacket *data) {
50
- uint8_t checksum = BL0940_READ_COMMAND;
47
+ bool BL0940::validate_checksum_(DataPacket *data) {
48
+ uint8_t checksum = this->read_command_;
51
49
  // Whole package but checksum
52
- for (uint32_t i = 0; i < sizeof(data->raw) - 1; i++) {
53
- checksum += data->raw[i];
50
+ uint8_t *raw = (uint8_t *) data;
51
+ for (uint32_t i = 0; i < sizeof(*data) - 1; i++) {
52
+ checksum += raw[i];
54
53
  }
55
54
  checksum ^= 0xFF;
56
55
  if (checksum != data->checksum) {
57
- ESP_LOGW(TAG, "BL0940 invalid checksum! 0x%02X != 0x%02X", checksum, data->checksum);
56
+ ESP_LOGW(TAG, "Invalid checksum! 0x%02X != 0x%02X", checksum, data->checksum);
58
57
  }
59
58
  return checksum == data->checksum;
60
59
  }
61
60
 
62
61
  void BL0940::update() {
63
62
  this->flush();
64
- this->write_byte(BL0940_READ_COMMAND);
63
+ this->write_byte(this->read_command_);
65
64
  this->write_byte(BL0940_FULL_PACKET);
66
65
  }
67
66
 
68
67
  void BL0940::setup() {
68
+ #ifdef USE_NUMBER
69
+ // add calibration callbacks
70
+ if (this->voltage_calibration_number_ != nullptr) {
71
+ this->voltage_calibration_number_->add_on_state_callback(
72
+ [this](float state) { this->voltage_calibration_callback_(state); });
73
+ if (this->voltage_calibration_number_->has_state()) {
74
+ this->voltage_calibration_callback_(this->voltage_calibration_number_->state);
75
+ }
76
+ }
77
+
78
+ if (this->current_calibration_number_ != nullptr) {
79
+ this->current_calibration_number_->add_on_state_callback(
80
+ [this](float state) { this->current_calibration_callback_(state); });
81
+ if (this->current_calibration_number_->has_state()) {
82
+ this->current_calibration_callback_(this->current_calibration_number_->state);
83
+ }
84
+ }
85
+
86
+ if (this->power_calibration_number_ != nullptr) {
87
+ this->power_calibration_number_->add_on_state_callback(
88
+ [this](float state) { this->power_calibration_callback_(state); });
89
+ if (this->power_calibration_number_->has_state()) {
90
+ this->power_calibration_callback_(this->power_calibration_number_->state);
91
+ }
92
+ }
93
+
94
+ if (this->energy_calibration_number_ != nullptr) {
95
+ this->energy_calibration_number_->add_on_state_callback(
96
+ [this](float state) { this->energy_calibration_callback_(state); });
97
+ if (this->energy_calibration_number_->has_state()) {
98
+ this->energy_calibration_callback_(this->energy_calibration_number_->state);
99
+ }
100
+ }
101
+ #endif
102
+
103
+ // calculate calibrated reference values
104
+ this->voltage_reference_cal_ = this->voltage_reference_ / this->voltage_cal_;
105
+ this->current_reference_cal_ = this->current_reference_ / this->current_cal_;
106
+ this->power_reference_cal_ = this->power_reference_ / this->power_cal_;
107
+ this->energy_reference_cal_ = this->energy_reference_ / this->energy_cal_;
108
+
69
109
  for (auto *i : BL0940_INIT) {
70
- this->write_array(i, 6);
110
+ this->write_byte(this->write_command_), this->write_array(i, 5);
71
111
  delay(1);
72
112
  }
73
113
  this->flush();
74
114
  }
75
115
 
76
- float BL0940::update_temp_(sensor::Sensor *sensor, ube16_t temperature) const {
77
- auto tb = (float) (temperature.h << 8 | temperature.l);
116
+ float BL0940::calculate_power_reference_() {
117
+ // calculate power reference based on voltage and current reference
118
+ return this->voltage_reference_cal_ * this->current_reference_cal_ * 4046 / 324004 / 79931;
119
+ }
120
+
121
+ float BL0940::calculate_energy_reference_() {
122
+ // formula: 3600000 * 4046 * RL * R1 * 1000 / (1638.4 * 256) / Vref² / (R1 + R2)
123
+ // or: power_reference_ * 3600000 / (1638.4 * 256)
124
+ return this->power_reference_cal_ * 3600000 / (1638.4 * 256);
125
+ }
126
+
127
+ float BL0940::calculate_calibration_value_(float state) { return (100 + state) / 100; }
128
+
129
+ void BL0940::reset_calibration() {
130
+ #ifdef USE_NUMBER
131
+ if (this->current_calibration_number_ != nullptr && this->current_cal_ != 1) {
132
+ this->current_calibration_number_->make_call().set_value(0).perform();
133
+ }
134
+ if (this->voltage_calibration_number_ != nullptr && this->voltage_cal_ != 1) {
135
+ this->voltage_calibration_number_->make_call().set_value(0).perform();
136
+ }
137
+ if (this->power_calibration_number_ != nullptr && this->power_cal_ != 1) {
138
+ this->power_calibration_number_->make_call().set_value(0).perform();
139
+ }
140
+ if (this->energy_calibration_number_ != nullptr && this->energy_cal_ != 1) {
141
+ this->energy_calibration_number_->make_call().set_value(0).perform();
142
+ }
143
+ #endif
144
+ ESP_LOGD(TAG, "external calibration values restored to initial state");
145
+ }
146
+
147
+ void BL0940::current_calibration_callback_(float state) {
148
+ this->current_cal_ = this->calculate_calibration_value_(state);
149
+ ESP_LOGV(TAG, "update current calibration state: %f", this->current_cal_);
150
+ this->recalibrate_();
151
+ }
152
+ void BL0940::voltage_calibration_callback_(float state) {
153
+ this->voltage_cal_ = this->calculate_calibration_value_(state);
154
+ ESP_LOGV(TAG, "update voltage calibration state: %f", this->voltage_cal_);
155
+ this->recalibrate_();
156
+ }
157
+ void BL0940::power_calibration_callback_(float state) {
158
+ this->power_cal_ = this->calculate_calibration_value_(state);
159
+ ESP_LOGV(TAG, "update power calibration state: %f", this->power_cal_);
160
+ this->recalibrate_();
161
+ }
162
+ void BL0940::energy_calibration_callback_(float state) {
163
+ this->energy_cal_ = this->calculate_calibration_value_(state);
164
+ ESP_LOGV(TAG, "update energy calibration state: %f", this->energy_cal_);
165
+ this->recalibrate_();
166
+ }
167
+
168
+ void BL0940::recalibrate_() {
169
+ ESP_LOGV(TAG, "Recalibrating reference values");
170
+ this->voltage_reference_cal_ = this->voltage_reference_ / this->voltage_cal_;
171
+ this->current_reference_cal_ = this->current_reference_ / this->current_cal_;
172
+
173
+ if (this->voltage_cal_ != 1 || this->current_cal_ != 1) {
174
+ this->power_reference_ = this->calculate_power_reference_();
175
+ }
176
+ this->power_reference_cal_ = this->power_reference_ / this->power_cal_;
177
+
178
+ if (this->voltage_cal_ != 1 || this->current_cal_ != 1 || this->power_cal_ != 1) {
179
+ this->energy_reference_ = this->calculate_energy_reference_();
180
+ }
181
+ this->energy_reference_cal_ = this->energy_reference_ / this->energy_cal_;
182
+
183
+ ESP_LOGD(TAG,
184
+ "Recalibrated reference values:\n"
185
+ "Voltage: %f\n, Current: %f\n, Power: %f\n, Energy: %f\n",
186
+ this->voltage_reference_cal_, this->current_reference_cal_, this->power_reference_cal_,
187
+ this->energy_reference_cal_);
188
+ }
189
+
190
+ float BL0940::update_temp_(sensor::Sensor *sensor, uint16_le_t temperature) const {
191
+ auto tb = (float) temperature;
78
192
  float converted_temp = ((float) 170 / 448) * (tb / 2 - 32) - 45;
79
193
  if (sensor != nullptr) {
80
194
  if (sensor->has_state() && std::abs(converted_temp - sensor->get_state()) > max_temperature_diff_) {
@@ -87,33 +201,40 @@ float BL0940::update_temp_(sensor::Sensor *sensor, ube16_t temperature) const {
87
201
  return converted_temp;
88
202
  }
89
203
 
90
- void BL0940::received_package_(const DataPacket *data) const {
204
+ void BL0940::received_package_(DataPacket *data) {
91
205
  // Bad header
92
206
  if (data->frame_header != BL0940_PACKET_HEADER) {
93
207
  ESP_LOGI(TAG, "Invalid data. Header mismatch: %d", data->frame_header);
94
208
  return;
95
209
  }
96
210
 
97
- float v_rms = (float) to_uint32_t(data->v_rms) / voltage_reference_;
98
- float i_rms = (float) to_uint32_t(data->i_rms) / current_reference_;
99
- float watt = (float) to_int32_t(data->watt) / power_reference_;
100
- uint32_t cf_cnt = to_uint32_t(data->cf_cnt);
101
- float total_energy_consumption = (float) cf_cnt / energy_reference_;
211
+ // cf_cnt is only 24 bits, so track overflows
212
+ uint32_t cf_cnt = (uint24_t) data->cf_cnt;
213
+ cf_cnt |= this->prev_cf_cnt_ & 0xff000000;
214
+ if (cf_cnt < this->prev_cf_cnt_) {
215
+ cf_cnt += 0x1000000;
216
+ }
217
+ this->prev_cf_cnt_ = cf_cnt;
218
+
219
+ float v_rms = (uint24_t) data->v_rms / this->voltage_reference_cal_;
220
+ float i_rms = (uint24_t) data->i_rms / this->current_reference_cal_;
221
+ float watt = (int24_t) data->watt / this->power_reference_cal_;
222
+ float total_energy_consumption = cf_cnt / this->energy_reference_cal_;
102
223
 
103
- float tps1 = update_temp_(internal_temperature_sensor_, data->tps1);
104
- float tps2 = update_temp_(external_temperature_sensor_, data->tps2);
224
+ float tps1 = update_temp_(this->internal_temperature_sensor_, data->tps1);
225
+ float tps2 = update_temp_(this->external_temperature_sensor_, data->tps2);
105
226
 
106
- if (voltage_sensor_ != nullptr) {
107
- voltage_sensor_->publish_state(v_rms);
227
+ if (this->voltage_sensor_ != nullptr) {
228
+ this->voltage_sensor_->publish_state(v_rms);
108
229
  }
109
- if (current_sensor_ != nullptr) {
110
- current_sensor_->publish_state(i_rms);
230
+ if (this->current_sensor_ != nullptr) {
231
+ this->current_sensor_->publish_state(i_rms);
111
232
  }
112
- if (power_sensor_ != nullptr) {
113
- power_sensor_->publish_state(watt);
233
+ if (this->power_sensor_ != nullptr) {
234
+ this->power_sensor_->publish_state(watt);
114
235
  }
115
- if (energy_sensor_ != nullptr) {
116
- energy_sensor_->publish_state(total_energy_consumption);
236
+ if (this->energy_sensor_ != nullptr) {
237
+ this->energy_sensor_->publish_state(total_energy_consumption);
117
238
  }
118
239
 
119
240
  ESP_LOGV(TAG, "BL0940: U %fV, I %fA, P %fW, Cnt %" PRId32 ", ∫P %fkWh, T1 %f°C, T2 %f°C", v_rms, i_rms, watt, cf_cnt,
@@ -121,7 +242,27 @@ void BL0940::received_package_(const DataPacket *data) const {
121
242
  }
122
243
 
123
244
  void BL0940::dump_config() { // NOLINT(readability-function-cognitive-complexity)
124
- ESP_LOGCONFIG(TAG, "BL0940:");
245
+ ESP_LOGCONFIG(TAG,
246
+ "BL0940:\n"
247
+ " LEGACY MODE: %s\n"
248
+ " READ CMD: 0x%02X\n"
249
+ " WRITE CMD: 0x%02X\n"
250
+ " ------------------\n"
251
+ " Current reference: %f\n"
252
+ " Energy reference: %f\n"
253
+ " Power reference: %f\n"
254
+ " Voltage reference: %f\n",
255
+ TRUEFALSE(this->legacy_mode_enabled_), this->read_command_, this->write_command_,
256
+ this->current_reference_, this->energy_reference_, this->power_reference_, this->voltage_reference_);
257
+ #ifdef USE_NUMBER
258
+ ESP_LOGCONFIG(TAG,
259
+ "BL0940:\n"
260
+ " Current calibration: %f\n"
261
+ " Energy calibration: %f\n"
262
+ " Power calibration: %f\n"
263
+ " Voltage calibration: %f\n",
264
+ this->current_cal_, this->energy_cal_, this->power_cal_, this->voltage_cal_);
265
+ #endif
125
266
  LOG_SENSOR("", "Voltage", this->voltage_sensor_);
126
267
  LOG_SENSOR("", "Current", this->current_sensor_);
127
268
  LOG_SENSOR("", "Power", this->power_sensor_);
@@ -130,9 +271,5 @@ void BL0940::dump_config() { // NOLINT(readability-function-cognitive-complexit
130
271
  LOG_SENSOR("", "External temperature", this->external_temperature_sensor_);
131
272
  }
132
273
 
133
- uint32_t BL0940::to_uint32_t(ube24_t input) { return input.h << 16 | input.m << 8 | input.l; }
134
-
135
- int32_t BL0940::to_int32_t(sbe24_t input) { return input.h << 16 | input.m << 8 | input.l; }
136
-
137
274
  } // namespace bl0940
138
275
  } // namespace esphome
@@ -1,66 +1,48 @@
1
1
  #pragma once
2
2
 
3
3
  #include "esphome/core/component.h"
4
- #include "esphome/components/uart/uart.h"
4
+ #include "esphome/core/datatypes.h"
5
+ #include "esphome/core/defines.h"
6
+ #ifdef USE_BUTTON
7
+ #include "esphome/components/button/button.h"
8
+ #endif
9
+ #ifdef USE_NUMBER
10
+ #include "esphome/components/number/number.h"
11
+ #endif
5
12
  #include "esphome/components/sensor/sensor.h"
13
+ #include "esphome/components/uart/uart.h"
6
14
 
7
15
  namespace esphome {
8
16
  namespace bl0940 {
9
17
 
10
- static const float BL0940_PREF = 1430;
11
- static const float BL0940_UREF = 33000;
12
- static const float BL0940_IREF = 275000; // 2750 from tasmota. Seems to generate values 100 times too high
13
-
14
- // Measured to 297J per click according to power consumption of 5 minutes
15
- // Converted to kWh (3.6MJ per kwH). Used to be 256 * 1638.4
16
- static const float BL0940_EREF = 3.6e6 / 297;
17
-
18
- struct ube24_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align)
19
- uint8_t l;
20
- uint8_t m;
21
- uint8_t h;
22
- } __attribute__((packed));
23
-
24
- struct ube16_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align)
25
- uint8_t l;
26
- uint8_t h;
27
- } __attribute__((packed));
28
-
29
- struct sbe24_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align)
30
- uint8_t l;
31
- uint8_t m;
32
- int8_t h;
33
- } __attribute__((packed));
34
-
35
18
  // Caveat: All these values are big endian (low - middle - high)
36
-
37
- union DataPacket { // NOLINT(altera-struct-pack-align)
38
- uint8_t raw[35];
39
- struct {
40
- uint8_t frame_header; // value of 0x58 according to docs. 0x55 according to Tasmota real world tests. Reality wins.
41
- ube24_t i_fast_rms; // 0x00
42
- ube24_t i_rms; // 0x04
43
- ube24_t RESERVED0; // reserved
44
- ube24_t v_rms; // 0x06
45
- ube24_t RESERVED1; // reserved
46
- sbe24_t watt; // 0x08
47
- ube24_t RESERVED2; // reserved
48
- ube24_t cf_cnt; // 0x0A
49
- ube24_t RESERVED3; // reserved
50
- ube16_t tps1; // 0x0c
51
- uint8_t RESERVED4; // value of 0x00
52
- ube16_t tps2; // 0x0c
53
- uint8_t RESERVED5; // value of 0x00
54
- uint8_t checksum; // checksum
55
- };
19
+ struct DataPacket {
20
+ uint8_t frame_header; // Packet header (0x58 in EN docs, 0x55 in CN docs and Tasmota tests)
21
+ uint24_le_t i_fast_rms; // Fast RMS current
22
+ uint24_le_t i_rms; // RMS current
23
+ uint24_t RESERVED0; // Reserved
24
+ uint24_le_t v_rms; // RMS voltage
25
+ uint24_t RESERVED1; // Reserved
26
+ int24_le_t watt; // Active power (can be negative for bidirectional measurement)
27
+ uint24_t RESERVED2; // Reserved
28
+ uint24_le_t cf_cnt; // Energy pulse count
29
+ uint24_t RESERVED3; // Reserved
30
+ uint16_le_t tps1; // Internal temperature sensor 1
31
+ uint8_t RESERVED4; // Reserved (should be 0x00)
32
+ uint16_le_t tps2; // Internal temperature sensor 2
33
+ uint8_t RESERVED5; // Reserved (should be 0x00)
34
+ uint8_t checksum; // Packet checksum
56
35
  } __attribute__((packed));
57
36
 
58
37
  class BL0940 : public PollingComponent, public uart::UARTDevice {
59
38
  public:
39
+ // Sensor setters
60
40
  void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
61
41
  void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; }
62
42
  void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; }
63
43
  void set_energy_sensor(sensor::Sensor *energy_sensor) { energy_sensor_ = energy_sensor; }
44
+
45
+ // Temperature sensor setters
64
46
  void set_internal_temperature_sensor(sensor::Sensor *internal_temperature_sensor) {
65
47
  internal_temperature_sensor_ = internal_temperature_sensor;
66
48
  }
@@ -68,42 +50,105 @@ class BL0940 : public PollingComponent, public uart::UARTDevice {
68
50
  external_temperature_sensor_ = external_temperature_sensor;
69
51
  }
70
52
 
53
+ // Configuration setters
54
+ void set_legacy_mode(bool enable) { this->legacy_mode_enabled_ = enable; }
55
+ void set_read_command(uint8_t read_command) { this->read_command_ = read_command; }
56
+ void set_write_command(uint8_t write_command) { this->write_command_ = write_command; }
57
+
58
+ // Reference value setters (used for calibration and conversion)
59
+ void set_current_reference(float current_ref) { this->current_reference_ = current_ref; }
60
+ void set_energy_reference(float energy_ref) { this->energy_reference_ = energy_ref; }
61
+ void set_power_reference(float power_ref) { this->power_reference_ = power_ref; }
62
+ void set_voltage_reference(float voltage_ref) { this->voltage_reference_ = voltage_ref; }
63
+
64
+ #ifdef USE_NUMBER
65
+ // Calibration number setters (for Home Assistant number entities)
66
+ void set_current_calibration_number(number::Number *num) { this->current_calibration_number_ = num; }
67
+ void set_voltage_calibration_number(number::Number *num) { this->voltage_calibration_number_ = num; }
68
+ void set_power_calibration_number(number::Number *num) { this->power_calibration_number_ = num; }
69
+ void set_energy_calibration_number(number::Number *num) { this->energy_calibration_number_ = num; }
70
+ #endif
71
+
72
+ #ifdef USE_BUTTON
73
+ // Resets all calibration values to defaults (can be triggered by a button)
74
+ void reset_calibration();
75
+ #endif
76
+
77
+ // Core component methods
71
78
  void loop() override;
72
-
73
79
  void update() override;
74
80
  void setup() override;
75
81
  void dump_config() override;
76
82
 
77
83
  protected:
78
- sensor::Sensor *voltage_sensor_{nullptr};
79
- sensor::Sensor *current_sensor_{nullptr};
80
- // NB This may be negative as the circuits is seemingly able to measure
81
- // power in both directions
82
- sensor::Sensor *power_sensor_{nullptr};
83
- sensor::Sensor *energy_sensor_{nullptr};
84
- sensor::Sensor *internal_temperature_sensor_{nullptr};
85
- sensor::Sensor *external_temperature_sensor_{nullptr};
86
-
87
- // Max difference between two measurements of the temperature. Used to avoid noise.
88
- float max_temperature_diff_{0};
89
- // Divide by this to turn into Watt
90
- float power_reference_ = BL0940_PREF;
91
- // Divide by this to turn into Volt
92
- float voltage_reference_ = BL0940_UREF;
93
- // Divide by this to turn into Ampere
94
- float current_reference_ = BL0940_IREF;
95
- // Divide by this to turn into kWh
96
- float energy_reference_ = BL0940_EREF;
97
-
98
- float update_temp_(sensor::Sensor *sensor, ube16_t packed_temperature) const;
99
-
100
- static uint32_t to_uint32_t(ube24_t input);
101
-
102
- static int32_t to_int32_t(sbe24_t input);
103
-
104
- static bool validate_checksum(const DataPacket *data);
105
-
106
- void received_package_(const DataPacket *data) const;
84
+ // --- Sensor pointers ---
85
+ sensor::Sensor *voltage_sensor_{nullptr}; // Voltage sensor
86
+ sensor::Sensor *current_sensor_{nullptr}; // Current sensor
87
+ sensor::Sensor *power_sensor_{nullptr}; // Power sensor (can be negative for bidirectional)
88
+ sensor::Sensor *energy_sensor_{nullptr}; // Energy sensor
89
+ sensor::Sensor *internal_temperature_sensor_{nullptr}; // Internal temperature sensor
90
+ sensor::Sensor *external_temperature_sensor_{nullptr}; // External temperature sensor
91
+
92
+ #ifdef USE_NUMBER
93
+ // --- Calibration number entities (for dynamic calibration via HA UI) ---
94
+ number::Number *voltage_calibration_number_{nullptr};
95
+ number::Number *current_calibration_number_{nullptr};
96
+ number::Number *power_calibration_number_{nullptr};
97
+ number::Number *energy_calibration_number_{nullptr};
98
+ #endif
99
+
100
+ // --- Internal state ---
101
+ uint32_t prev_cf_cnt_ = 0; // Previous energy pulse count (for energy calculation)
102
+ float max_temperature_diff_{0}; // Max allowed temperature difference between two measurements (noise filter)
103
+
104
+ // --- Reference values for conversion ---
105
+ float power_reference_; // Divider for raw power to get Watts
106
+ float power_reference_cal_; // Calibrated power reference
107
+ float voltage_reference_; // Divider for raw voltage to get Volts
108
+ float voltage_reference_cal_; // Calibrated voltage reference
109
+ float current_reference_; // Divider for raw current to get Amperes
110
+ float current_reference_cal_; // Calibrated current reference
111
+ float energy_reference_; // Divider for raw energy to get kWh
112
+ float energy_reference_cal_; // Calibrated energy reference
113
+
114
+ // --- Home Assistant calibration values (multipliers, default 1) ---
115
+ float current_cal_{1};
116
+ float voltage_cal_{1};
117
+ float power_cal_{1};
118
+ float energy_cal_{1};
119
+
120
+ // --- Protocol commands ---
121
+ uint8_t read_command_;
122
+ uint8_t write_command_;
123
+
124
+ // --- Mode flags ---
125
+ bool legacy_mode_enabled_ = true;
126
+
127
+ // --- Methods ---
128
+ // Converts packed temperature value to float and updates the sensor
129
+ float update_temp_(sensor::Sensor *sensor, uint16_le_t packed_temperature) const;
130
+
131
+ // Validates the checksum of a received data packet
132
+ bool validate_checksum_(DataPacket *data);
133
+
134
+ // Handles a received data packet
135
+ void received_package_(DataPacket *data);
136
+
137
+ // Calculates reference values for calibration and conversion
138
+ float calculate_energy_reference_();
139
+ float calculate_power_reference_();
140
+ float calculate_calibration_value_(float state);
141
+
142
+ // Calibration update callbacks (used with number entities)
143
+ void current_calibration_callback_(float state);
144
+ void voltage_calibration_callback_(float state);
145
+ void power_calibration_callback_(float state);
146
+ void energy_calibration_callback_(float state);
147
+ void reset_calibration_callback_();
148
+
149
+ // Recalculates all reference values after calibration changes
150
+ void recalibrate_();
107
151
  };
152
+
108
153
  } // namespace bl0940
109
154
  } // namespace esphome
@@ -0,0 +1,27 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components import button
3
+ import esphome.config_validation as cv
4
+ from esphome.const import ENTITY_CATEGORY_CONFIG, ICON_RESTART
5
+
6
+ from .. import CONF_BL0940_ID, bl0940_ns
7
+ from ..sensor import BL0940
8
+
9
+ CalibrationResetButton = bl0940_ns.class_(
10
+ "CalibrationResetButton", button.Button, cg.Component
11
+ )
12
+
13
+ CONFIG_SCHEMA = cv.All(
14
+ button.button_schema(
15
+ CalibrationResetButton,
16
+ entity_category=ENTITY_CATEGORY_CONFIG,
17
+ icon=ICON_RESTART,
18
+ )
19
+ .extend({cv.GenerateID(CONF_BL0940_ID): cv.use_id(BL0940)})
20
+ .extend(cv.COMPONENT_SCHEMA)
21
+ )
22
+
23
+
24
+ async def to_code(config):
25
+ var = await button.new_button(config)
26
+ await cg.register_component(var, config)
27
+ await cg.register_parented(var, config[CONF_BL0940_ID])
@@ -0,0 +1,20 @@
1
+ #include "calibration_reset_button.h"
2
+ #include "../bl0940.h"
3
+ #include "esphome/core/hal.h"
4
+ #include "esphome/core/log.h"
5
+ #include "esphome/core/application.h"
6
+
7
+ namespace esphome {
8
+ namespace bl0940 {
9
+
10
+ static const char *const TAG = "bl0940.button.calibration_reset";
11
+
12
+ void CalibrationResetButton::dump_config() { LOG_BUTTON("", "Calibration Reset Button", this); }
13
+
14
+ void CalibrationResetButton::press_action() {
15
+ ESP_LOGI(TAG, "Resetting calibration defaults...");
16
+ this->parent_->reset_calibration();
17
+ }
18
+
19
+ } // namespace bl0940
20
+ } // namespace esphome
@@ -0,0 +1,19 @@
1
+ #pragma once
2
+
3
+ #include "esphome/core/component.h"
4
+ #include "esphome/components/button/button.h"
5
+
6
+ namespace esphome {
7
+ namespace bl0940 {
8
+
9
+ class BL0940; // Forward declaration of BL0940 class
10
+
11
+ class CalibrationResetButton : public button::Button, public Component, public Parented<BL0940> {
12
+ public:
13
+ void dump_config() override;
14
+
15
+ void press_action() override;
16
+ };
17
+
18
+ } // namespace bl0940
19
+ } // namespace esphome