esphome 2025.8.4__py3-none-any.whl → 2025.9.0b2__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 (364) 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/ags10/ags10.cpp +3 -18
  7. esphome/components/ags10/ags10.h +2 -12
  8. esphome/components/aht10/aht10.cpp +3 -3
  9. esphome/components/airthings_ble/__init__.py +2 -2
  10. esphome/components/alarm_control_panel/__init__.py +2 -2
  11. esphome/components/am2315c/am2315c.cpp +1 -17
  12. esphome/components/am2315c/am2315c.h +2 -3
  13. esphome/components/api/__init__.py +2 -2
  14. esphome/components/api/api_connection.cpp +38 -34
  15. esphome/components/api/api_connection.h +20 -40
  16. esphome/components/api/api_frame_helper.cpp +25 -25
  17. esphome/components/api/api_frame_helper.h +3 -3
  18. esphome/components/api/api_frame_helper_noise.cpp +75 -40
  19. esphome/components/api/api_frame_helper_noise.h +3 -7
  20. esphome/components/api/api_frame_helper_plaintext.cpp +17 -4
  21. esphome/components/api/api_frame_helper_plaintext.h +1 -4
  22. esphome/components/api/api_pb2.cpp +12 -2
  23. esphome/components/api/api_pb2.h +144 -143
  24. esphome/components/api/api_pb2_dump.cpp +6 -1
  25. esphome/components/api/api_pb2_service.cpp +0 -14
  26. esphome/components/api/api_pb2_service.h +1 -3
  27. esphome/components/api/client.py +5 -3
  28. esphome/components/api/proto.cpp +33 -37
  29. esphome/components/async_tcp/__init__.py +2 -2
  30. esphome/components/atm90e26/sensor.py +2 -0
  31. esphome/components/atm90e32/sensor.py +4 -2
  32. esphome/components/audio_adc/__init__.py +2 -2
  33. esphome/components/audio_dac/__init__.py +2 -2
  34. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +1 -1
  35. esphome/components/bedjet/bedjet_hub.cpp +1 -1
  36. esphome/components/binary_sensor/__init__.py +2 -2
  37. esphome/components/binary_sensor/binary_sensor.cpp +13 -0
  38. esphome/components/binary_sensor/binary_sensor.h +4 -7
  39. esphome/components/bl0940/__init__.py +6 -1
  40. esphome/components/bl0940/bl0940.cpp +178 -41
  41. esphome/components/bl0940/bl0940.h +121 -76
  42. esphome/components/bl0940/button/__init__.py +27 -0
  43. esphome/components/bl0940/button/calibration_reset_button.cpp +20 -0
  44. esphome/components/bl0940/button/calibration_reset_button.h +19 -0
  45. esphome/components/bl0940/number/__init__.py +94 -0
  46. esphome/components/bl0940/number/calibration_number.cpp +29 -0
  47. esphome/components/bl0940/number/calibration_number.h +26 -0
  48. esphome/components/bl0940/sensor.py +151 -2
  49. esphome/components/bl0942/bl0942.cpp +1 -1
  50. esphome/components/ble_client/output/__init__.py +4 -4
  51. esphome/components/bluetooth_proxy/__init__.py +1 -1
  52. esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -1
  53. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +15 -7
  54. esphome/components/bluetooth_proxy/bluetooth_proxy.h +6 -3
  55. esphome/components/button/__init__.py +2 -2
  56. esphome/components/button/button.cpp +13 -0
  57. esphome/components/button/button.h +4 -7
  58. esphome/components/camera/buffer.h +18 -0
  59. esphome/components/camera/buffer_impl.cpp +20 -0
  60. esphome/components/camera/buffer_impl.h +26 -0
  61. esphome/components/camera/camera.h +43 -0
  62. esphome/components/camera/encoder.h +69 -0
  63. esphome/components/camera_encoder/__init__.py +62 -0
  64. esphome/components/camera_encoder/encoder_buffer_impl.cpp +23 -0
  65. esphome/components/camera_encoder/encoder_buffer_impl.h +25 -0
  66. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +82 -0
  67. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +39 -0
  68. esphome/components/captive_portal/__init__.py +2 -2
  69. esphome/components/captive_portal/captive_index.h +77 -97
  70. esphome/components/captive_portal/captive_portal.cpp +35 -12
  71. esphome/components/captive_portal/captive_portal.h +3 -3
  72. esphome/components/ccs811/ccs811.cpp +3 -3
  73. esphome/components/climate/__init__.py +2 -2
  74. esphome/components/climate/climate.cpp +1 -1
  75. esphome/components/cover/__init__.py +5 -5
  76. esphome/components/cover/cover.cpp +1 -1
  77. esphome/components/cover/cover.h +2 -2
  78. esphome/components/dallas_temp/dallas_temp.cpp +2 -2
  79. esphome/components/datetime/__init__.py +2 -2
  80. esphome/components/datetime/date_entity.h +2 -2
  81. esphome/components/datetime/datetime_entity.h +2 -2
  82. esphome/components/datetime/time_entity.h +2 -2
  83. esphome/components/debug/debug_esp32.cpp +1 -1
  84. esphome/components/display/__init__.py +4 -4
  85. esphome/components/duty_time/duty_time_sensor.cpp +1 -1
  86. esphome/components/esp32/__init__.py +0 -5
  87. esphome/components/esp32/gpio.cpp +27 -23
  88. esphome/components/esp32/gpio.h +26 -11
  89. esphome/components/esp32/preferences.cpp +8 -4
  90. esphome/components/esp32_ble/__init__.py +7 -2
  91. esphome/components/esp32_ble/ble_uuid.cpp +30 -9
  92. esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +4 -3
  93. esphome/components/esp32_ble_client/ble_client_base.cpp +7 -3
  94. esphome/components/esp32_ble_client/ble_client_base.h +8 -5
  95. esphome/components/esp32_ble_tracker/__init__.py +2 -2
  96. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +11 -47
  97. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -14
  98. esphome/components/esp8266/__init__.py +2 -2
  99. esphome/components/esp8266/core.cpp +2 -2
  100. esphome/components/esp8266/gpio.py +4 -4
  101. esphome/components/esp8266/preferences.cpp +30 -28
  102. esphome/components/esphome/ota/__init__.py +2 -2
  103. esphome/components/esphome/ota/ota_esphome.cpp +21 -19
  104. esphome/components/esphome/ota/ota_esphome.h +6 -5
  105. esphome/components/ethernet/__init__.py +7 -2
  106. esphome/components/ethernet/ethernet_component.cpp +49 -3
  107. esphome/components/ethernet/ethernet_component.h +2 -0
  108. esphome/components/event/__init__.py +2 -2
  109. esphome/components/event/event.h +4 -4
  110. esphome/components/factory_reset/button/factory_reset_button.cpp +18 -1
  111. esphome/components/factory_reset/button/factory_reset_button.h +6 -1
  112. esphome/components/factory_reset/switch/factory_reset_switch.cpp +18 -1
  113. esphome/components/factory_reset/switch/factory_reset_switch.h +5 -1
  114. esphome/components/fan/__init__.py +2 -2
  115. esphome/components/fan/fan.cpp +2 -1
  116. esphome/components/gdk101/gdk101.cpp +4 -4
  117. esphome/components/globals/__init__.py +2 -2
  118. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +19 -18
  119. esphome/components/gpio_expander/cached_gpio.h +36 -16
  120. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +5 -5
  121. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +1 -1
  122. esphome/components/haier/haier_base.cpp +1 -1
  123. esphome/components/haier/hon_climate.cpp +1 -1
  124. esphome/components/hlw8012/hlw8012.cpp +5 -5
  125. esphome/components/honeywellabp2_i2c/honeywellabp2.cpp +4 -4
  126. esphome/components/host/preferences.h +3 -2
  127. esphome/components/hte501/hte501.cpp +3 -21
  128. esphome/components/hte501/hte501.h +2 -3
  129. esphome/components/http_request/ota/__init__.py +2 -2
  130. esphome/components/i2c/__init__.py +2 -2
  131. esphome/components/i2c/i2c.cpp +13 -9
  132. esphome/components/i2c/i2c_bus.h +36 -6
  133. esphome/components/i2s_audio/__init__.py +8 -2
  134. esphome/components/i2s_audio/media_player/__init__.py +1 -1
  135. esphome/components/i2s_audio/microphone/__init__.py +1 -1
  136. esphome/components/i2s_audio/speaker/__init__.py +1 -1
  137. esphome/components/ina2xx_base/__init__.py +4 -2
  138. esphome/components/inkplate/__init__.py +1 -0
  139. esphome/components/inkplate/const.py +105 -0
  140. esphome/components/inkplate/display.py +238 -0
  141. esphome/components/{inkplate6 → inkplate}/inkplate.cpp +156 -74
  142. esphome/components/{inkplate6 → inkplate}/inkplate.h +28 -68
  143. esphome/components/inkplate6/__init__.py +0 -1
  144. esphome/components/inkplate6/display.py +2 -211
  145. esphome/components/integration/integration_sensor.cpp +1 -1
  146. esphome/components/json/__init__.py +2 -2
  147. esphome/components/lc709203f/lc709203f.cpp +4 -17
  148. esphome/components/lc709203f/lc709203f.h +2 -3
  149. esphome/components/ld2420/text_sensor/{text_sensor.cpp → ld2420_text_sensor.cpp} +1 -1
  150. esphome/components/ld2450/ld2450.cpp +1 -1
  151. esphome/components/libretiny/preferences.cpp +13 -5
  152. esphome/components/light/__init__.py +2 -2
  153. esphome/components/light/addressable_light_effect.h +7 -0
  154. esphome/components/light/base_light_effects.h +8 -0
  155. esphome/components/light/light_call.cpp +22 -20
  156. esphome/components/light/light_effect.cpp +36 -0
  157. esphome/components/light/light_effect.h +14 -0
  158. esphome/components/light/light_json_schema.cpp +9 -1
  159. esphome/components/light/light_state.cpp +2 -2
  160. esphome/components/light/light_state.h +38 -0
  161. esphome/components/lock/__init__.py +2 -2
  162. esphome/components/lock/lock.h +2 -2
  163. esphome/components/logger/__init__.py +2 -2
  164. esphome/components/logger/logger.cpp +25 -4
  165. esphome/components/logger/logger.h +1 -1
  166. esphome/components/logger/logger_esp32.cpp +16 -8
  167. esphome/components/logger/logger_esp8266.cpp +11 -3
  168. esphome/components/logger/logger_libretiny.cpp +13 -3
  169. esphome/components/logger/logger_rp2040.cpp +14 -3
  170. esphome/components/logger/logger_zephyr.cpp +15 -4
  171. esphome/components/lvgl/defines.py +1 -0
  172. esphome/components/lvgl/hello_world.py +96 -33
  173. esphome/components/lvgl/number/lvgl_number.h +1 -1
  174. esphome/components/lvgl/select/lvgl_select.h +1 -1
  175. esphome/components/lvgl/widgets/__init__.py +0 -1
  176. esphome/components/lvgl/widgets/spinbox.py +20 -11
  177. esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp +1 -1
  178. esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp +1 -1
  179. esphome/components/mapping/__init__.py +13 -5
  180. esphome/components/mapping/mapping.h +69 -0
  181. esphome/components/max17043/max17043.cpp +2 -2
  182. esphome/components/mcp23016/__init__.py +1 -0
  183. esphome/components/mcp23016/mcp23016.cpp +20 -5
  184. esphome/components/mcp23016/mcp23016.h +10 -4
  185. esphome/components/mcp23x08_base/mcp23x08_base.cpp +1 -1
  186. esphome/components/mcp23x17_base/mcp23x17_base.cpp +2 -2
  187. esphome/components/md5/md5.cpp +3 -2
  188. esphome/components/mdns/__init__.py +2 -2
  189. esphome/components/mdns/mdns_component.cpp +145 -54
  190. esphome/components/media_player/__init__.py +2 -2
  191. esphome/components/micro_wake_word/__init__.py +2 -2
  192. esphome/components/microphone/__init__.py +2 -2
  193. esphome/components/mipi/__init__.py +77 -33
  194. esphome/components/mipi_rgb/__init__.py +2 -0
  195. esphome/components/mipi_rgb/display.py +321 -0
  196. esphome/components/mipi_rgb/mipi_rgb.cpp +388 -0
  197. esphome/components/mipi_rgb/mipi_rgb.h +127 -0
  198. esphome/components/mipi_rgb/models/guition.py +24 -0
  199. esphome/components/mipi_rgb/models/lilygo.py +228 -0
  200. esphome/components/mipi_rgb/models/rpi.py +9 -0
  201. esphome/components/mipi_rgb/models/st7701s.py +214 -0
  202. esphome/components/mipi_rgb/models/waveshare.py +64 -0
  203. esphome/components/mipi_spi/models/jc.py +229 -0
  204. esphome/components/mlx90614/mlx90614.cpp +1 -16
  205. esphome/components/mlx90614/mlx90614.h +0 -1
  206. esphome/components/mqtt/__init__.py +2 -2
  207. esphome/components/mqtt/mqtt_sensor.cpp +7 -2
  208. esphome/components/ms5611/ms5611.cpp +7 -6
  209. esphome/components/network/__init__.py +2 -2
  210. esphome/components/nextion/nextion_upload.cpp +4 -1
  211. esphome/components/nrf52/__init__.py +49 -6
  212. esphome/components/nrf52/const.py +1 -0
  213. esphome/components/nrf52/dfu.cpp +51 -0
  214. esphome/components/nrf52/dfu.h +24 -0
  215. esphome/components/ntc/ntc.cpp +1 -1
  216. esphome/components/number/__init__.py +2 -2
  217. esphome/components/number/automation.cpp +1 -1
  218. esphome/components/number/number.cpp +21 -0
  219. esphome/components/number/number.h +4 -13
  220. esphome/components/opentherm/hub.h +6 -6
  221. esphome/components/opentherm/number/{number.cpp → opentherm_number.cpp} +2 -2
  222. esphome/components/opentherm/output/{output.cpp → opentherm_output.cpp} +1 -1
  223. esphome/components/opentherm/switch/{switch.cpp → opentherm_switch.cpp} +1 -1
  224. esphome/components/openthread/openthread.cpp +41 -7
  225. esphome/components/openthread/openthread.h +11 -0
  226. esphome/components/ota/__init__.py +2 -2
  227. esphome/components/pca6416a/__init__.py +1 -0
  228. esphome/components/pca6416a/pca6416a.cpp +20 -5
  229. esphome/components/pca6416a/pca6416a.h +12 -5
  230. esphome/components/pca9554/__init__.py +2 -1
  231. esphome/components/pca9554/pca9554.cpp +12 -18
  232. esphome/components/pca9554/pca9554.h +10 -9
  233. esphome/components/pcf8574/__init__.py +1 -0
  234. esphome/components/pcf8574/pcf8574.cpp +14 -5
  235. esphome/components/pcf8574/pcf8574.h +13 -6
  236. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +7 -7
  237. esphome/components/pipsolar/__init__.py +3 -3
  238. esphome/components/pipsolar/output/__init__.py +4 -4
  239. esphome/components/pulse_width/pulse_width.cpp +2 -2
  240. esphome/components/qmp6988/qmp6988.cpp +81 -126
  241. esphome/components/qmp6988/qmp6988.h +31 -37
  242. esphome/components/radon_eye_ble/__init__.py +2 -2
  243. esphome/components/remote_base/__init__.py +6 -8
  244. esphome/components/rotary_encoder/rotary_encoder.cpp +1 -1
  245. esphome/components/rp2040/__init__.py +2 -2
  246. esphome/components/runtime_stats/runtime_stats.cpp +10 -23
  247. esphome/components/runtime_stats/runtime_stats.h +4 -10
  248. esphome/components/safe_mode/__init__.py +2 -2
  249. esphome/components/safe_mode/safe_mode.cpp +33 -31
  250. esphome/components/script/script.cpp +6 -0
  251. esphome/components/script/script.h +19 -5
  252. esphome/components/sdm_meter/sensor.py +3 -1
  253. esphome/components/select/__init__.py +2 -2
  254. esphome/components/select/select.h +2 -2
  255. esphome/components/sen5x/sen5x.cpp +57 -55
  256. esphome/components/sen5x/sen5x.h +21 -15
  257. esphome/components/sen5x/sensor.py +67 -44
  258. esphome/components/sensirion_common/i2c_sensirion.cpp +18 -47
  259. esphome/components/sensirion_common/i2c_sensirion.h +39 -55
  260. esphome/components/sensor/__init__.py +2 -2
  261. esphome/components/sensor/automation.h +1 -1
  262. esphome/components/sensor/sensor.cpp +34 -6
  263. esphome/components/sensor/sensor.h +4 -21
  264. esphome/components/sgp30/sgp30.cpp +34 -35
  265. esphome/components/sgp30/sgp30.h +11 -10
  266. esphome/components/sgp4x/sgp4x.cpp +2 -2
  267. esphome/components/shelly_dimmer/light.py +7 -7
  268. esphome/components/sht4x/sht4x.cpp +1 -1
  269. esphome/components/sntp/sntp_component.cpp +36 -9
  270. esphome/components/sntp/sntp_component.h +7 -0
  271. esphome/components/sound_level/sound_level.cpp +1 -1
  272. esphome/components/speaker/__init__.py +2 -2
  273. esphome/components/speaker/media_player/__init__.py +2 -2
  274. esphome/components/speaker/media_player/speaker_media_player.cpp +1 -1
  275. esphome/components/spi/__init__.py +2 -2
  276. esphome/components/sprinkler/sprinkler.cpp +1 -1
  277. esphome/components/sps30/sps30.cpp +18 -23
  278. esphome/components/sps30/sps30.h +3 -3
  279. esphome/components/status_led/__init__.py +2 -2
  280. esphome/components/stepper/__init__.py +2 -2
  281. esphome/components/switch/__init__.py +2 -2
  282. esphome/components/switch/switch.cpp +5 -5
  283. esphome/components/sx1509/__init__.py +1 -1
  284. esphome/components/sx1509/sx1509.cpp +12 -7
  285. esphome/components/sx1509/sx1509.h +11 -4
  286. esphome/components/tca9555/tca9555.cpp +5 -5
  287. esphome/components/tee501/tee501.cpp +2 -21
  288. esphome/components/tee501/tee501.h +2 -4
  289. esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +1 -1
  290. esphome/components/template/datetime/template_date.cpp +1 -1
  291. esphome/components/template/datetime/template_datetime.cpp +2 -2
  292. esphome/components/template/datetime/template_time.cpp +1 -1
  293. esphome/components/template/number/template_number.cpp +1 -1
  294. esphome/components/template/select/template_select.cpp +1 -1
  295. esphome/components/template/text/template_text.cpp +1 -1
  296. esphome/components/text/__init__.py +2 -2
  297. esphome/components/text/text.h +2 -2
  298. esphome/components/text_sensor/__init__.py +2 -2
  299. esphome/components/text_sensor/text_sensor.h +4 -4
  300. esphome/components/thermostat/climate.py +11 -7
  301. esphome/components/thermostat/thermostat_climate.cpp +237 -206
  302. esphome/components/thermostat/thermostat_climate.h +52 -41
  303. esphome/components/time/__init__.py +2 -2
  304. esphome/components/tmp1075/tmp1075.cpp +1 -1
  305. esphome/components/total_daily_energy/total_daily_energy.cpp +1 -1
  306. esphome/components/touchscreen/__init__.py +2 -2
  307. esphome/components/tuya/number/tuya_number.cpp +1 -1
  308. esphome/components/udp/udp_component.cpp +3 -3
  309. esphome/components/ufire_ec/ufire_ec.cpp +4 -4
  310. esphome/components/ufire_ise/ufire_ise.cpp +4 -4
  311. esphome/components/update/__init__.py +2 -2
  312. esphome/components/usb_uart/usb_uart.cpp +1 -1
  313. esphome/components/valve/__init__.py +5 -5
  314. esphome/components/valve/valve.cpp +1 -1
  315. esphome/components/valve/valve.h +2 -2
  316. esphome/components/wake_on_lan/wake_on_lan.cpp +2 -2
  317. esphome/components/waveshare_epaper/waveshare_213v3.cpp +1 -1
  318. esphome/components/web_server/__init__.py +2 -2
  319. esphome/components/web_server/ota/__init__.py +2 -2
  320. esphome/components/web_server/ota/ota_web_server.cpp +11 -0
  321. esphome/components/web_server/server_index_v2.h +149 -149
  322. esphome/components/web_server/web_server.cpp +58 -12
  323. esphome/components/web_server_base/__init__.py +2 -2
  324. esphome/components/wifi/__init__.py +5 -5
  325. esphome/components/wifi/wifi_component.cpp +4 -4
  326. esphome/components/wifi/wifi_component_esp_idf.cpp +2 -0
  327. esphome/components/wifi_info/wifi_info_text_sensor.h +3 -2
  328. esphome/config_validation.py +2 -2
  329. esphome/const.py +3 -1
  330. esphome/core/__init__.py +1 -0
  331. esphome/core/application.cpp +89 -51
  332. esphome/core/application.h +1 -0
  333. esphome/core/component.cpp +41 -19
  334. esphome/core/component.h +17 -13
  335. esphome/core/config.py +7 -7
  336. esphome/core/defines.h +4 -0
  337. esphome/core/entity_base.cpp +22 -8
  338. esphome/core/entity_base.h +43 -0
  339. esphome/core/helpers.cpp +34 -20
  340. esphome/core/helpers.h +33 -3
  341. esphome/core/ring_buffer.cpp +6 -2
  342. esphome/core/ring_buffer.h +2 -1
  343. esphome/core/scheduler.cpp +178 -97
  344. esphome/core/scheduler.h +67 -36
  345. esphome/core/time.cpp +6 -20
  346. esphome/coroutine.py +80 -3
  347. esphome/cpp_generator.py +13 -0
  348. esphome/cpp_helpers.py +2 -2
  349. esphome/dashboard/web_server.py +67 -10
  350. esphome/espota2.py +13 -6
  351. esphome/helpers.py +68 -83
  352. esphome/resolver.py +67 -0
  353. esphome/util.py +9 -6
  354. esphome/wizard.py +39 -26
  355. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/METADATA +9 -9
  356. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/RECORD +364 -333
  357. /esphome/components/ld2420/text_sensor/{text_sensor.h → ld2420_text_sensor.h} +0 -0
  358. /esphome/components/opentherm/number/{number.h → opentherm_number.h} +0 -0
  359. /esphome/components/opentherm/output/{output.h → opentherm_output.h} +0 -0
  360. /esphome/components/opentherm/switch/{switch.h → opentherm_switch.h} +0 -0
  361. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/WHEEL +0 -0
  362. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/entry_points.txt +0 -0
  363. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/licenses/LICENSE +0 -0
  364. {esphome-2025.8.4.dist-info → esphome-2025.9.0b2.dist-info}/top_level.txt +0 -0
esphome/core/defines.h CHANGED
@@ -240,6 +240,10 @@
240
240
  #define USE_SOCKET_SELECT_SUPPORT
241
241
  #endif
242
242
 
243
+ #ifdef USE_NRF52
244
+ #define USE_NRF52_DFU
245
+ #endif
246
+
243
247
  // Disabled feature flags
244
248
  // #define USE_BSEC // Requires a library with proprietary license
245
249
  // #define USE_BSEC2 // Requires a library with proprietary license
@@ -1,6 +1,7 @@
1
1
  #include "esphome/core/entity_base.h"
2
2
  #include "esphome/core/application.h"
3
3
  #include "esphome/core/helpers.h"
4
+ #include "esphome/core/string_ref.h"
4
5
 
5
6
  namespace esphome {
6
7
 
@@ -44,19 +45,29 @@ void EntityBase::set_icon(const char *icon) {
44
45
  #endif
45
46
  }
46
47
 
48
+ // Check if the object_id is dynamic (changes with MAC suffix)
49
+ bool EntityBase::is_object_id_dynamic_() const {
50
+ return !this->flags_.has_own_name && App.is_name_add_mac_suffix_enabled();
51
+ }
52
+
47
53
  // Entity Object ID
48
54
  std::string EntityBase::get_object_id() const {
49
55
  // Check if `App.get_friendly_name()` is constant or dynamic.
50
- if (!this->flags_.has_own_name && App.is_name_add_mac_suffix_enabled()) {
56
+ if (this->is_object_id_dynamic_()) {
51
57
  // `App.get_friendly_name()` is dynamic.
52
58
  return str_sanitize(str_snake_case(App.get_friendly_name()));
53
- } else {
54
- // `App.get_friendly_name()` is constant.
55
- if (this->object_id_c_str_ == nullptr) {
56
- return "";
57
- }
58
- return this->object_id_c_str_;
59
59
  }
60
+ // `App.get_friendly_name()` is constant.
61
+ return this->object_id_c_str_ == nullptr ? "" : this->object_id_c_str_;
62
+ }
63
+ StringRef EntityBase::get_object_id_ref_for_api_() const {
64
+ static constexpr auto EMPTY_STRING = StringRef::from_lit("");
65
+ // Return empty for dynamic case (MAC suffix)
66
+ if (this->is_object_id_dynamic_()) {
67
+ return EMPTY_STRING;
68
+ }
69
+ // For static case, return the string or empty if null
70
+ return this->object_id_c_str_ == nullptr ? EMPTY_STRING : StringRef(this->object_id_c_str_);
60
71
  }
61
72
  void EntityBase::set_object_id(const char *object_id) {
62
73
  this->object_id_c_str_ = object_id;
@@ -64,7 +75,10 @@ void EntityBase::set_object_id(const char *object_id) {
64
75
  }
65
76
 
66
77
  // Calculate Object ID Hash from Entity Name
67
- void EntityBase::calc_object_id_() { this->object_id_hash_ = fnv1_hash(this->get_object_id()); }
78
+ void EntityBase::calc_object_id_() {
79
+ this->object_id_hash_ =
80
+ fnv1_hash(this->is_object_id_dynamic_() ? this->get_object_id().c_str() : this->object_id_c_str_);
81
+ }
68
82
 
69
83
  uint32_t EntityBase::get_object_id_hash() { return this->object_id_hash_; }
70
84
 
@@ -12,6 +12,11 @@
12
12
 
13
13
  namespace esphome {
14
14
 
15
+ // Forward declaration for friend access
16
+ namespace api {
17
+ class APIConnection;
18
+ } // namespace api
19
+
15
20
  enum EntityCategory : uint8_t {
16
21
  ENTITY_CATEGORY_NONE = 0,
17
22
  ENTITY_CATEGORY_CONFIG = 1,
@@ -80,12 +85,50 @@ class EntityBase {
80
85
  // Set has_state - for components that need to manually set this
81
86
  void set_has_state(bool state) { this->flags_.has_state = state; }
82
87
 
88
+ /**
89
+ * @brief Get a unique hash for storing preferences/settings for this entity.
90
+ *
91
+ * This method returns a hash that uniquely identifies the entity for the purpose of
92
+ * storing preferences (such as calibration, state, etc.). Unlike get_object_id_hash(),
93
+ * this hash also incorporates the device_id (if devices are enabled), ensuring uniqueness
94
+ * across multiple devices that may have entities with the same object_id.
95
+ *
96
+ * Use this method when storing or retrieving preferences/settings that should be unique
97
+ * per device-entity pair. Use get_object_id_hash() when you need a hash that identifies
98
+ * the entity regardless of the device it belongs to.
99
+ *
100
+ * For backward compatibility, if device_id is 0 (the main device), the hash is unchanged
101
+ * from previous versions, so existing single-device configurations will continue to work.
102
+ *
103
+ * @return uint32_t The unique hash for preferences, including device_id if available.
104
+ */
105
+ uint32_t get_preference_hash() {
106
+ #ifdef USE_DEVICES
107
+ // Combine object_id_hash with device_id to ensure uniqueness across devices
108
+ // Note: device_id is 0 for the main device, so XORing with 0 preserves the original hash
109
+ // This ensures backward compatibility for existing single-device configurations
110
+ return this->get_object_id_hash() ^ this->get_device_id();
111
+ #else
112
+ // Without devices, just use object_id_hash as before
113
+ return this->get_object_id_hash();
114
+ #endif
115
+ }
116
+
83
117
  protected:
118
+ friend class api::APIConnection;
119
+
120
+ // Get object_id as StringRef when it's static (for API usage)
121
+ // Returns empty StringRef if object_id is dynamic (needs allocation)
122
+ StringRef get_object_id_ref_for_api_() const;
123
+
84
124
  /// The hash_base() function has been deprecated. It is kept in this
85
125
  /// class for now, to prevent external components from not compiling.
86
126
  virtual uint32_t hash_base() { return 0L; }
87
127
  void calc_object_id_();
88
128
 
129
+ /// Check if the object_id is dynamic (changes with MAC suffix)
130
+ bool is_object_id_dynamic_() const;
131
+
89
132
  StringRef name_;
90
133
  const char *object_id_c_str_{nullptr};
91
134
  #ifdef USE_ENTITY_ICON
esphome/core/helpers.cpp CHANGED
@@ -41,17 +41,28 @@ static const uint16_t CRC16_1021_BE_LUT_H[] = {0x0000, 0x1231, 0x2462, 0x3653, 0
41
41
 
42
42
  // Mathematics
43
43
 
44
- uint8_t crc8(const uint8_t *data, uint8_t len) {
45
- uint8_t crc = 0;
46
-
44
+ uint8_t crc8(const uint8_t *data, uint8_t len, uint8_t crc, uint8_t poly, bool msb_first) {
47
45
  while ((len--) != 0u) {
48
46
  uint8_t inbyte = *data++;
49
- for (uint8_t i = 8; i != 0u; i--) {
50
- bool mix = (crc ^ inbyte) & 0x01;
51
- crc >>= 1;
52
- if (mix)
53
- crc ^= 0x8C;
54
- inbyte >>= 1;
47
+ if (msb_first) {
48
+ // MSB first processing (for polynomials like 0x31, 0x07)
49
+ crc ^= inbyte;
50
+ for (uint8_t i = 8; i != 0u; i--) {
51
+ if (crc & 0x80) {
52
+ crc = (crc << 1) ^ poly;
53
+ } else {
54
+ crc <<= 1;
55
+ }
56
+ }
57
+ } else {
58
+ // LSB first processing (default for Dallas/Maxim 0x8C)
59
+ for (uint8_t i = 8; i != 0u; i--) {
60
+ bool mix = (crc ^ inbyte) & 0x01;
61
+ crc >>= 1;
62
+ if (mix)
63
+ crc ^= poly;
64
+ inbyte >>= 1;
65
+ }
55
66
  }
56
67
  }
57
68
  return crc;
@@ -131,11 +142,13 @@ uint16_t crc16be(const uint8_t *data, uint16_t len, uint16_t crc, uint16_t poly,
131
142
  return refout ? (crc ^ 0xffff) : crc;
132
143
  }
133
144
 
134
- uint32_t fnv1_hash(const std::string &str) {
145
+ uint32_t fnv1_hash(const char *str) {
135
146
  uint32_t hash = 2166136261UL;
136
- for (char c : str) {
137
- hash *= 16777619UL;
138
- hash ^= c;
147
+ if (str) {
148
+ while (*str) {
149
+ hash *= 16777619UL;
150
+ hash ^= *str++;
151
+ }
139
152
  }
140
153
  return hash;
141
154
  }
@@ -242,23 +255,22 @@ size_t parse_hex(const char *str, size_t length, uint8_t *data, size_t count) {
242
255
  }
243
256
 
244
257
  std::string format_mac_address_pretty(const uint8_t *mac) {
245
- return str_snprintf("%02X:%02X:%02X:%02X:%02X:%02X", 17, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
258
+ char buf[18];
259
+ format_mac_addr_upper(mac, buf);
260
+ return std::string(buf);
246
261
  }
247
262
 
248
- static char format_hex_char(uint8_t v) { return v >= 10 ? 'a' + (v - 10) : '0' + v; }
249
263
  std::string format_hex(const uint8_t *data, size_t length) {
250
264
  std::string ret;
251
265
  ret.resize(length * 2);
252
266
  for (size_t i = 0; i < length; i++) {
253
- ret[2 * i] = format_hex_char((data[i] & 0xF0) >> 4);
267
+ ret[2 * i] = format_hex_char(data[i] >> 4);
254
268
  ret[2 * i + 1] = format_hex_char(data[i] & 0x0F);
255
269
  }
256
270
  return ret;
257
271
  }
258
272
  std::string format_hex(const std::vector<uint8_t> &data) { return format_hex(data.data(), data.size()); }
259
273
 
260
- static char format_hex_pretty_char(uint8_t v) { return v >= 10 ? 'A' + (v - 10) : '0' + v; }
261
-
262
274
  // Shared implementation for uint8_t and string hex formatting
263
275
  static std::string format_hex_pretty_uint8(const uint8_t *data, size_t length, char separator, bool show_length) {
264
276
  if (data == nullptr || length == 0)
@@ -267,7 +279,7 @@ static std::string format_hex_pretty_uint8(const uint8_t *data, size_t length, c
267
279
  uint8_t multiple = separator ? 3 : 2; // 3 if separator is not \0, 2 otherwise
268
280
  ret.resize(multiple * length - (separator ? 1 : 0));
269
281
  for (size_t i = 0; i < length; i++) {
270
- ret[multiple * i] = format_hex_pretty_char((data[i] & 0xF0) >> 4);
282
+ ret[multiple * i] = format_hex_pretty_char(data[i] >> 4);
271
283
  ret[multiple * i + 1] = format_hex_pretty_char(data[i] & 0x0F);
272
284
  if (separator && i != length - 1)
273
285
  ret[multiple * i + 2] = separator;
@@ -578,7 +590,9 @@ bool HighFrequencyLoopRequester::is_high_frequency() { return num_requests > 0;
578
590
  std::string get_mac_address() {
579
591
  uint8_t mac[6];
580
592
  get_mac_address_raw(mac);
581
- return str_snprintf("%02x%02x%02x%02x%02x%02x", 12, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
593
+ char buf[13];
594
+ format_mac_addr_lower_no_sep(mac, buf);
595
+ return std::string(buf);
582
596
  }
583
597
 
584
598
  std::string get_mac_address_pretty() {
esphome/core/helpers.h CHANGED
@@ -145,8 +145,8 @@ template<typename T, typename U> T remap(U value, U min, U max, T min_out, T max
145
145
  return (value - min) * (max_out - min_out) / (max - min) + min_out;
146
146
  }
147
147
 
148
- /// Calculate a CRC-8 checksum of \p data with size \p len using the CRC-8-Dallas/Maxim polynomial.
149
- uint8_t crc8(const uint8_t *data, uint8_t len);
148
+ /// Calculate a CRC-8 checksum of \p data with size \p len.
149
+ uint8_t crc8(const uint8_t *data, uint8_t len, uint8_t crc = 0x00, uint8_t poly = 0x8C, bool msb_first = false);
150
150
 
151
151
  /// Calculate a CRC-16 checksum of \p data with size \p len.
152
152
  uint16_t crc16(const uint8_t *data, uint16_t len, uint16_t crc = 0xffff, uint16_t reverse_poly = 0xa001,
@@ -155,7 +155,8 @@ uint16_t crc16be(const uint8_t *data, uint16_t len, uint16_t crc = 0, uint16_t p
155
155
  bool refout = false);
156
156
 
157
157
  /// Calculate a FNV-1 hash of \p str.
158
- uint32_t fnv1_hash(const std::string &str);
158
+ uint32_t fnv1_hash(const char *str);
159
+ inline uint32_t fnv1_hash(const std::string &str) { return fnv1_hash(str.c_str()); }
159
160
 
160
161
  /// Return a random 32-bit unsigned integer.
161
162
  uint32_t random_uint32();
@@ -379,6 +380,35 @@ template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> optional<
379
380
  return parse_hex<T>(str.c_str(), str.length());
380
381
  }
381
382
 
383
+ /// Convert a nibble (0-15) to lowercase hex char
384
+ inline char format_hex_char(uint8_t v) { return v >= 10 ? 'a' + (v - 10) : '0' + v; }
385
+
386
+ /// Convert a nibble (0-15) to uppercase hex char (used for pretty printing)
387
+ /// This always uses uppercase (A-F) for pretty/human-readable output
388
+ inline char format_hex_pretty_char(uint8_t v) { return v >= 10 ? 'A' + (v - 10) : '0' + v; }
389
+
390
+ /// Format MAC address as XX:XX:XX:XX:XX:XX (uppercase)
391
+ inline void format_mac_addr_upper(const uint8_t *mac, char *output) {
392
+ for (size_t i = 0; i < 6; i++) {
393
+ uint8_t byte = mac[i];
394
+ output[i * 3] = format_hex_pretty_char(byte >> 4);
395
+ output[i * 3 + 1] = format_hex_pretty_char(byte & 0x0F);
396
+ if (i < 5)
397
+ output[i * 3 + 2] = ':';
398
+ }
399
+ output[17] = '\0';
400
+ }
401
+
402
+ /// Format MAC address as xxxxxxxxxxxxxx (lowercase, no separators)
403
+ inline void format_mac_addr_lower_no_sep(const uint8_t *mac, char *output) {
404
+ for (size_t i = 0; i < 6; i++) {
405
+ uint8_t byte = mac[i];
406
+ output[i * 2] = format_hex_char(byte >> 4);
407
+ output[i * 2 + 1] = format_hex_char(byte & 0x0F);
408
+ }
409
+ output[12] = '\0';
410
+ }
411
+
382
412
  /// Format the six-byte array \p mac into a MAC address.
383
413
  std::string format_mac_address_pretty(const uint8_t mac[6]);
384
414
  /// Format the byte array \p data of length \p len in lowercased hex.
@@ -78,9 +78,13 @@ size_t RingBuffer::write(const void *data, size_t len) {
78
78
  return this->write_without_replacement(data, len, 0);
79
79
  }
80
80
 
81
- size_t RingBuffer::write_without_replacement(const void *data, size_t len, TickType_t ticks_to_wait) {
81
+ size_t RingBuffer::write_without_replacement(const void *data, size_t len, TickType_t ticks_to_wait,
82
+ bool write_partial) {
82
83
  if (!xRingbufferSend(this->handle_, data, len, ticks_to_wait)) {
83
- // Couldn't fit all the data, so only write what will fit
84
+ if (!write_partial) {
85
+ return 0; // Not enough space available and not allowed to write partial data
86
+ }
87
+ // Couldn't fit all the data, write what will fit
84
88
  size_t free = std::min(this->free(), len);
85
89
  if (xRingbufferSend(this->handle_, data, free, 0)) {
86
90
  return free;
@@ -50,7 +50,8 @@ class RingBuffer {
50
50
  * @param ticks_to_wait Maximum number of FreeRTOS ticks to wait (default: 0)
51
51
  * @return Number of bytes written
52
52
  */
53
- size_t write_without_replacement(const void *data, size_t len, TickType_t ticks_to_wait = 0);
53
+ size_t write_without_replacement(const void *data, size_t len, TickType_t ticks_to_wait = 0,
54
+ bool write_partial = true);
54
55
 
55
56
  /**
56
57
  * @brief Returns the number of available bytes in the ring buffer.