esphome 2025.6.3__py3-none-any.whl → 2025.7.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (599) hide show
  1. esphome/__main__.py +1 -3
  2. esphome/codegen.py +2 -0
  3. esphome/components/ac_dimmer/ac_dimmer.cpp +6 -6
  4. esphome/components/adc/__init__.py +25 -1
  5. esphome/components/adc/adc_sensor.h +11 -11
  6. esphome/components/adc/adc_sensor_common.cpp +1 -1
  7. esphome/components/adc/adc_sensor_esp32.cpp +16 -8
  8. esphome/components/ade7880/ade7880.h +0 -2
  9. esphome/components/ads1115/ads1115.h +0 -1
  10. esphome/components/ads1118/ads1118.h +0 -1
  11. esphome/components/ags10/ags10.h +0 -2
  12. esphome/components/aic3204/aic3204.h +0 -1
  13. esphome/components/alarm_control_panel/__init__.py +5 -2
  14. esphome/components/alpha3/alpha3.h +0 -1
  15. esphome/components/am43/cover/am43_cover.h +0 -1
  16. esphome/components/am43/sensor/am43_sensor.h +0 -1
  17. esphome/components/analog_threshold/analog_threshold_binary_sensor.h +0 -2
  18. esphome/components/anova/anova.cpp +5 -1
  19. esphome/components/anova/anova.h +0 -1
  20. esphome/components/apds9960/apds9960.cpp +1 -1
  21. esphome/components/api/__init__.py +42 -20
  22. esphome/components/api/api_connection.cpp +318 -391
  23. esphome/components/api/api_connection.h +206 -126
  24. esphome/components/api/api_frame_helper.cpp +89 -124
  25. esphome/components/api/api_frame_helper.h +57 -45
  26. esphome/components/api/api_pb2.cpp +414 -4350
  27. esphome/components/api/api_pb2.h +287 -198
  28. esphome/components/api/api_pb2_dump.cpp +4333 -0
  29. esphome/components/api/api_pb2_service.cpp +180 -425
  30. esphome/components/api/api_pb2_service.h +7 -6
  31. esphome/components/api/api_pb2_size.h +2 -4
  32. esphome/components/api/api_server.cpp +138 -167
  33. esphome/components/api/api_server.h +66 -12
  34. esphome/components/api/client.py +8 -2
  35. esphome/components/api/list_entities.cpp +36 -105
  36. esphome/components/api/list_entities.h +31 -23
  37. esphome/components/api/proto.h +26 -3
  38. esphome/components/api/subscribe_state.cpp +23 -29
  39. esphome/components/api/subscribe_state.h +26 -19
  40. esphome/components/as5600/as5600.h +0 -1
  41. esphome/components/async_tcp/__init__.py +14 -5
  42. esphome/components/atc_mithermometer/atc_mithermometer.h +0 -1
  43. esphome/components/atm90e32/atm90e32.cpp +2 -1
  44. esphome/components/audio/audio_decoder.cpp +1 -1
  45. esphome/components/audio/audio_transfer_buffer.cpp +2 -2
  46. esphome/components/b_parasite/b_parasite.h +0 -1
  47. esphome/components/bedjet/bedjet_hub.cpp +5 -1
  48. esphome/components/bedjet/climate/bedjet_climate.cpp +5 -1
  49. esphome/components/beken_spi_led_strip/led_strip.cpp +4 -2
  50. esphome/components/bh1750/bh1750.cpp +5 -5
  51. esphome/components/binary_sensor/__init__.py +82 -5
  52. esphome/components/binary_sensor/automation.h +19 -1
  53. esphome/components/binary_sensor/binary_sensor.cpp +12 -30
  54. esphome/components/binary_sensor/binary_sensor.h +11 -25
  55. esphome/components/binary_sensor/filter.cpp +29 -24
  56. esphome/components/binary_sensor/filter.h +20 -10
  57. esphome/components/ble_client/output/ble_binary_output.h +0 -1
  58. esphome/components/ble_client/sensor/ble_rssi_sensor.cpp +5 -1
  59. esphome/components/ble_client/sensor/ble_rssi_sensor.h +0 -1
  60. esphome/components/ble_client/sensor/ble_sensor.cpp +5 -1
  61. esphome/components/ble_client/sensor/ble_sensor.h +0 -1
  62. esphome/components/ble_client/switch/ble_switch.h +0 -1
  63. esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +5 -1
  64. esphome/components/ble_client/text_sensor/ble_text_sensor.h +0 -1
  65. esphome/components/ble_presence/ble_presence_device.h +0 -1
  66. esphome/components/ble_rssi/ble_rssi_sensor.h +0 -1
  67. esphome/components/ble_scanner/ble_scanner.h +0 -1
  68. esphome/components/bluetooth_proxy/bluetooth_connection.h +9 -2
  69. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +16 -6
  70. esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -2
  71. esphome/components/bme680/sensor.py +1 -1
  72. esphome/components/bmp581/bmp581.h +0 -2
  73. esphome/components/button/__init__.py +5 -2
  74. esphome/components/camera/__init__.py +1 -0
  75. esphome/components/camera/camera.cpp +22 -0
  76. esphome/components/camera/camera.h +80 -0
  77. esphome/components/canbus/__init__.py +1 -0
  78. esphome/components/cap1188/cap1188.h +0 -1
  79. esphome/components/captive_portal/__init__.py +12 -2
  80. esphome/components/captive_portal/captive_portal.cpp +12 -2
  81. esphome/components/captive_portal/captive_portal.h +5 -2
  82. esphome/components/ccs811/ccs811.h +0 -2
  83. esphome/components/climate/__init__.py +5 -2
  84. esphome/components/cm1106/sensor.py +2 -2
  85. esphome/components/const/__init__.py +2 -0
  86. esphome/components/copy/binary_sensor/copy_binary_sensor.h +0 -1
  87. esphome/components/copy/button/copy_button.h +0 -1
  88. esphome/components/copy/cover/copy_cover.h +0 -1
  89. esphome/components/copy/fan/copy_fan.h +0 -1
  90. esphome/components/copy/lock/copy_lock.h +0 -1
  91. esphome/components/copy/number/copy_number.h +0 -1
  92. esphome/components/copy/select/copy_select.h +0 -1
  93. esphome/components/copy/sensor/copy_sensor.h +0 -1
  94. esphome/components/copy/switch/copy_switch.h +0 -1
  95. esphome/components/copy/text/copy_text.h +0 -1
  96. esphome/components/copy/text_sensor/copy_text_sensor.h +0 -1
  97. esphome/components/cover/__init__.py +5 -2
  98. esphome/components/cs5460a/cs5460a.h +0 -1
  99. esphome/components/datetime/__init__.py +4 -2
  100. esphome/components/debug/__init__.py +20 -0
  101. esphome/components/deep_sleep/__init__.py +43 -9
  102. esphome/components/demo/__init__.py +2 -2
  103. esphome/components/display/display.cpp +4 -3
  104. esphome/components/display/display.h +0 -2
  105. esphome/components/display/display_buffer.cpp +1 -1
  106. esphome/components/ds2484/__init__.py +1 -0
  107. esphome/components/ds2484/ds2484.cpp +209 -0
  108. esphome/components/ds2484/ds2484.h +43 -0
  109. esphome/components/ds2484/one_wire.py +37 -0
  110. esphome/components/duty_time/duty_time_sensor.h +0 -1
  111. esphome/components/ens160_base/ens160_base.h +0 -1
  112. esphome/components/es7210/es7210.h +0 -1
  113. esphome/components/es7243e/es7243e.h +0 -1
  114. esphome/components/es8156/es8156.h +0 -1
  115. esphome/components/es8311/es8311.h +0 -1
  116. esphome/components/es8388/es8388.h +0 -1
  117. esphome/components/esp32/__init__.py +102 -135
  118. esphome/components/esp32/core.cpp +0 -4
  119. esphome/components/esp32/gpio.h +1 -1
  120. esphome/components/esp32/helpers.cpp +69 -0
  121. esphome/components/esp32_ble/ble.cpp +5 -6
  122. esphome/components/esp32_ble/ble.h +29 -14
  123. esphome/components/esp32_ble/ble_event.h +6 -6
  124. esphome/components/esp32_ble_client/ble_client_base.cpp +21 -6
  125. esphome/components/esp32_ble_client/ble_client_base.h +24 -9
  126. esphome/components/esp32_ble_tracker/__init__.py +2 -8
  127. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +5 -5
  128. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +11 -7
  129. esphome/components/esp32_camera/__init__.py +111 -97
  130. esphome/components/esp32_camera/esp32_camera.cpp +41 -31
  131. esphome/components/esp32_camera/esp32_camera.h +35 -30
  132. esphome/components/esp32_camera_web_server/__init__.py +2 -1
  133. esphome/components/esp32_camera_web_server/camera_web_server.cpp +8 -8
  134. esphome/components/esp32_camera_web_server/camera_web_server.h +3 -3
  135. esphome/components/esp32_hall/sensor.py +2 -21
  136. esphome/components/esp32_hosted/__init__.py +101 -0
  137. esphome/components/esp32_hosted/esp32_hosted.py.script +12 -0
  138. esphome/components/esp32_improv/esp32_improv_component.cpp +3 -0
  139. esphome/components/esp32_rmt/__init__.py +0 -58
  140. esphome/components/esp32_rmt_led_strip/led_strip.cpp +77 -63
  141. esphome/components/esp32_rmt_led_strip/led_strip.h +11 -17
  142. esphome/components/esp32_rmt_led_strip/light.py +14 -76
  143. esphome/components/esp32_touch/esp32_touch.h +174 -28
  144. esphome/components/esp32_touch/esp32_touch_common.cpp +162 -0
  145. esphome/components/esp32_touch/esp32_touch_v1.cpp +238 -0
  146. esphome/components/esp32_touch/esp32_touch_v2.cpp +397 -0
  147. esphome/components/esp8266/__init__.py +1 -0
  148. esphome/components/esp8266/gpio.cpp +10 -10
  149. esphome/components/esp8266/helpers.cpp +31 -0
  150. esphome/components/esphome/ota/__init__.py +1 -0
  151. esphome/components/esphome/ota/ota_esphome.cpp +24 -19
  152. esphome/components/ethernet/__init__.py +42 -23
  153. esphome/components/ethernet/esp_eth_phy_jl1101.c +0 -16
  154. esphome/components/ethernet/ethernet_component.cpp +69 -29
  155. esphome/components/ethernet/ethernet_component.h +18 -10
  156. esphome/components/event/__init__.py +5 -2
  157. esphome/components/ezo/ezo.h +0 -1
  158. esphome/components/ezo_pmp/ezo_pmp.h +0 -1
  159. esphome/components/fan/__init__.py +5 -2
  160. esphome/components/feedback/feedback_cover.h +0 -1
  161. esphome/components/font/__init__.py +92 -82
  162. esphome/components/font/font.cpp +9 -2
  163. esphome/components/font/font.h +20 -5
  164. esphome/components/fs3000/fs3000.h +0 -1
  165. esphome/components/gcja5/gcja5.h +0 -1
  166. esphome/components/gl_r01_i2c/__init__.py +0 -0
  167. esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +68 -0
  168. esphome/components/gl_r01_i2c/gl_r01_i2c.h +22 -0
  169. esphome/components/gl_r01_i2c/sensor.py +36 -0
  170. esphome/components/gp8403/gp8403.h +0 -1
  171. esphome/components/gpio/binary_sensor/__init__.py +17 -0
  172. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +77 -3
  173. esphome/components/gpio/binary_sensor/gpio_binary_sensor.h +40 -0
  174. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +0 -2
  175. esphome/components/he60r/he60r.h +0 -1
  176. esphome/components/heatpumpir/climate.py +2 -1
  177. esphome/components/heatpumpir/heatpumpir.cpp +1 -0
  178. esphome/components/heatpumpir/heatpumpir.h +1 -0
  179. esphome/components/honeywellabp2_i2c/honeywellabp2.h +0 -1
  180. esphome/components/host/__init__.py +2 -1
  181. esphome/components/host/helpers.cpp +57 -0
  182. esphome/components/http_request/__init__.py +19 -1
  183. esphome/components/http_request/http_request.h +1 -1
  184. esphome/components/http_request/http_request_arduino.h +1 -0
  185. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  186. esphome/components/http_request/update/http_request_update.cpp +28 -9
  187. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +3 -9
  188. esphome/components/hydreon_rgxx/sensor.py +1 -1
  189. esphome/components/i2c/__init__.py +23 -11
  190. esphome/components/i2c/i2c_bus.h +8 -1
  191. esphome/components/i2c/i2c_bus_arduino.cpp +4 -3
  192. esphome/components/i2c/i2c_bus_arduino.h +6 -3
  193. esphome/components/i2c/i2c_bus_esp_idf.h +5 -3
  194. esphome/components/i2c_device/i2c_device.h +0 -1
  195. esphome/components/i2s_audio/__init__.py +2 -10
  196. esphome/components/i2s_audio/i2s_audio.cpp +1 -5
  197. esphome/components/i2s_audio/media_player/__init__.py +2 -2
  198. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +2 -2
  199. esphome/components/iaqcore/iaqcore.h +0 -2
  200. esphome/components/image/__init__.py +123 -24
  201. esphome/components/improv_serial/improv_serial_component.cpp +0 -4
  202. esphome/components/ina219/ina219.cpp +7 -0
  203. esphome/components/ina219/ina219.h +1 -0
  204. esphome/components/ina260/ina260.h +0 -2
  205. esphome/components/inkbird_ibsth1_mini/inkbird_ibsth1_mini.h +0 -1
  206. esphome/components/inkplate6/display.py +15 -0
  207. esphome/components/inkplate6/inkplate.cpp +2 -2
  208. esphome/components/integration/integration_sensor.h +0 -1
  209. esphome/components/internal_temperature/internal_temperature.cpp +8 -27
  210. esphome/components/internal_temperature/sensor.py +0 -26
  211. esphome/components/interval/interval.h +0 -2
  212. esphome/components/ld2410/button/__init__.py +3 -3
  213. esphome/components/ld2410/button/factory_reset_button.cpp +9 -0
  214. esphome/components/ld2410/button/{reset_button.h → factory_reset_button.h} +2 -2
  215. esphome/components/ld2410/ld2410.cpp +430 -261
  216. esphome/components/ld2410/ld2410.h +44 -146
  217. esphome/components/ld2410/number/__init__.py +2 -2
  218. esphome/components/ld2410/sensor.py +1 -1
  219. esphome/components/ld2410/switch/__init__.py +1 -1
  220. esphome/components/ld2420/ld2420.cpp +196 -100
  221. esphome/components/ld2420/ld2420.h +46 -118
  222. esphome/components/ld2420/number/__init__.py +2 -2
  223. esphome/components/ld2420/sensor/__init__.py +6 -2
  224. esphome/components/ld2420/sensor/ld2420_sensor.h +1 -1
  225. esphome/components/ld2450/button/__init__.py +3 -3
  226. esphome/components/ld2450/button/factory_reset_button.cpp +9 -0
  227. esphome/components/ld2450/button/{reset_button.h → factory_reset_button.h} +2 -2
  228. esphome/components/ld2450/ld2450.cpp +384 -232
  229. esphome/components/ld2450/ld2450.h +60 -69
  230. esphome/components/ld2450/switch/__init__.py +1 -1
  231. esphome/components/ledc/ledc_output.cpp +1 -63
  232. esphome/components/libretiny/__init__.py +4 -3
  233. esphome/components/libretiny/const.py +5 -0
  234. esphome/components/libretiny/generate_components.py +1 -0
  235. esphome/components/libretiny/helpers.cpp +35 -0
  236. esphome/components/libretiny/lt_component.cpp +5 -3
  237. esphome/components/light/__init__.py +4 -2
  238. esphome/components/light/addressable_light.h +3 -3
  239. esphome/components/light/light_call.cpp +180 -243
  240. esphome/components/light/light_call.h +72 -20
  241. esphome/components/light/light_color_values.h +14 -14
  242. esphome/components/light/light_state.h +15 -13
  243. esphome/components/light/transformers.h +2 -2
  244. esphome/components/ln882x/__init__.py +52 -0
  245. esphome/components/ln882x/boards.py +285 -0
  246. esphome/components/lock/__init__.py +5 -2
  247. esphome/components/logger/__init__.py +40 -3
  248. esphome/components/logger/logger.cpp +47 -12
  249. esphome/components/logger/logger.h +80 -49
  250. esphome/components/logger/logger_esp32.cpp +3 -3
  251. esphome/components/lps22/__init__.py +0 -0
  252. esphome/components/lps22/lps22.cpp +75 -0
  253. esphome/components/lps22/lps22.h +27 -0
  254. esphome/components/lps22/sensor.py +58 -0
  255. esphome/components/ltr390/ltr390.h +0 -1
  256. esphome/components/ltr501/ltr501.h +0 -1
  257. esphome/components/ltr_als_ps/ltr_als_ps.h +0 -1
  258. esphome/components/lvgl/__init__.py +1 -1
  259. esphome/components/lvgl/schemas.py +66 -6
  260. esphome/components/lvgl/styles.py +24 -16
  261. esphome/components/lvgl/widgets/__init__.py +12 -2
  262. esphome/components/lvgl/widgets/lv_bar.py +40 -19
  263. esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +1 -1
  264. esphome/components/max9611/max9611.h +0 -1
  265. esphome/components/mcp23016/__init__.py +1 -1
  266. esphome/components/mcp23xxx_base/__init__.py +1 -1
  267. esphome/components/mcp4461/__init__.py +1 -1
  268. esphome/components/mcp4461/output/__init__.py +3 -2
  269. esphome/components/mcp9600/mcp9600.h +0 -2
  270. esphome/components/md5/md5.cpp +3 -3
  271. esphome/components/md5/md5.h +1 -6
  272. esphome/components/mdns/__init__.py +22 -11
  273. esphome/components/media_player/__init__.py +4 -3
  274. esphome/components/micro_wake_word/__init__.py +1 -5
  275. esphome/components/micro_wake_word/streaming_model.cpp +2 -2
  276. esphome/components/microphone/microphone.cpp +7 -9
  277. esphome/components/microphone/microphone.h +0 -2
  278. esphome/components/mipi_spi/display.py +1 -0
  279. esphome/components/mmc5603/mmc5603.cpp +1 -1
  280. esphome/components/modbus/modbus.cpp +33 -15
  281. esphome/components/modbus/modbus.h +9 -0
  282. esphome/components/modbus_controller/__init__.py +42 -10
  283. esphome/components/modbus_controller/modbus_controller.cpp +92 -11
  284. esphome/components/modbus_controller/modbus_controller.h +61 -7
  285. esphome/components/mopeka_pro_check/mopeka_pro_check.h +0 -1
  286. esphome/components/mopeka_std_check/mopeka_std_check.h +0 -1
  287. esphome/components/mpl3115a2/mpl3115a2.h +0 -2
  288. esphome/components/mqtt/__init__.py +16 -0
  289. esphome/components/mqtt/mqtt_backend.h +2 -1
  290. esphome/components/mqtt/mqtt_backend_esp32.cpp +126 -45
  291. esphome/components/mqtt/mqtt_backend_esp32.h +106 -4
  292. esphome/components/mqtt/mqtt_client.cpp +15 -9
  293. esphome/components/mqtt/mqtt_client.h +8 -3
  294. esphome/components/ms8607/ms8607.h +0 -1
  295. esphome/components/neopixelbus/light.py +4 -1
  296. esphome/components/neopixelbus/neopixelbus_light.h +1 -1
  297. esphome/components/network/__init__.py +4 -1
  298. esphome/components/network/ip_address.h +1 -0
  299. esphome/components/nextion/__init__.py +16 -0
  300. esphome/components/nextion/base_component.py +1 -0
  301. esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +1 -1
  302. esphome/components/nextion/display.py +14 -4
  303. esphome/components/nextion/nextion.cpp +166 -101
  304. esphome/components/nextion/nextion.h +84 -53
  305. esphome/components/nextion/nextion_commands.cpp +11 -10
  306. esphome/components/nextion/nextion_component.cpp +28 -28
  307. esphome/components/nextion/nextion_component.h +53 -18
  308. esphome/components/nextion/nextion_component_base.h +3 -0
  309. esphome/components/nextion/nextion_upload.cpp +36 -0
  310. esphome/components/nextion/nextion_upload_arduino.cpp +10 -35
  311. esphome/components/nextion/nextion_upload_idf.cpp +9 -33
  312. esphome/components/nextion/sensor/nextion_sensor.cpp +1 -1
  313. esphome/components/nextion/switch/nextion_switch.cpp +1 -1
  314. esphome/components/nextion/text_sensor/nextion_textsensor.cpp +1 -1
  315. esphome/components/nfc/nfc.cpp +3 -22
  316. esphome/components/nfc/nfc.h +3 -3
  317. esphome/components/number/__init__.py +5 -2
  318. esphome/components/online_image/__init__.py +5 -0
  319. esphome/components/online_image/online_image.cpp +6 -2
  320. esphome/components/online_image/online_image.h +4 -1
  321. esphome/components/opentherm/opentherm.cpp +7 -12
  322. esphome/components/openthread/__init__.py +47 -40
  323. esphome/components/openthread/const.py +1 -0
  324. esphome/components/openthread/openthread_esp.cpp +27 -5
  325. esphome/components/opt3001/__init__.py +0 -0
  326. esphome/components/opt3001/opt3001.cpp +122 -0
  327. esphome/components/opt3001/opt3001.h +27 -0
  328. esphome/components/opt3001/sensor.py +35 -0
  329. esphome/components/ota/__init__.py +17 -0
  330. esphome/components/ota/ota_backend.h +27 -1
  331. esphome/components/ota/ota_backend_arduino_esp32.cpp +12 -2
  332. esphome/components/ota/ota_backend_arduino_esp32.h +3 -0
  333. esphome/components/ota/ota_backend_arduino_esp8266.cpp +18 -4
  334. esphome/components/ota/ota_backend_arduino_esp8266.h +3 -0
  335. esphome/components/ota/ota_backend_arduino_libretiny.cpp +12 -2
  336. esphome/components/ota/ota_backend_arduino_libretiny.h +3 -0
  337. esphome/components/ota/ota_backend_arduino_rp2040.cpp +9 -2
  338. esphome/components/ota/ota_backend_arduino_rp2040.h +3 -0
  339. esphome/components/ota/ota_backend_esp_idf.cpp +10 -16
  340. esphome/components/ota/ota_backend_esp_idf.h +1 -0
  341. esphome/components/packages/__init__.py +5 -2
  342. esphome/components/packet_transport/binary_sensor.py +61 -4
  343. esphome/components/packet_transport/packet_transport.cpp +31 -1
  344. esphome/components/packet_transport/packet_transport.h +11 -5
  345. esphome/components/pcf8574/__init__.py +1 -1
  346. esphome/components/pi4ioe5v6408/__init__.py +84 -0
  347. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +171 -0
  348. esphome/components/pi4ioe5v6408/pi4ioe5v6408.h +70 -0
  349. esphome/components/pmsa003i/pmsa003i.h +0 -1
  350. esphome/components/pmsx003/pmsx003.h +0 -1
  351. esphome/components/pn7150/pn7150.cpp +7 -7
  352. esphome/components/pn7150/pn7150.h +0 -1
  353. esphome/components/pn7160/pn7160.cpp +7 -7
  354. esphome/components/pn7160/pn7160.h +0 -1
  355. esphome/components/preferences/syncer.h +2 -0
  356. esphome/components/prometheus/prometheus_handler.h +1 -1
  357. esphome/components/psram/psram.cpp +0 -20
  358. esphome/components/pulse_counter/pulse_counter_sensor.h +0 -1
  359. esphome/components/pulse_meter/pulse_meter_sensor.cpp +8 -4
  360. esphome/components/pulse_width/pulse_width.h +0 -1
  361. esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +0 -4
  362. esphome/components/pvvx_mithermometer/display/pvvx_display.h +0 -2
  363. esphome/components/pvvx_mithermometer/pvvx_mithermometer.h +0 -1
  364. esphome/components/qr_code/__init__.py +13 -10
  365. esphome/components/qwiic_pir/qwiic_pir.h +0 -1
  366. esphome/components/radon_eye_ble/radon_eye_listener.cpp +1 -1
  367. esphome/components/rc522/rc522.h +0 -1
  368. esphome/components/rdm6300/rdm6300.h +0 -2
  369. esphome/components/remote_base/__init__.py +7 -5
  370. esphome/components/remote_base/remote_base.cpp +24 -21
  371. esphome/components/remote_base/remote_base.h +3 -26
  372. esphome/components/remote_receiver/__init__.py +40 -46
  373. esphome/components/remote_receiver/remote_receiver.h +4 -18
  374. esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -87
  375. esphome/components/remote_receiver/remote_receiver_esp8266.cpp +1 -1
  376. esphome/components/remote_transmitter/__init__.py +42 -43
  377. esphome/components/remote_transmitter/remote_transmitter.h +2 -14
  378. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -77
  379. esphome/components/resistance/resistance_sensor.h +0 -1
  380. esphome/components/rp2040/__init__.py +1 -0
  381. esphome/components/rp2040/helpers.cpp +55 -0
  382. esphome/components/rp2040_pio_led_strip/led_strip.cpp +2 -2
  383. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -4
  384. esphome/components/rtttl/__init__.py +4 -4
  385. esphome/components/rtttl/rtttl.cpp +10 -1
  386. esphome/components/ruuvitag/ruuvitag.h +0 -1
  387. esphome/components/safe_mode/safe_mode.cpp +2 -0
  388. esphome/components/safe_mode/safe_mode.h +4 -1
  389. esphome/components/scd30/scd30.h +0 -1
  390. esphome/components/scd30/sensor.py +2 -2
  391. esphome/components/scd4x/scd4x.cpp +61 -54
  392. esphome/components/scd4x/scd4x.h +17 -15
  393. esphome/components/scd4x/sensor.py +4 -4
  394. esphome/components/script/script.h +0 -2
  395. esphome/components/sdp3x/sensor.py +1 -1
  396. esphome/components/select/__init__.py +5 -2
  397. esphome/components/sen5x/sen5x.h +0 -1
  398. esphome/components/senseair/senseair.h +0 -1
  399. esphome/components/sensor/__init__.py +4 -2
  400. esphome/components/sensor/filter.cpp +1 -1
  401. esphome/components/sensor/sensor.cpp +12 -6
  402. esphome/components/sensor/sensor.h +13 -5
  403. esphome/components/servo/servo.h +0 -1
  404. esphome/components/sfa30/sfa30.h +0 -1
  405. esphome/components/sgp30/sgp30.h +0 -1
  406. esphome/components/sgp4x/sgp4x.h +0 -1
  407. esphome/components/shelly_dimmer/stm32flash.cpp +1 -2
  408. esphome/components/sht4x/sht4x.h +0 -1
  409. esphome/components/sm300d2/sm300d2.h +0 -2
  410. esphome/components/smt100/sensor.py +8 -4
  411. esphome/components/smt100/smt100.cpp +5 -5
  412. esphome/components/smt100/smt100.h +3 -3
  413. esphome/components/sn74hc595/__init__.py +1 -1
  414. esphome/components/sn74hc595/sn74hc595.cpp +5 -4
  415. esphome/components/sntp/sntp_component.cpp +9 -3
  416. esphome/components/sntp/time.py +2 -0
  417. esphome/components/socket/__init__.py +17 -0
  418. esphome/components/spi/__init__.py +27 -6
  419. esphome/components/spi/spi.cpp +3 -2
  420. esphome/components/spi/spi.h +9 -3
  421. esphome/components/spi/spi_arduino.cpp +3 -5
  422. esphome/components/spi/spi_esp_idf.cpp +40 -21
  423. esphome/components/spi_led_strip/spi_led_strip.cpp +1 -1
  424. esphome/components/sps30/sps30.h +0 -1
  425. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  426. esphome/components/st7701s/st7701s.cpp +0 -4
  427. esphome/components/status/status_binary_sensor.h +0 -2
  428. esphome/components/substitutions/__init__.py +76 -19
  429. esphome/components/substitutions/jinja.py +99 -0
  430. esphome/components/sun/sun.cpp +3 -4
  431. esphome/components/switch/__init__.py +5 -2
  432. esphome/components/switch/binary_sensor/switch_binary_sensor.h +0 -1
  433. esphome/components/sx126x/__init__.py +317 -0
  434. esphome/components/sx126x/automation.h +62 -0
  435. esphome/components/sx126x/packet_transport/__init__.py +26 -0
  436. esphome/components/sx126x/packet_transport/sx126x_transport.cpp +26 -0
  437. esphome/components/sx126x/packet_transport/sx126x_transport.h +25 -0
  438. esphome/components/sx126x/sx126x.cpp +523 -0
  439. esphome/components/sx126x/sx126x.h +140 -0
  440. esphome/components/sx126x/sx126x_reg.h +163 -0
  441. esphome/components/sx127x/__init__.py +325 -0
  442. esphome/components/sx127x/automation.h +62 -0
  443. esphome/components/sx127x/packet_transport/__init__.py +26 -0
  444. esphome/components/sx127x/packet_transport/sx127x_transport.cpp +26 -0
  445. esphome/components/sx127x/packet_transport/sx127x_transport.h +25 -0
  446. esphome/components/sx127x/sx127x.cpp +498 -0
  447. esphome/components/sx127x/sx127x.h +128 -0
  448. esphome/components/sx127x/sx127x_reg.h +295 -0
  449. esphome/components/syslog/esphome_syslog.cpp +5 -3
  450. esphome/components/syslog/esphome_syslog.h +1 -1
  451. esphome/components/tca9555/__init__.py +1 -1
  452. esphome/components/template/binary_sensor/template_binary_sensor.cpp +1 -9
  453. esphome/components/text/__init__.py +5 -2
  454. esphome/components/text_sensor/__init__.py +5 -2
  455. esphome/components/thermostat/thermostat_climate.cpp +34 -31
  456. esphome/components/thermostat/thermostat_climate.h +43 -39
  457. esphome/components/time/__init__.py +16 -2
  458. esphome/components/time/real_time_clock.cpp +4 -0
  459. esphome/components/time/real_time_clock.h +5 -1
  460. esphome/components/tlc5971/tlc5971.cpp +4 -1
  461. esphome/components/tmp1075/tmp1075.h +0 -2
  462. esphome/components/tof10120/tof10120_sensor.h +0 -1
  463. esphome/components/tormatic/tormatic_cover.h +0 -1
  464. esphome/components/total_daily_energy/total_daily_energy.h +0 -1
  465. esphome/components/tsl2591/tsl2591.cpp +1 -1
  466. esphome/components/ttp229_bsf/ttp229_bsf.h +0 -1
  467. esphome/components/ttp229_lsf/ttp229_lsf.h +0 -1
  468. esphome/components/tx20/tx20.cpp +2 -2
  469. esphome/components/uart/__init__.py +18 -0
  470. esphome/components/uart/uart_component_esp_idf.cpp +0 -4
  471. esphome/components/update/__init__.py +5 -2
  472. esphome/components/update/update_entity.h +8 -0
  473. esphome/components/usb_host/__init__.py +5 -2
  474. esphome/components/valve/__init__.py +5 -2
  475. esphome/components/vbus/vbus.h +0 -1
  476. esphome/components/veml3235/veml3235.h +0 -1
  477. esphome/components/veml7700/veml7700.h +0 -1
  478. esphome/components/vl53l0x/vl53l0x_sensor.h +0 -1
  479. esphome/components/voice_assistant/voice_assistant.cpp +4 -4
  480. esphome/components/watchdog/watchdog.cpp +0 -4
  481. esphome/components/waveshare_epaper/waveshare_epaper.cpp +6 -6
  482. esphome/components/web_server/__init__.py +34 -19
  483. esphome/components/web_server/ota/__init__.py +32 -0
  484. esphome/components/web_server/ota/ota_web_server.cpp +210 -0
  485. esphome/components/web_server/ota/ota_web_server.h +26 -0
  486. esphome/components/web_server/web_server.cpp +305 -427
  487. esphome/components/web_server/web_server.h +33 -23
  488. esphome/components/web_server/web_server_v1.cpp +4 -5
  489. esphome/components/web_server_base/__init__.py +5 -2
  490. esphome/components/web_server_base/web_server_base.cpp +2 -94
  491. esphome/components/web_server_base/web_server_base.h +5 -25
  492. esphome/components/web_server_idf/multipart.cpp +254 -0
  493. esphome/components/web_server_idf/multipart.h +86 -0
  494. esphome/components/web_server_idf/utils.cpp +32 -0
  495. esphome/components/web_server_idf/utils.h +10 -0
  496. esphome/components/web_server_idf/web_server_idf.cpp +162 -16
  497. esphome/components/web_server_idf/web_server_idf.h +11 -10
  498. esphome/components/wiegand/wiegand.cpp +2 -2
  499. esphome/components/wifi/__init__.py +18 -0
  500. esphome/components/wifi/wifi_component.cpp +17 -22
  501. esphome/components/wifi/wifi_component.h +27 -23
  502. esphome/components/wifi/wifi_component_esp32_arduino.cpp +52 -59
  503. esphome/components/wifi/wifi_component_esp8266.cpp +46 -46
  504. esphome/components/wifi/wifi_component_esp_idf.cpp +35 -36
  505. esphome/components/wifi/wifi_component_libretiny.cpp +26 -27
  506. esphome/components/wifi/wifi_component_pico_w.cpp +3 -3
  507. esphome/components/wifi_info/wifi_info_text_sensor.cpp +6 -6
  508. esphome/components/wireguard/__init__.py +2 -11
  509. esphome/components/xiaomi_ble/xiaomi_ble.cpp +13 -1
  510. esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
  511. esphome/components/xiaomi_cgd1/xiaomi_cgd1.h +0 -1
  512. esphome/components/xiaomi_cgdk2/xiaomi_cgdk2.h +0 -1
  513. esphome/components/xiaomi_cgg1/xiaomi_cgg1.h +0 -1
  514. esphome/components/xiaomi_cgpr1/xiaomi_cgpr1.h +0 -1
  515. esphome/components/xiaomi_gcls002/xiaomi_gcls002.h +0 -1
  516. esphome/components/xiaomi_hhccjcy01/xiaomi_hhccjcy01.h +0 -1
  517. esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h +0 -1
  518. esphome/components/xiaomi_hhccpot002/xiaomi_hhccpot002.h +0 -1
  519. esphome/components/xiaomi_jqjcy01ym/xiaomi_jqjcy01ym.h +0 -1
  520. esphome/components/xiaomi_lywsd02/xiaomi_lywsd02.h +0 -1
  521. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +0 -1
  522. esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.h +0 -1
  523. esphome/components/xiaomi_lywsdcgq/xiaomi_lywsdcgq.h +0 -1
  524. esphome/components/xiaomi_mhoc303/xiaomi_mhoc303.h +0 -1
  525. esphome/components/xiaomi_mhoc401/xiaomi_mhoc401.h +0 -1
  526. esphome/components/xiaomi_miscale/xiaomi_miscale.h +0 -1
  527. esphome/components/xiaomi_mjyd02yla/xiaomi_mjyd02yla.h +0 -1
  528. esphome/components/xiaomi_mue4094rt/xiaomi_mue4094rt.h +0 -1
  529. esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.h +0 -1
  530. esphome/components/xiaomi_wx08zm/xiaomi_wx08zm.h +0 -1
  531. esphome/components/xiaomi_xmwsdj04mmc/__init__.py +0 -0
  532. esphome/components/xiaomi_xmwsdj04mmc/sensor.py +77 -0
  533. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp +77 -0
  534. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.h +36 -0
  535. esphome/components/zio_ultrasonic/zio_ultrasonic.h +0 -2
  536. esphome/components/zyaura/zyaura.h +0 -1
  537. esphome/config.py +88 -22
  538. esphome/config_helpers.py +74 -1
  539. esphome/config_validation.py +12 -1
  540. esphome/const.py +65 -10
  541. esphome/core/__init__.py +18 -2
  542. esphome/core/application.cpp +163 -10
  543. esphome/core/application.h +145 -165
  544. esphome/core/area.h +19 -0
  545. esphome/core/automation.h +58 -9
  546. esphome/core/color.cpp +3 -5
  547. esphome/core/color.h +16 -16
  548. esphome/core/component.cpp +151 -18
  549. esphome/core/component.h +98 -4
  550. esphome/core/component_iterator.cpp +7 -7
  551. esphome/core/component_iterator.h +9 -7
  552. esphome/core/config.py +155 -6
  553. esphome/core/controller.cpp +4 -2
  554. esphome/core/controller.h +1 -1
  555. esphome/core/datatypes.h +2 -2
  556. esphome/core/defines.h +17 -2
  557. esphome/core/device.h +20 -0
  558. esphome/core/entity_base.cpp +20 -15
  559. esphome/core/entity_base.h +76 -0
  560. esphome/core/entity_helpers.py +162 -1
  561. esphome/core/event_pool.h +81 -0
  562. esphome/core/helpers.cpp +75 -230
  563. esphome/core/helpers.h +164 -104
  564. esphome/core/lock_free_queue.h +151 -0
  565. esphome/core/log.cpp +2 -2
  566. esphome/core/log.h +2 -0
  567. esphome/core/optional.h +5 -0
  568. esphome/core/ring_buffer.cpp +2 -2
  569. esphome/core/scheduler.cpp +278 -103
  570. esphome/core/scheduler.h +157 -17
  571. esphome/core/time.cpp +5 -5
  572. esphome/core/time.h +5 -5
  573. esphome/cpp_generator.py +17 -0
  574. esphome/cpp_helpers.py +0 -22
  575. esphome/cpp_types.py +3 -1
  576. esphome/dashboard/entries.py +1 -1
  577. esphome/dashboard/util/text.py +5 -21
  578. esphome/dashboard/web_server.py +9 -1
  579. esphome/helpers.py +47 -0
  580. esphome/loader.py +15 -1
  581. esphome/pins.py +14 -8
  582. esphome/wizard.py +16 -3
  583. esphome/writer.py +21 -3
  584. esphome/yaml_util.py +0 -2
  585. {esphome-2025.6.3.dist-info → esphome-2025.7.0b1.dist-info}/METADATA +10 -9
  586. {esphome-2025.6.3.dist-info → esphome-2025.7.0b1.dist-info}/RECORD +591 -531
  587. esphome/components/esp32_ble/ble_event_pool.h +0 -72
  588. esphome/components/esp32_ble/queue.h +0 -85
  589. esphome/components/esp32_hall/esp32_hall.cpp +0 -25
  590. esphome/components/esp32_hall/esp32_hall.h +0 -23
  591. esphome/components/esp32_touch/esp32_touch.cpp +0 -355
  592. esphome/components/ld2410/button/reset_button.cpp +0 -9
  593. esphome/components/ld2450/button/reset_button.cpp +0 -9
  594. esphome/components/openthread/tlv.py +0 -65
  595. /esphome/{dashboard/enum.py → enum.py} +0 -0
  596. {esphome-2025.6.3.dist-info → esphome-2025.7.0b1.dist-info}/WHEEL +0 -0
  597. {esphome-2025.6.3.dist-info → esphome-2025.7.0b1.dist-info}/entry_points.txt +0 -0
  598. {esphome-2025.6.3.dist-info → esphome-2025.7.0b1.dist-info}/licenses/LICENSE +0 -0
  599. {esphome-2025.6.3.dist-info → esphome-2025.7.0b1.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  from collections.abc import MutableMapping
2
2
  import functools
3
3
  import hashlib
4
+ from itertools import accumulate
4
5
  import logging
5
6
  import os
6
7
  from pathlib import Path
@@ -468,8 +469,9 @@ class EFont:
468
469
 
469
470
 
470
471
  class GlyphInfo:
471
- def __init__(self, data_len, advance, offset_x, offset_y, width, height):
472
- self.data_len = data_len
472
+ def __init__(self, glyph, data, advance, offset_x, offset_y, width, height):
473
+ self.glyph = glyph
474
+ self.bitmap_data = data
473
475
  self.advance = advance
474
476
  self.offset_x = offset_x
475
477
  self.offset_y = offset_y
@@ -477,6 +479,62 @@ class GlyphInfo:
477
479
  self.height = height
478
480
 
479
481
 
482
+ def glyph_to_glyphinfo(glyph, font, size, bpp):
483
+ scale = 256 // (1 << bpp)
484
+ if not font.is_scalable:
485
+ sizes = [pt_to_px(x.size) for x in font.available_sizes]
486
+ if size in sizes:
487
+ font.select_size(sizes.index(size))
488
+ else:
489
+ font.set_pixel_sizes(size, 0)
490
+ flags = FT_LOAD_RENDER
491
+ if bpp != 1:
492
+ flags |= FT_LOAD_NO_BITMAP
493
+ else:
494
+ flags |= FT_LOAD_TARGET_MONO
495
+ font.load_char(glyph, flags)
496
+ width = font.glyph.bitmap.width
497
+ height = font.glyph.bitmap.rows
498
+ buffer = font.glyph.bitmap.buffer
499
+ pitch = font.glyph.bitmap.pitch
500
+ glyph_data = [0] * ((height * width * bpp + 7) // 8)
501
+ src_mode = font.glyph.bitmap.pixel_mode
502
+ pos = 0
503
+ for y in range(height):
504
+ for x in range(width):
505
+ if src_mode == ft_pixel_mode_mono:
506
+ pixel = (
507
+ (1 << bpp) - 1
508
+ if buffer[y * pitch + x // 8] & (1 << (7 - x % 8))
509
+ else 0
510
+ )
511
+ else:
512
+ pixel = buffer[y * pitch + x] // scale
513
+ for bit_num in range(bpp):
514
+ if pixel & (1 << (bpp - bit_num - 1)):
515
+ glyph_data[pos // 8] |= 0x80 >> (pos % 8)
516
+ pos += 1
517
+ ascender = pt_to_px(font.size.ascender)
518
+ if ascender == 0:
519
+ if not font.is_scalable:
520
+ ascender = size
521
+ else:
522
+ _LOGGER.error(
523
+ "Unable to determine ascender of font %s %s",
524
+ font.family_name,
525
+ font.style_name,
526
+ )
527
+ return GlyphInfo(
528
+ glyph,
529
+ glyph_data,
530
+ pt_to_px(font.glyph.metrics.horiAdvance),
531
+ font.glyph.bitmap_left,
532
+ ascender - font.glyph.bitmap_top,
533
+ width,
534
+ height,
535
+ )
536
+
537
+
480
538
  async def to_code(config):
481
539
  """
482
540
  Collect all glyph codepoints, construct a map from a codepoint to a font file.
@@ -506,98 +564,47 @@ async def to_code(config):
506
564
 
507
565
  codepoints = list(point_set)
508
566
  codepoints.sort(key=functools.cmp_to_key(glyph_comparator))
509
- glyph_args = {}
510
- data = []
511
567
  bpp = config[CONF_BPP]
512
- scale = 256 // (1 << bpp)
513
568
  size = config[CONF_SIZE]
514
569
  # create the data array for all glyphs
515
- for codepoint in codepoints:
516
- font = point_font_map[codepoint]
517
- if not font.is_scalable:
518
- sizes = [pt_to_px(x.size) for x in font.available_sizes]
519
- if size in sizes:
520
- font.select_size(sizes.index(size))
521
- else:
522
- font.set_pixel_sizes(size, 0)
523
- flags = FT_LOAD_RENDER
524
- if bpp != 1:
525
- flags |= FT_LOAD_NO_BITMAP
526
- else:
527
- flags |= FT_LOAD_TARGET_MONO
528
- font.load_char(codepoint, flags)
529
- width = font.glyph.bitmap.width
530
- height = font.glyph.bitmap.rows
531
- buffer = font.glyph.bitmap.buffer
532
- pitch = font.glyph.bitmap.pitch
533
- glyph_data = [0] * ((height * width * bpp + 7) // 8)
534
- src_mode = font.glyph.bitmap.pixel_mode
535
- pos = 0
536
- for y in range(height):
537
- for x in range(width):
538
- if src_mode == ft_pixel_mode_mono:
539
- pixel = (
540
- (1 << bpp) - 1
541
- if buffer[y * pitch + x // 8] & (1 << (7 - x % 8))
542
- else 0
543
- )
544
- else:
545
- pixel = buffer[y * pitch + x] // scale
546
- for bit_num in range(bpp):
547
- if pixel & (1 << (bpp - bit_num - 1)):
548
- glyph_data[pos // 8] |= 0x80 >> (pos % 8)
549
- pos += 1
550
- ascender = pt_to_px(font.size.ascender)
551
- if ascender == 0:
552
- if not font.is_scalable:
553
- ascender = size
554
- else:
555
- _LOGGER.error(
556
- "Unable to determine ascender of font %s", config[CONF_FILE]
557
- )
558
- glyph_args[codepoint] = GlyphInfo(
559
- len(data),
560
- pt_to_px(font.glyph.metrics.horiAdvance),
561
- font.glyph.bitmap_left,
562
- ascender - font.glyph.bitmap_top,
563
- width,
564
- height,
565
- )
566
- data += glyph_data
567
-
568
- rhs = [HexInt(x) for x in data]
570
+ glyph_args = [
571
+ glyph_to_glyphinfo(x, point_font_map[x], size, bpp) for x in codepoints
572
+ ]
573
+ rhs = [HexInt(x) for x in flatten([x.bitmap_data for x in glyph_args])]
569
574
  prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs)
570
575
 
571
576
  # Create the glyph table that points to data in the above array.
572
- glyph_initializer = []
573
- for codepoint in codepoints:
574
- glyph_initializer.append(
575
- cg.StructInitializer(
576
- GlyphData,
577
- (
578
- "a_char",
579
- cg.RawExpression(
580
- f"(const uint8_t *){cpp_string_escape(codepoint)}"
581
- ),
582
- ),
583
- (
584
- "data",
585
- cg.RawExpression(
586
- f"{str(prog_arr)} + {str(glyph_args[codepoint].data_len)}"
587
- ),
588
- ),
589
- ("advance", glyph_args[codepoint].advance),
590
- ("offset_x", glyph_args[codepoint].offset_x),
591
- ("offset_y", glyph_args[codepoint].offset_y),
592
- ("width", glyph_args[codepoint].width),
593
- ("height", glyph_args[codepoint].height),
594
- )
577
+ glyph_initializer = [
578
+ cg.StructInitializer(
579
+ GlyphData,
580
+ (
581
+ "a_char",
582
+ cg.RawExpression(f"(const uint8_t *){cpp_string_escape(x.glyph)}"),
583
+ ),
584
+ (
585
+ "data",
586
+ cg.RawExpression(f"{str(prog_arr)} + {str(y - len(x.bitmap_data))}"),
587
+ ),
588
+ ("advance", x.advance),
589
+ ("offset_x", x.offset_x),
590
+ ("offset_y", x.offset_y),
591
+ ("width", x.width),
592
+ ("height", x.height),
593
+ )
594
+ for (x, y) in zip(
595
+ glyph_args, list(accumulate([len(x.bitmap_data) for x in glyph_args]))
595
596
  )
597
+ ]
596
598
 
597
599
  glyphs = cg.static_const_array(config[CONF_RAW_GLYPH_ID], glyph_initializer)
598
600
 
599
601
  font_height = pt_to_px(base_font.size.height)
600
602
  ascender = pt_to_px(base_font.size.ascender)
603
+ descender = abs(pt_to_px(base_font.size.descender))
604
+ g = glyph_to_glyphinfo("x", base_font, size, bpp)
605
+ xheight = g.height if len(g.bitmap_data) > 1 else 0
606
+ g = glyph_to_glyphinfo("X", base_font, size, bpp)
607
+ capheight = g.height if len(g.bitmap_data) > 1 else 0
601
608
  if font_height == 0:
602
609
  if not base_font.is_scalable:
603
610
  font_height = size
@@ -610,5 +617,8 @@ async def to_code(config):
610
617
  len(glyph_initializer),
611
618
  ascender,
612
619
  font_height,
620
+ descender,
621
+ xheight,
622
+ capheight,
613
623
  bpp,
614
624
  )
@@ -45,8 +45,15 @@ void Glyph::scan_area(int *x1, int *y1, int *width, int *height) const {
45
45
  *height = this->glyph_data_->height;
46
46
  }
47
47
 
48
- Font::Font(const GlyphData *data, int data_nr, int baseline, int height, uint8_t bpp)
49
- : baseline_(baseline), height_(height), bpp_(bpp) {
48
+ Font::Font(const GlyphData *data, int data_nr, int baseline, int height, int descender, int xheight, int capheight,
49
+ uint8_t bpp)
50
+ : baseline_(baseline),
51
+ height_(height),
52
+ descender_(descender),
53
+ linegap_(height - baseline - descender),
54
+ xheight_(xheight),
55
+ capheight_(capheight),
56
+ bpp_(bpp) {
50
57
  glyphs_.reserve(data_nr);
51
58
  for (int i = 0; i < data_nr; ++i)
52
59
  glyphs_.emplace_back(&data[i]);
@@ -50,11 +50,17 @@ class Font
50
50
  public:
51
51
  /** Construct the font with the given glyphs.
52
52
  *
53
- * @param glyphs A vector of glyphs, must be sorted lexicographically.
53
+ * @param data A vector of glyphs, must be sorted lexicographically.
54
+ * @param data_nr The number of glyphs in data.
54
55
  * @param baseline The y-offset from the top of the text to the baseline.
55
- * @param bottom The y-offset from the top of the text to the bottom (i.e. height).
56
+ * @param height The y-offset from the top of the text to the bottom.
57
+ * @param descender The y-offset from the baseline to the lowest stroke in the font (e.g. from letters like g or p).
58
+ * @param xheight The height of lowercase letters, usually measured at the "x" glyph.
59
+ * @param capheight The height of capital letters, usually measured at the "X" glyph.
60
+ * @param bpp The bits per pixel used for this font. Used to read data out of the glyph bitmaps.
56
61
  */
57
- Font(const GlyphData *data, int data_nr, int baseline, int height, uint8_t bpp = 1);
62
+ Font(const GlyphData *data, int data_nr, int baseline, int height, int descender, int xheight, int capheight,
63
+ uint8_t bpp = 1);
58
64
 
59
65
  int match_next_glyph(const uint8_t *str, int *match_length);
60
66
 
@@ -65,14 +71,23 @@ class Font
65
71
  #endif
66
72
  inline int get_baseline() { return this->baseline_; }
67
73
  inline int get_height() { return this->height_; }
74
+ inline int get_ascender() { return this->baseline_; }
75
+ inline int get_descender() { return this->descender_; }
76
+ inline int get_linegap() { return this->linegap_; }
77
+ inline int get_xheight() { return this->xheight_; }
78
+ inline int get_capheight() { return this->capheight_; }
68
79
  inline int get_bpp() { return this->bpp_; }
69
80
 
70
- const std::vector<Glyph, ExternalRAMAllocator<Glyph>> &get_glyphs() const { return glyphs_; }
81
+ const std::vector<Glyph, RAMAllocator<Glyph>> &get_glyphs() const { return glyphs_; }
71
82
 
72
83
  protected:
73
- std::vector<Glyph, ExternalRAMAllocator<Glyph>> glyphs_;
84
+ std::vector<Glyph, RAMAllocator<Glyph>> glyphs_;
74
85
  int baseline_;
75
86
  int height_;
87
+ int descender_;
88
+ int linegap_;
89
+ int xheight_;
90
+ int capheight_;
76
91
  uint8_t bpp_; // bits per pixel
77
92
  };
78
93
 
@@ -18,7 +18,6 @@ class FS3000Component : public PollingComponent, public i2c::I2CDevice, public s
18
18
  void update() override;
19
19
 
20
20
  void dump_config() override;
21
- float get_setup_priority() const override { return setup_priority::DATA; }
22
21
 
23
22
  void set_model(FS3000Model model) { this->model_ = model; }
24
23
 
@@ -12,7 +12,6 @@ class GCJA5Component : public Component, public uart::UARTDevice {
12
12
  public:
13
13
  void dump_config() override;
14
14
  void loop() override;
15
- float get_setup_priority() const override { return setup_priority::DATA; }
16
15
 
17
16
  void set_pm_1_0_sensor(sensor::Sensor *pm_1_0) { pm_1_0_sensor_ = pm_1_0; }
18
17
  void set_pm_2_5_sensor(sensor::Sensor *pm_2_5) { pm_2_5_sensor_ = pm_2_5; }
File without changes
@@ -0,0 +1,68 @@
1
+ #include "esphome/core/log.h"
2
+ #include "esphome/core/hal.h"
3
+ #include "gl_r01_i2c.h"
4
+
5
+ namespace esphome {
6
+ namespace gl_r01_i2c {
7
+
8
+ static const char *const TAG = "gl_r01_i2c";
9
+
10
+ // Register definitions from datasheet
11
+ static const uint8_t REG_VERSION = 0x00;
12
+ static const uint8_t REG_DISTANCE = 0x02;
13
+ static const uint8_t REG_TRIGGER = 0x10;
14
+ static const uint8_t CMD_TRIGGER = 0xB0;
15
+ static const uint8_t RESTART_CMD1 = 0x5A;
16
+ static const uint8_t RESTART_CMD2 = 0xA5;
17
+ static const uint8_t READ_DELAY = 40; // minimum milliseconds from datasheet to safely read measurement result
18
+
19
+ void GLR01I2CComponent::setup() {
20
+ ESP_LOGCONFIG(TAG, "Setting up GL-R01 I2C...");
21
+ // Verify sensor presence
22
+ if (!this->read_byte_16(REG_VERSION, &this->version_)) {
23
+ ESP_LOGE(TAG, "Failed to communicate with GL-R01 I2C sensor!");
24
+ this->mark_failed();
25
+ return;
26
+ }
27
+ ESP_LOGD(TAG, "Found GL-R01 I2C with version 0x%04X", this->version_);
28
+ }
29
+
30
+ void GLR01I2CComponent::dump_config() {
31
+ ESP_LOGCONFIG(TAG, "GL-R01 I2C:");
32
+ ESP_LOGCONFIG(TAG, " Firmware Version: 0x%04X", this->version_);
33
+ LOG_I2C_DEVICE(this);
34
+ LOG_SENSOR(" ", "Distance", this);
35
+ }
36
+
37
+ void GLR01I2CComponent::update() {
38
+ // Trigger a new measurement
39
+ if (!this->write_byte(REG_TRIGGER, CMD_TRIGGER)) {
40
+ ESP_LOGE(TAG, "Failed to trigger measurement!");
41
+ this->status_set_warning();
42
+ return;
43
+ }
44
+
45
+ // Schedule reading the result after the read delay
46
+ this->set_timeout(READ_DELAY, [this]() { this->read_distance_(); });
47
+ }
48
+
49
+ void GLR01I2CComponent::read_distance_() {
50
+ uint16_t distance = 0;
51
+ if (!this->read_byte_16(REG_DISTANCE, &distance)) {
52
+ ESP_LOGE(TAG, "Failed to read distance value!");
53
+ this->status_set_warning();
54
+ return;
55
+ }
56
+
57
+ if (distance == 0xFFFF) {
58
+ ESP_LOGW(TAG, "Invalid measurement received!");
59
+ this->status_set_warning();
60
+ } else {
61
+ ESP_LOGV(TAG, "Distance: %umm", distance);
62
+ this->publish_state(distance);
63
+ this->status_clear_warning();
64
+ }
65
+ }
66
+
67
+ } // namespace gl_r01_i2c
68
+ } // namespace esphome
@@ -0,0 +1,22 @@
1
+ #pragma once
2
+
3
+ #include "esphome/core/component.h"
4
+ #include "esphome/components/sensor/sensor.h"
5
+ #include "esphome/components/i2c/i2c.h"
6
+
7
+ namespace esphome {
8
+ namespace gl_r01_i2c {
9
+
10
+ class GLR01I2CComponent : public sensor::Sensor, public i2c::I2CDevice, public PollingComponent {
11
+ public:
12
+ void setup() override;
13
+ void dump_config() override;
14
+ void update() override;
15
+
16
+ protected:
17
+ void read_distance_();
18
+ uint16_t version_{0};
19
+ };
20
+
21
+ } // namespace gl_r01_i2c
22
+ } // namespace esphome
@@ -0,0 +1,36 @@
1
+ import esphome.codegen as cg
2
+ import esphome.config_validation as cv
3
+ from esphome.components import i2c, sensor
4
+ from esphome.const import (
5
+ CONF_ID,
6
+ DEVICE_CLASS_DISTANCE,
7
+ STATE_CLASS_MEASUREMENT,
8
+ UNIT_MILLIMETER,
9
+ )
10
+
11
+ CODEOWNERS = ["@pkejval"]
12
+ DEPENDENCIES = ["i2c"]
13
+
14
+ gl_r01_i2c_ns = cg.esphome_ns.namespace("gl_r01_i2c")
15
+ GLR01I2CComponent = gl_r01_i2c_ns.class_(
16
+ "GLR01I2CComponent", i2c.I2CDevice, cg.PollingComponent
17
+ )
18
+
19
+ CONFIG_SCHEMA = (
20
+ sensor.sensor_schema(
21
+ GLR01I2CComponent,
22
+ unit_of_measurement=UNIT_MILLIMETER,
23
+ accuracy_decimals=0,
24
+ device_class=DEVICE_CLASS_DISTANCE,
25
+ state_class=STATE_CLASS_MEASUREMENT,
26
+ )
27
+ .extend(cv.polling_component_schema("60s"))
28
+ .extend(i2c.i2c_device_schema(0x74))
29
+ )
30
+
31
+
32
+ async def to_code(config):
33
+ var = cg.new_Pvariable(config[CONF_ID])
34
+ await cg.register_component(var, config)
35
+ await sensor.register_sensor(var, config)
36
+ await i2c.register_i2c_device(var, config)
@@ -15,7 +15,6 @@ class GP8403 : public Component, public i2c::I2CDevice {
15
15
  public:
16
16
  void setup() override;
17
17
  void dump_config() override;
18
- float get_setup_priority() const override { return setup_priority::DATA; }
19
18
 
20
19
  void set_voltage(gp8403::GP8403Voltage voltage) { this->voltage_ = voltage; }
21
20
 
@@ -10,11 +10,24 @@ GPIOBinarySensor = gpio_ns.class_(
10
10
  "GPIOBinarySensor", binary_sensor.BinarySensor, cg.Component
11
11
  )
12
12
 
13
+ CONF_USE_INTERRUPT = "use_interrupt"
14
+ CONF_INTERRUPT_TYPE = "interrupt_type"
15
+
16
+ INTERRUPT_TYPES = {
17
+ "RISING": gpio_ns.INTERRUPT_RISING_EDGE,
18
+ "FALLING": gpio_ns.INTERRUPT_FALLING_EDGE,
19
+ "ANY": gpio_ns.INTERRUPT_ANY_EDGE,
20
+ }
21
+
13
22
  CONFIG_SCHEMA = (
14
23
  binary_sensor.binary_sensor_schema(GPIOBinarySensor)
15
24
  .extend(
16
25
  {
17
26
  cv.Required(CONF_PIN): pins.gpio_input_pin_schema,
27
+ cv.Optional(CONF_USE_INTERRUPT, default=True): cv.boolean,
28
+ cv.Optional(CONF_INTERRUPT_TYPE, default="ANY"): cv.enum(
29
+ INTERRUPT_TYPES, upper=True
30
+ ),
18
31
  }
19
32
  )
20
33
  .extend(cv.COMPONENT_SCHEMA)
@@ -27,3 +40,7 @@ async def to_code(config):
27
40
 
28
41
  pin = await cg.gpio_pin_expression(config[CONF_PIN])
29
42
  cg.add(var.set_pin(pin))
43
+
44
+ cg.add(var.set_use_interrupt(config[CONF_USE_INTERRUPT]))
45
+ if config[CONF_USE_INTERRUPT]:
46
+ cg.add(var.set_interrupt_type(config[CONF_INTERRUPT_TYPE]))
@@ -6,17 +6,91 @@ namespace gpio {
6
6
 
7
7
  static const char *const TAG = "gpio.binary_sensor";
8
8
 
9
+ void IRAM_ATTR GPIOBinarySensorStore::gpio_intr(GPIOBinarySensorStore *arg) {
10
+ bool new_state = arg->isr_pin_.digital_read();
11
+ if (new_state != arg->last_state_) {
12
+ arg->state_ = new_state;
13
+ arg->last_state_ = new_state;
14
+ arg->changed_ = true;
15
+ // Wake up the component from its disabled loop state
16
+ if (arg->component_ != nullptr) {
17
+ arg->component_->enable_loop_soon_any_context();
18
+ }
19
+ }
20
+ }
21
+
22
+ void GPIOBinarySensorStore::setup(InternalGPIOPin *pin, gpio::InterruptType type, Component *component) {
23
+ pin->setup();
24
+ this->isr_pin_ = pin->to_isr();
25
+ this->component_ = component;
26
+
27
+ // Read initial state
28
+ this->last_state_ = pin->digital_read();
29
+ this->state_ = this->last_state_;
30
+
31
+ // Attach interrupt - from this point on, any changes will be caught by the interrupt
32
+ pin->attach_interrupt(&GPIOBinarySensorStore::gpio_intr, this, type);
33
+ }
34
+
9
35
  void GPIOBinarySensor::setup() {
10
- this->pin_->setup();
11
- this->publish_initial_state(this->pin_->digital_read());
36
+ if (this->use_interrupt_ && !this->pin_->is_internal()) {
37
+ ESP_LOGD(TAG, "GPIO is not internal, falling back to polling mode");
38
+ this->use_interrupt_ = false;
39
+ }
40
+
41
+ if (this->use_interrupt_) {
42
+ auto *internal_pin = static_cast<InternalGPIOPin *>(this->pin_);
43
+ this->store_.setup(internal_pin, this->interrupt_type_, this);
44
+ this->publish_initial_state(this->store_.get_state());
45
+ } else {
46
+ this->pin_->setup();
47
+ this->publish_initial_state(this->pin_->digital_read());
48
+ }
12
49
  }
13
50
 
14
51
  void GPIOBinarySensor::dump_config() {
15
52
  LOG_BINARY_SENSOR("", "GPIO Binary Sensor", this);
16
53
  LOG_PIN(" Pin: ", this->pin_);
54
+ const char *mode = this->use_interrupt_ ? "interrupt" : "polling";
55
+ ESP_LOGCONFIG(TAG, " Mode: %s", mode);
56
+ if (this->use_interrupt_) {
57
+ const char *interrupt_type;
58
+ switch (this->interrupt_type_) {
59
+ case gpio::INTERRUPT_RISING_EDGE:
60
+ interrupt_type = "RISING_EDGE";
61
+ break;
62
+ case gpio::INTERRUPT_FALLING_EDGE:
63
+ interrupt_type = "FALLING_EDGE";
64
+ break;
65
+ case gpio::INTERRUPT_ANY_EDGE:
66
+ interrupt_type = "ANY_EDGE";
67
+ break;
68
+ default:
69
+ interrupt_type = "UNKNOWN";
70
+ break;
71
+ }
72
+ ESP_LOGCONFIG(TAG, " Interrupt Type: %s", interrupt_type);
73
+ }
17
74
  }
18
75
 
19
- void GPIOBinarySensor::loop() { this->publish_state(this->pin_->digital_read()); }
76
+ void GPIOBinarySensor::loop() {
77
+ if (this->use_interrupt_) {
78
+ if (this->store_.is_changed()) {
79
+ // Clear the flag immediately to minimize the window where we might miss changes
80
+ this->store_.clear_changed();
81
+ // Read the state and publish it
82
+ // Note: If the ISR fires between clear_changed() and get_state(), that's fine -
83
+ // we'll process the new change on the next loop iteration
84
+ bool state = this->store_.get_state();
85
+ this->publish_state(state);
86
+ } else {
87
+ // No changes, disable the loop until the next interrupt
88
+ this->disable_loop();
89
+ }
90
+ } else {
91
+ this->publish_state(this->pin_->digital_read());
92
+ }
93
+ }
20
94
 
21
95
  float GPIOBinarySensor::get_setup_priority() const { return setup_priority::HARDWARE; }
22
96
 
@@ -2,14 +2,51 @@
2
2
 
3
3
  #include "esphome/core/component.h"
4
4
  #include "esphome/core/hal.h"
5
+ #include "esphome/core/helpers.h"
5
6
  #include "esphome/components/binary_sensor/binary_sensor.h"
6
7
 
7
8
  namespace esphome {
8
9
  namespace gpio {
9
10
 
11
+ // Store class for ISR data (no vtables, ISR-safe)
12
+ class GPIOBinarySensorStore {
13
+ public:
14
+ void setup(InternalGPIOPin *pin, gpio::InterruptType type, Component *component);
15
+
16
+ static void gpio_intr(GPIOBinarySensorStore *arg);
17
+
18
+ bool get_state() const {
19
+ // No lock needed: state_ is atomically updated by ISR
20
+ // Volatile ensures we read the latest value
21
+ return this->state_;
22
+ }
23
+
24
+ bool is_changed() const {
25
+ // Simple read of volatile bool - no clearing here
26
+ return this->changed_;
27
+ }
28
+
29
+ void clear_changed() {
30
+ // Separate method to clear the flag
31
+ this->changed_ = false;
32
+ }
33
+
34
+ protected:
35
+ ISRInternalGPIOPin isr_pin_;
36
+ volatile bool state_{false};
37
+ volatile bool last_state_{false};
38
+ volatile bool changed_{false};
39
+ Component *component_{nullptr}; // Pointer to the component for enable_loop_soon_any_context()
40
+ };
41
+
10
42
  class GPIOBinarySensor : public binary_sensor::BinarySensor, public Component {
11
43
  public:
44
+ // No destructor needed: ESPHome components are created at boot and live forever.
45
+ // Interrupts are only detached on reboot when memory is cleared anyway.
46
+
12
47
  void set_pin(GPIOPin *pin) { pin_ = pin; }
48
+ void set_use_interrupt(bool use_interrupt) { use_interrupt_ = use_interrupt; }
49
+ void set_interrupt_type(gpio::InterruptType type) { interrupt_type_ = type; }
13
50
  // ========== INTERNAL METHODS ==========
14
51
  // (In most use cases you won't need these)
15
52
  /// Setup pin
@@ -22,6 +59,9 @@ class GPIOBinarySensor : public binary_sensor::BinarySensor, public Component {
22
59
 
23
60
  protected:
24
61
  GPIOPin *pin_;
62
+ bool use_interrupt_{true};
63
+ gpio::InterruptType interrupt_type_{gpio::INTERRUPT_ANY_EDGE};
64
+ GPIOBinarySensorStore store_;
25
65
  };
26
66
 
27
67
  } // namespace gpio
@@ -22,8 +22,6 @@ class GroveGasMultichannelV2Component : public PollingComponent, public i2c::I2C
22
22
 
23
23
  void dump_config() override;
24
24
 
25
- float get_setup_priority() const override { return setup_priority::DATA; }
26
-
27
25
  protected:
28
26
  enum ErrorCode {
29
27
  UNKNOWN,
@@ -13,7 +13,6 @@ class HE60rCover : public cover::Cover, public Component, public uart::UARTDevic
13
13
  void setup() override;
14
14
  void loop() override;
15
15
  void dump_config() override;
16
- float get_setup_priority() const override { return setup_priority::DATA; };
17
16
 
18
17
  void set_open_duration(uint32_t duration) { this->open_duration_ = duration; }
19
18
  void set_close_duration(uint32_t duration) { this->close_duration_ = duration; }
@@ -70,6 +70,7 @@ PROTOCOLS = {
70
70
  "airway": Protocol.PROTOCOL_AIRWAY,
71
71
  "bgh_aud": Protocol.PROTOCOL_BGH_AUD,
72
72
  "panasonic_altdke": Protocol.PROTOCOL_PANASONIC_ALTDKE,
73
+ "philco_phs32": Protocol.PROTOCOL_PHILCO_PHS32,
73
74
  "vaillantvai8": Protocol.PROTOCOL_VAILLANTVAI8,
74
75
  "r51m": Protocol.PROTOCOL_R51M,
75
76
  }
@@ -125,6 +126,6 @@ async def to_code(config):
125
126
  cg.add(var.set_max_temperature(config[CONF_MAX_TEMPERATURE]))
126
127
  cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE]))
127
128
 
128
- cg.add_library("tonia/HeatpumpIR", "1.0.32")
129
+ cg.add_library("tonia/HeatpumpIR", "1.0.35")
129
130
  if CORE.is_libretiny:
130
131
  CORE.add_platformio_option("lib_ignore", "IRremoteESP8266")
@@ -65,6 +65,7 @@ const std::map<Protocol, std::function<HeatpumpIR *()>> PROTOCOL_CONSTRUCTOR_MAP
65
65
  {PROTOCOL_AIRWAY, []() { return new AIRWAYHeatpumpIR(); }}, // NOLINT
66
66
  {PROTOCOL_BGH_AUD, []() { return new BGHHeatpumpIR(); }}, // NOLINT
67
67
  {PROTOCOL_PANASONIC_ALTDKE, []() { return new PanasonicAltDKEHeatpumpIR(); }}, // NOLINT
68
+ {PROTOCOL_PHILCO_PHS32, []() { return new PhilcoPHS32HeatpumpIR(); }}, // NOLINT
68
69
  {PROTOCOL_VAILLANTVAI8, []() { return new VaillantHeatpumpIR(); }}, // NOLINT
69
70
  {PROTOCOL_R51M, []() { return new R51MHeatpumpIR(); }}, // NOLINT
70
71
  };