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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (646) 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 +57 -21
  22. esphome/components/api/api_connection.cpp +344 -539
  23. esphome/components/api/api_connection.h +224 -141
  24. esphome/components/api/api_frame_helper.cpp +91 -127
  25. esphome/components/api/api_frame_helper.h +64 -54
  26. esphome/components/api/api_pb2.cpp +1837 -9044
  27. esphome/components/api/api_pb2.h +532 -685
  28. esphome/components/api/api_pb2_dump.cpp +4432 -0
  29. esphome/components/api/api_pb2_service.cpp +184 -425
  30. esphome/components/api/api_pb2_service.h +13 -6
  31. esphome/components/api/api_server.cpp +131 -167
  32. esphome/components/api/api_server.h +38 -10
  33. esphome/components/api/client.py +8 -2
  34. esphome/components/api/custom_api_device.h +8 -0
  35. esphome/components/api/list_entities.cpp +37 -104
  36. esphome/components/api/list_entities.h +33 -23
  37. esphome/components/api/proto.h +532 -26
  38. esphome/components/api/subscribe_state.cpp +23 -29
  39. esphome/components/api/subscribe_state.h +26 -19
  40. esphome/components/api/user_services.h +2 -0
  41. esphome/components/as3935_spi/as3935_spi.h +0 -2
  42. esphome/components/as5600/as5600.h +0 -1
  43. esphome/components/async_tcp/__init__.py +14 -5
  44. esphome/components/atc_mithermometer/atc_mithermometer.h +0 -1
  45. esphome/components/atm90e32/atm90e32.cpp +2 -1
  46. esphome/components/audio/audio_decoder.cpp +1 -1
  47. esphome/components/audio/audio_transfer_buffer.cpp +2 -2
  48. esphome/components/b_parasite/b_parasite.h +0 -1
  49. esphome/components/bedjet/bedjet_hub.cpp +5 -1
  50. esphome/components/bedjet/climate/bedjet_climate.cpp +5 -1
  51. esphome/components/beken_spi_led_strip/led_strip.cpp +4 -2
  52. esphome/components/bh1750/bh1750.cpp +5 -5
  53. esphome/components/binary_sensor/__init__.py +82 -5
  54. esphome/components/binary_sensor/automation.h +19 -1
  55. esphome/components/binary_sensor/binary_sensor.cpp +12 -30
  56. esphome/components/binary_sensor/binary_sensor.h +11 -25
  57. esphome/components/binary_sensor/filter.cpp +29 -24
  58. esphome/components/binary_sensor/filter.h +20 -10
  59. esphome/components/ble_client/output/ble_binary_output.h +0 -1
  60. esphome/components/ble_client/sensor/ble_rssi_sensor.cpp +5 -1
  61. esphome/components/ble_client/sensor/ble_rssi_sensor.h +0 -1
  62. esphome/components/ble_client/sensor/ble_sensor.cpp +5 -1
  63. esphome/components/ble_client/sensor/ble_sensor.h +0 -1
  64. esphome/components/ble_client/switch/ble_switch.h +0 -1
  65. esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +5 -1
  66. esphome/components/ble_client/text_sensor/ble_text_sensor.h +0 -1
  67. esphome/components/ble_presence/ble_presence_device.h +0 -1
  68. esphome/components/ble_rssi/ble_rssi_sensor.h +0 -1
  69. esphome/components/ble_scanner/ble_scanner.h +0 -1
  70. esphome/components/bluetooth_proxy/bluetooth_connection.h +9 -2
  71. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +16 -6
  72. esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -2
  73. esphome/components/bme680/sensor.py +1 -1
  74. esphome/components/bmp581/bmp581.h +0 -2
  75. esphome/components/button/__init__.py +5 -2
  76. esphome/components/camera/__init__.py +1 -0
  77. esphome/components/camera/camera.cpp +22 -0
  78. esphome/components/camera/camera.h +80 -0
  79. esphome/components/canbus/__init__.py +1 -0
  80. esphome/components/cap1188/cap1188.h +0 -1
  81. esphome/components/captive_portal/__init__.py +12 -2
  82. esphome/components/captive_portal/captive_portal.cpp +12 -2
  83. esphome/components/captive_portal/captive_portal.h +5 -2
  84. esphome/components/ccs811/ccs811.h +0 -2
  85. esphome/components/climate/__init__.py +5 -2
  86. esphome/components/cm1106/sensor.py +2 -2
  87. esphome/components/const/__init__.py +2 -0
  88. esphome/components/copy/binary_sensor/copy_binary_sensor.h +0 -1
  89. esphome/components/copy/button/copy_button.h +0 -1
  90. esphome/components/copy/cover/copy_cover.h +0 -1
  91. esphome/components/copy/fan/copy_fan.h +0 -1
  92. esphome/components/copy/lock/copy_lock.h +0 -1
  93. esphome/components/copy/number/copy_number.h +0 -1
  94. esphome/components/copy/select/copy_select.h +0 -1
  95. esphome/components/copy/sensor/copy_sensor.h +0 -1
  96. esphome/components/copy/switch/copy_switch.h +0 -1
  97. esphome/components/copy/text/copy_text.h +0 -1
  98. esphome/components/copy/text_sensor/copy_text_sensor.h +0 -1
  99. esphome/components/cover/__init__.py +5 -2
  100. esphome/components/cs5460a/cs5460a.h +0 -1
  101. esphome/components/datetime/__init__.py +4 -2
  102. esphome/components/debug/__init__.py +20 -0
  103. esphome/components/debug/debug_esp32.cpp +2 -0
  104. esphome/components/deep_sleep/__init__.py +43 -9
  105. esphome/components/demo/__init__.py +2 -2
  106. esphome/components/display/display.cpp +4 -3
  107. esphome/components/display/display.h +0 -2
  108. esphome/components/display/display_buffer.cpp +1 -1
  109. esphome/components/ds2484/__init__.py +1 -0
  110. esphome/components/ds2484/ds2484.cpp +209 -0
  111. esphome/components/ds2484/ds2484.h +43 -0
  112. esphome/components/ds2484/one_wire.py +37 -0
  113. esphome/components/duty_time/duty_time_sensor.h +0 -1
  114. esphome/components/ens160_base/ens160_base.h +0 -1
  115. esphome/components/es7210/es7210.h +0 -1
  116. esphome/components/es7243e/es7243e.h +0 -1
  117. esphome/components/es8156/es8156.h +0 -1
  118. esphome/components/es8311/es8311.h +0 -1
  119. esphome/components/es8388/es8388.h +0 -1
  120. esphome/components/esp32/__init__.py +103 -135
  121. esphome/components/esp32/core.cpp +0 -4
  122. esphome/components/esp32/gpio.h +1 -1
  123. esphome/components/esp32/helpers.cpp +69 -0
  124. esphome/components/esp32_ble/ble.cpp +5 -6
  125. esphome/components/esp32_ble/ble.h +29 -14
  126. esphome/components/esp32_ble/ble_event.h +6 -6
  127. esphome/components/esp32_ble_client/ble_client_base.cpp +21 -6
  128. esphome/components/esp32_ble_client/ble_client_base.h +24 -9
  129. esphome/components/esp32_ble_tracker/__init__.py +2 -8
  130. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +5 -5
  131. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +11 -7
  132. esphome/components/esp32_camera/__init__.py +112 -98
  133. esphome/components/esp32_camera/esp32_camera.cpp +41 -31
  134. esphome/components/esp32_camera/esp32_camera.h +35 -30
  135. esphome/components/esp32_camera_web_server/__init__.py +2 -1
  136. esphome/components/esp32_camera_web_server/camera_web_server.cpp +8 -8
  137. esphome/components/esp32_camera_web_server/camera_web_server.h +3 -3
  138. esphome/components/esp32_hall/sensor.py +2 -21
  139. esphome/components/esp32_hosted/__init__.py +101 -0
  140. esphome/components/esp32_hosted/esp32_hosted.py.script +12 -0
  141. esphome/components/esp32_improv/esp32_improv_component.cpp +3 -0
  142. esphome/components/esp32_rmt/__init__.py +0 -58
  143. esphome/components/esp32_rmt_led_strip/led_strip.cpp +77 -63
  144. esphome/components/esp32_rmt_led_strip/led_strip.h +11 -17
  145. esphome/components/esp32_rmt_led_strip/light.py +14 -76
  146. esphome/components/esp32_touch/esp32_touch.h +174 -28
  147. esphome/components/esp32_touch/esp32_touch_common.cpp +162 -0
  148. esphome/components/esp32_touch/esp32_touch_v1.cpp +240 -0
  149. esphome/components/esp32_touch/esp32_touch_v2.cpp +397 -0
  150. esphome/components/esp8266/__init__.py +2 -0
  151. esphome/components/esp8266/gpio.cpp +10 -10
  152. esphome/components/esp8266/helpers.cpp +31 -0
  153. esphome/components/esp_ldo/__init__.py +10 -8
  154. esphome/components/esp_ldo/esp_ldo.h +3 -0
  155. esphome/components/esphome/ota/__init__.py +1 -0
  156. esphome/components/esphome/ota/ota_esphome.cpp +24 -19
  157. esphome/components/ethernet/__init__.py +42 -23
  158. esphome/components/ethernet/esp_eth_phy_jl1101.c +0 -16
  159. esphome/components/ethernet/ethernet_component.cpp +69 -29
  160. esphome/components/ethernet/ethernet_component.h +18 -10
  161. esphome/components/event/__init__.py +5 -2
  162. esphome/components/ezo/ezo.h +0 -1
  163. esphome/components/ezo_pmp/ezo_pmp.h +0 -1
  164. esphome/components/fan/__init__.py +5 -2
  165. esphome/components/fan/fan.cpp +4 -0
  166. esphome/components/feedback/feedback_cover.h +0 -1
  167. esphome/components/font/__init__.py +92 -82
  168. esphome/components/font/font.cpp +9 -2
  169. esphome/components/font/font.h +20 -5
  170. esphome/components/fs3000/fs3000.h +0 -1
  171. esphome/components/gcja5/gcja5.h +0 -1
  172. esphome/components/gl_r01_i2c/__init__.py +0 -0
  173. esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +68 -0
  174. esphome/components/gl_r01_i2c/gl_r01_i2c.h +22 -0
  175. esphome/components/gl_r01_i2c/sensor.py +36 -0
  176. esphome/components/gp8403/gp8403.h +0 -1
  177. esphome/components/gpio/binary_sensor/__init__.py +39 -1
  178. esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +77 -3
  179. esphome/components/gpio/binary_sensor/gpio_binary_sensor.h +40 -0
  180. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +0 -2
  181. esphome/components/he60r/he60r.h +0 -1
  182. esphome/components/heatpumpir/climate.py +2 -1
  183. esphome/components/heatpumpir/heatpumpir.cpp +1 -0
  184. esphome/components/heatpumpir/heatpumpir.h +1 -0
  185. esphome/components/honeywellabp2_i2c/honeywellabp2.h +0 -1
  186. esphome/components/host/__init__.py +3 -1
  187. esphome/components/host/helpers.cpp +57 -0
  188. esphome/components/http_request/__init__.py +19 -1
  189. esphome/components/http_request/http_request.h +1 -1
  190. esphome/components/http_request/http_request_arduino.h +1 -0
  191. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  192. esphome/components/http_request/update/http_request_update.cpp +35 -16
  193. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +3 -9
  194. esphome/components/hydreon_rgxx/sensor.py +1 -1
  195. esphome/components/i2c/__init__.py +23 -11
  196. esphome/components/i2c/i2c_bus.h +8 -1
  197. esphome/components/i2c/i2c_bus_arduino.cpp +4 -3
  198. esphome/components/i2c/i2c_bus_arduino.h +6 -3
  199. esphome/components/i2c/i2c_bus_esp_idf.h +5 -3
  200. esphome/components/i2c_device/i2c_device.h +0 -1
  201. esphome/components/i2s_audio/__init__.py +2 -10
  202. esphome/components/i2s_audio/i2s_audio.cpp +1 -5
  203. esphome/components/i2s_audio/media_player/__init__.py +2 -2
  204. esphome/components/i2s_audio/speaker/__init__.py +1 -1
  205. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +2 -2
  206. esphome/components/iaqcore/iaqcore.h +0 -2
  207. esphome/components/image/__init__.py +123 -24
  208. esphome/components/improv_serial/improv_serial_component.cpp +0 -4
  209. esphome/components/ina219/ina219.cpp +7 -0
  210. esphome/components/ina219/ina219.h +1 -0
  211. esphome/components/ina260/ina260.h +0 -2
  212. esphome/components/inkbird_ibsth1_mini/inkbird_ibsth1_mini.h +0 -1
  213. esphome/components/inkplate6/display.py +15 -0
  214. esphome/components/inkplate6/inkplate.cpp +2 -2
  215. esphome/components/integration/integration_sensor.h +0 -1
  216. esphome/components/internal_temperature/internal_temperature.cpp +8 -27
  217. esphome/components/internal_temperature/sensor.py +0 -26
  218. esphome/components/interval/interval.h +0 -2
  219. esphome/components/json/__init__.py +1 -1
  220. esphome/components/json/json_util.cpp +56 -63
  221. esphome/components/ld2410/button/__init__.py +3 -3
  222. esphome/components/ld2410/button/factory_reset_button.cpp +9 -0
  223. esphome/components/ld2410/button/{reset_button.h → factory_reset_button.h} +2 -2
  224. esphome/components/ld2410/ld2410.cpp +421 -268
  225. esphome/components/ld2410/ld2410.h +44 -146
  226. esphome/components/ld2410/number/__init__.py +2 -2
  227. esphome/components/ld2410/sensor.py +1 -1
  228. esphome/components/ld2410/switch/__init__.py +1 -1
  229. esphome/components/ld2420/binary_sensor/ld2420_binary_sensor.cpp +2 -2
  230. esphome/components/ld2420/button/reconfig_buttons.cpp +1 -1
  231. esphome/components/ld2420/ld2420.cpp +252 -147
  232. esphome/components/ld2420/ld2420.h +52 -126
  233. esphome/components/ld2420/number/__init__.py +2 -2
  234. esphome/components/ld2420/number/gate_config_number.cpp +1 -1
  235. esphome/components/ld2420/select/operating_mode_select.cpp +1 -1
  236. esphome/components/ld2420/sensor/__init__.py +6 -2
  237. esphome/components/ld2420/sensor/ld2420_sensor.cpp +2 -2
  238. esphome/components/ld2420/sensor/ld2420_sensor.h +1 -1
  239. esphome/components/ld2420/text_sensor/text_sensor.cpp +2 -2
  240. esphome/components/ld2450/button/__init__.py +3 -3
  241. esphome/components/ld2450/button/factory_reset_button.cpp +9 -0
  242. esphome/components/ld2450/button/{reset_button.h → factory_reset_button.h} +2 -2
  243. esphome/components/ld2450/ld2450.cpp +384 -232
  244. esphome/components/ld2450/ld2450.h +60 -69
  245. esphome/components/ld2450/switch/__init__.py +1 -1
  246. esphome/components/ledc/ledc_output.cpp +1 -63
  247. esphome/components/libretiny/__init__.py +5 -3
  248. esphome/components/libretiny/const.py +5 -0
  249. esphome/components/libretiny/generate_components.py +1 -0
  250. esphome/components/libretiny/helpers.cpp +35 -0
  251. esphome/components/libretiny/lt_component.cpp +5 -3
  252. esphome/components/light/__init__.py +4 -2
  253. esphome/components/light/addressable_light.h +3 -3
  254. esphome/components/light/light_call.cpp +180 -243
  255. esphome/components/light/light_call.h +72 -20
  256. esphome/components/light/light_color_values.h +14 -14
  257. esphome/components/light/light_json_schema.cpp +17 -16
  258. esphome/components/light/light_state.h +15 -13
  259. esphome/components/light/transformers.h +2 -2
  260. esphome/components/ln882x/__init__.py +52 -0
  261. esphome/components/ln882x/boards.py +285 -0
  262. esphome/components/lock/__init__.py +5 -2
  263. esphome/components/logger/__init__.py +40 -3
  264. esphome/components/logger/logger.cpp +47 -12
  265. esphome/components/logger/logger.h +80 -49
  266. esphome/components/logger/logger_esp32.cpp +3 -3
  267. esphome/components/lps22/__init__.py +0 -0
  268. esphome/components/lps22/lps22.cpp +75 -0
  269. esphome/components/lps22/lps22.h +27 -0
  270. esphome/components/lps22/sensor.py +58 -0
  271. esphome/components/ltr390/ltr390.h +0 -1
  272. esphome/components/ltr501/ltr501.h +0 -1
  273. esphome/components/ltr_als_ps/ltr_als_ps.h +0 -1
  274. esphome/components/lvgl/__init__.py +1 -1
  275. esphome/components/lvgl/schemas.py +66 -6
  276. esphome/components/lvgl/styles.py +24 -16
  277. esphome/components/lvgl/widgets/__init__.py +12 -2
  278. esphome/components/lvgl/widgets/lv_bar.py +40 -19
  279. esphome/components/lvgl/widgets/meter.py +20 -13
  280. esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +1 -1
  281. esphome/components/max9611/max9611.h +0 -1
  282. esphome/components/mcp23016/__init__.py +1 -1
  283. esphome/components/mcp23xxx_base/__init__.py +1 -1
  284. esphome/components/mcp4461/__init__.py +1 -1
  285. esphome/components/mcp4461/output/__init__.py +3 -2
  286. esphome/components/mcp9600/mcp9600.h +0 -2
  287. esphome/components/md5/md5.cpp +3 -3
  288. esphome/components/md5/md5.h +1 -6
  289. esphome/components/mdns/__init__.py +22 -11
  290. esphome/components/media_player/__init__.py +4 -3
  291. esphome/components/micro_wake_word/__init__.py +1 -5
  292. esphome/components/micro_wake_word/streaming_model.cpp +2 -2
  293. esphome/components/microphone/microphone.cpp +7 -9
  294. esphome/components/microphone/microphone.h +0 -2
  295. esphome/components/mipi_spi/display.py +1 -0
  296. esphome/components/mmc5603/mmc5603.cpp +1 -1
  297. esphome/components/modbus/modbus.cpp +33 -15
  298. esphome/components/modbus/modbus.h +9 -0
  299. esphome/components/modbus_controller/__init__.py +42 -10
  300. esphome/components/modbus_controller/modbus_controller.cpp +92 -11
  301. esphome/components/modbus_controller/modbus_controller.h +61 -7
  302. esphome/components/mopeka_pro_check/mopeka_pro_check.h +0 -1
  303. esphome/components/mopeka_std_check/mopeka_std_check.h +0 -1
  304. esphome/components/mpl3115a2/mpl3115a2.h +0 -2
  305. esphome/components/mqtt/__init__.py +16 -0
  306. esphome/components/mqtt/mqtt_alarm_control_panel.cpp +2 -1
  307. esphome/components/mqtt/mqtt_backend.h +2 -1
  308. esphome/components/mqtt/mqtt_backend_esp32.cpp +132 -47
  309. esphome/components/mqtt/mqtt_backend_esp32.h +106 -4
  310. esphome/components/mqtt/mqtt_binary_sensor.cpp +1 -0
  311. esphome/components/mqtt/mqtt_button.cpp +4 -1
  312. esphome/components/mqtt/mqtt_client.cpp +17 -9
  313. esphome/components/mqtt/mqtt_client.h +8 -3
  314. esphome/components/mqtt/mqtt_climate.cpp +6 -4
  315. esphome/components/mqtt/mqtt_component.cpp +3 -1
  316. esphome/components/mqtt/mqtt_cover.cpp +1 -0
  317. esphome/components/mqtt/mqtt_date.cpp +4 -3
  318. esphome/components/mqtt/mqtt_datetime.cpp +7 -6
  319. esphome/components/mqtt/mqtt_event.cpp +6 -3
  320. esphome/components/mqtt/mqtt_fan.cpp +1 -0
  321. esphome/components/mqtt/mqtt_light.cpp +8 -4
  322. esphome/components/mqtt/mqtt_lock.cpp +3 -1
  323. esphome/components/mqtt/mqtt_number.cpp +1 -0
  324. esphome/components/mqtt/mqtt_select.cpp +2 -1
  325. esphome/components/mqtt/mqtt_sensor.cpp +3 -1
  326. esphome/components/mqtt/mqtt_switch.cpp +3 -1
  327. esphome/components/mqtt/mqtt_text.cpp +1 -0
  328. esphome/components/mqtt/mqtt_text_sensor.cpp +3 -1
  329. esphome/components/mqtt/mqtt_time.cpp +4 -3
  330. esphome/components/mqtt/mqtt_update.cpp +1 -0
  331. esphome/components/mqtt/mqtt_valve.cpp +3 -1
  332. esphome/components/ms8607/ms8607.cpp +1 -1
  333. esphome/components/ms8607/ms8607.h +0 -1
  334. esphome/components/neopixelbus/light.py +4 -1
  335. esphome/components/neopixelbus/neopixelbus_light.h +1 -1
  336. esphome/components/network/__init__.py +4 -1
  337. esphome/components/network/ip_address.h +1 -0
  338. esphome/components/nextion/__init__.py +16 -0
  339. esphome/components/nextion/base_component.py +1 -0
  340. esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +1 -1
  341. esphome/components/nextion/display.py +14 -4
  342. esphome/components/nextion/nextion.cpp +166 -101
  343. esphome/components/nextion/nextion.h +84 -53
  344. esphome/components/nextion/nextion_commands.cpp +11 -10
  345. esphome/components/nextion/nextion_component.cpp +28 -28
  346. esphome/components/nextion/nextion_component.h +53 -18
  347. esphome/components/nextion/nextion_component_base.h +3 -0
  348. esphome/components/nextion/nextion_upload.cpp +36 -0
  349. esphome/components/nextion/nextion_upload_arduino.cpp +10 -35
  350. esphome/components/nextion/nextion_upload_idf.cpp +9 -33
  351. esphome/components/nextion/sensor/nextion_sensor.cpp +1 -1
  352. esphome/components/nextion/switch/nextion_switch.cpp +1 -1
  353. esphome/components/nextion/text_sensor/nextion_textsensor.cpp +1 -1
  354. esphome/components/nfc/nfc.cpp +3 -22
  355. esphome/components/nfc/nfc.h +3 -3
  356. esphome/components/number/__init__.py +5 -2
  357. esphome/components/online_image/__init__.py +9 -1
  358. esphome/components/online_image/online_image.cpp +17 -7
  359. esphome/components/online_image/online_image.h +10 -2
  360. esphome/components/opentherm/opentherm.cpp +7 -12
  361. esphome/components/opentherm/output/output.cpp +1 -1
  362. esphome/components/openthread/__init__.py +47 -40
  363. esphome/components/openthread/const.py +1 -0
  364. esphome/components/openthread/openthread_esp.cpp +27 -5
  365. esphome/components/opt3001/__init__.py +0 -0
  366. esphome/components/opt3001/opt3001.cpp +122 -0
  367. esphome/components/opt3001/opt3001.h +27 -0
  368. esphome/components/opt3001/sensor.py +35 -0
  369. esphome/components/ota/__init__.py +17 -0
  370. esphome/components/ota/ota_backend.h +27 -1
  371. esphome/components/ota/ota_backend_arduino_esp32.cpp +12 -2
  372. esphome/components/ota/ota_backend_arduino_esp32.h +3 -0
  373. esphome/components/ota/ota_backend_arduino_esp8266.cpp +18 -4
  374. esphome/components/ota/ota_backend_arduino_esp8266.h +3 -0
  375. esphome/components/ota/ota_backend_arduino_libretiny.cpp +12 -2
  376. esphome/components/ota/ota_backend_arduino_libretiny.h +3 -0
  377. esphome/components/ota/ota_backend_arduino_rp2040.cpp +9 -2
  378. esphome/components/ota/ota_backend_arduino_rp2040.h +3 -0
  379. esphome/components/ota/ota_backend_esp_idf.cpp +10 -16
  380. esphome/components/ota/ota_backend_esp_idf.h +1 -0
  381. esphome/components/packages/__init__.py +5 -2
  382. esphome/components/packet_transport/binary_sensor.py +61 -4
  383. esphome/components/packet_transport/packet_transport.cpp +34 -1
  384. esphome/components/packet_transport/packet_transport.h +11 -5
  385. esphome/components/pcf8574/__init__.py +1 -1
  386. esphome/components/pi4ioe5v6408/__init__.py +84 -0
  387. esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +171 -0
  388. esphome/components/pi4ioe5v6408/pi4ioe5v6408.h +70 -0
  389. esphome/components/pmsa003i/pmsa003i.h +0 -1
  390. esphome/components/pmsx003/pmsx003.h +0 -1
  391. esphome/components/pn7150/pn7150.cpp +7 -7
  392. esphome/components/pn7150/pn7150.h +0 -1
  393. esphome/components/pn7160/pn7160.cpp +7 -7
  394. esphome/components/pn7160/pn7160.h +0 -1
  395. esphome/components/preferences/syncer.h +2 -0
  396. esphome/components/prometheus/prometheus_handler.h +1 -1
  397. esphome/components/psram/psram.cpp +0 -20
  398. esphome/components/pulse_counter/pulse_counter_sensor.h +0 -1
  399. esphome/components/pulse_meter/pulse_meter_sensor.cpp +8 -4
  400. esphome/components/pulse_width/pulse_width.h +0 -1
  401. esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +0 -4
  402. esphome/components/pvvx_mithermometer/display/pvvx_display.h +0 -2
  403. esphome/components/pvvx_mithermometer/pvvx_mithermometer.h +0 -1
  404. esphome/components/qr_code/__init__.py +13 -10
  405. esphome/components/qwiic_pir/qwiic_pir.h +0 -1
  406. esphome/components/radon_eye_ble/radon_eye_listener.cpp +1 -1
  407. esphome/components/rc522/rc522.h +0 -1
  408. esphome/components/rdm6300/rdm6300.h +0 -2
  409. esphome/components/remote_base/__init__.py +7 -5
  410. esphome/components/remote_base/remote_base.cpp +24 -21
  411. esphome/components/remote_base/remote_base.h +3 -26
  412. esphome/components/remote_receiver/__init__.py +40 -46
  413. esphome/components/remote_receiver/remote_receiver.h +4 -18
  414. esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -87
  415. esphome/components/remote_receiver/remote_receiver_esp8266.cpp +1 -1
  416. esphome/components/remote_transmitter/__init__.py +42 -43
  417. esphome/components/remote_transmitter/remote_transmitter.h +2 -14
  418. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -77
  419. esphome/components/resistance/resistance_sensor.h +0 -1
  420. esphome/components/rp2040/__init__.py +2 -0
  421. esphome/components/rp2040/helpers.cpp +55 -0
  422. esphome/components/rp2040_pio_led_strip/led_strip.cpp +2 -2
  423. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -4
  424. esphome/components/rtttl/__init__.py +4 -4
  425. esphome/components/rtttl/rtttl.cpp +10 -1
  426. esphome/components/ruuvitag/ruuvitag.h +0 -1
  427. esphome/components/safe_mode/safe_mode.cpp +2 -0
  428. esphome/components/safe_mode/safe_mode.h +4 -1
  429. esphome/components/scd30/scd30.h +0 -1
  430. esphome/components/scd30/sensor.py +2 -2
  431. esphome/components/scd4x/scd4x.cpp +61 -54
  432. esphome/components/scd4x/scd4x.h +17 -15
  433. esphome/components/scd4x/sensor.py +4 -4
  434. esphome/components/script/script.h +0 -2
  435. esphome/components/sdp3x/sensor.py +1 -1
  436. esphome/components/select/__init__.py +5 -2
  437. esphome/components/sen5x/sen5x.h +0 -1
  438. esphome/components/senseair/senseair.h +0 -1
  439. esphome/components/sensor/__init__.py +4 -2
  440. esphome/components/sensor/filter.cpp +1 -1
  441. esphome/components/sensor/sensor.cpp +12 -6
  442. esphome/components/sensor/sensor.h +13 -5
  443. esphome/components/servo/servo.cpp +2 -2
  444. esphome/components/servo/servo.h +0 -1
  445. esphome/components/sfa30/sfa30.h +0 -1
  446. esphome/components/sgp30/sgp30.h +0 -1
  447. esphome/components/sgp4x/sgp4x.h +0 -1
  448. esphome/components/shelly_dimmer/stm32flash.cpp +1 -2
  449. esphome/components/sht4x/sht4x.h +0 -1
  450. esphome/components/sm300d2/sm300d2.h +0 -2
  451. esphome/components/smt100/sensor.py +8 -4
  452. esphome/components/smt100/smt100.cpp +5 -5
  453. esphome/components/smt100/smt100.h +3 -3
  454. esphome/components/sn74hc595/__init__.py +1 -1
  455. esphome/components/sn74hc595/sn74hc595.cpp +5 -4
  456. esphome/components/sntp/sntp_component.cpp +9 -3
  457. esphome/components/sntp/time.py +2 -0
  458. esphome/components/socket/__init__.py +17 -0
  459. esphome/components/spi/__init__.py +27 -6
  460. esphome/components/spi/spi.cpp +3 -2
  461. esphome/components/spi/spi.h +9 -3
  462. esphome/components/spi/spi_arduino.cpp +3 -5
  463. esphome/components/spi/spi_esp_idf.cpp +40 -21
  464. esphome/components/spi_led_strip/spi_led_strip.cpp +1 -1
  465. esphome/components/sps30/sps30.h +0 -1
  466. esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
  467. esphome/components/st7701s/st7701s.cpp +0 -4
  468. esphome/components/status/status_binary_sensor.h +0 -2
  469. esphome/components/substitutions/__init__.py +81 -21
  470. esphome/components/substitutions/jinja.py +99 -0
  471. esphome/components/sun/sun.cpp +3 -4
  472. esphome/components/switch/__init__.py +5 -2
  473. esphome/components/switch/binary_sensor/switch_binary_sensor.h +0 -1
  474. esphome/components/sx126x/__init__.py +317 -0
  475. esphome/components/sx126x/automation.h +62 -0
  476. esphome/components/sx126x/packet_transport/__init__.py +26 -0
  477. esphome/components/sx126x/packet_transport/sx126x_transport.cpp +26 -0
  478. esphome/components/sx126x/packet_transport/sx126x_transport.h +25 -0
  479. esphome/components/sx126x/sx126x.cpp +523 -0
  480. esphome/components/sx126x/sx126x.h +140 -0
  481. esphome/components/sx126x/sx126x_reg.h +163 -0
  482. esphome/components/sx127x/__init__.py +325 -0
  483. esphome/components/sx127x/automation.h +62 -0
  484. esphome/components/sx127x/packet_transport/__init__.py +26 -0
  485. esphome/components/sx127x/packet_transport/sx127x_transport.cpp +26 -0
  486. esphome/components/sx127x/packet_transport/sx127x_transport.h +25 -0
  487. esphome/components/sx127x/sx127x.cpp +498 -0
  488. esphome/components/sx127x/sx127x.h +128 -0
  489. esphome/components/sx127x/sx127x_reg.h +295 -0
  490. esphome/components/syslog/esphome_syslog.cpp +5 -3
  491. esphome/components/syslog/esphome_syslog.h +1 -1
  492. esphome/components/tca9555/__init__.py +1 -1
  493. esphome/components/template/binary_sensor/template_binary_sensor.cpp +1 -9
  494. esphome/components/text/__init__.py +5 -2
  495. esphome/components/text_sensor/__init__.py +5 -2
  496. esphome/components/thermostat/thermostat_climate.cpp +34 -31
  497. esphome/components/thermostat/thermostat_climate.h +43 -39
  498. esphome/components/time/__init__.py +16 -2
  499. esphome/components/time/real_time_clock.cpp +4 -0
  500. esphome/components/time/real_time_clock.h +5 -1
  501. esphome/components/tlc5971/tlc5971.cpp +4 -1
  502. esphome/components/tmp1075/tmp1075.h +0 -2
  503. esphome/components/tof10120/tof10120_sensor.h +0 -1
  504. esphome/components/tormatic/tormatic_cover.h +0 -1
  505. esphome/components/total_daily_energy/total_daily_energy.h +0 -1
  506. esphome/components/tsl2591/tsl2591.cpp +1 -1
  507. esphome/components/ttp229_bsf/ttp229_bsf.h +0 -1
  508. esphome/components/ttp229_lsf/ttp229_lsf.h +0 -1
  509. esphome/components/tx20/tx20.cpp +2 -2
  510. esphome/components/uart/__init__.py +18 -0
  511. esphome/components/uart/uart_component_esp_idf.cpp +0 -4
  512. esphome/components/update/__init__.py +5 -2
  513. esphome/components/update/update_entity.h +8 -0
  514. esphome/components/usb_host/__init__.py +5 -2
  515. esphome/components/usb_host/usb_host_client.cpp +10 -10
  516. esphome/components/usb_uart/cp210x.cpp +1 -1
  517. esphome/components/usb_uart/usb_uart.cpp +41 -44
  518. esphome/components/usb_uart/usb_uart.h +4 -3
  519. esphome/components/valve/__init__.py +5 -2
  520. esphome/components/vbus/vbus.h +0 -1
  521. esphome/components/veml3235/veml3235.h +0 -1
  522. esphome/components/veml7700/veml7700.h +0 -1
  523. esphome/components/vl53l0x/vl53l0x_sensor.h +0 -1
  524. esphome/components/voice_assistant/voice_assistant.cpp +4 -4
  525. esphome/components/watchdog/watchdog.cpp +0 -4
  526. esphome/components/waveshare_epaper/waveshare_epaper.cpp +6 -6
  527. esphome/components/web_server/__init__.py +34 -19
  528. esphome/components/web_server/ota/__init__.py +32 -0
  529. esphome/components/web_server/ota/ota_web_server.cpp +210 -0
  530. esphome/components/web_server/ota/ota_web_server.h +26 -0
  531. esphome/components/web_server/web_server.cpp +318 -436
  532. esphome/components/web_server/web_server.h +33 -23
  533. esphome/components/web_server/web_server_v1.cpp +4 -5
  534. esphome/components/web_server_base/__init__.py +5 -2
  535. esphome/components/web_server_base/web_server_base.cpp +2 -94
  536. esphome/components/web_server_base/web_server_base.h +5 -25
  537. esphome/components/web_server_idf/multipart.cpp +254 -0
  538. esphome/components/web_server_idf/multipart.h +86 -0
  539. esphome/components/web_server_idf/utils.cpp +32 -0
  540. esphome/components/web_server_idf/utils.h +10 -0
  541. esphome/components/web_server_idf/web_server_idf.cpp +164 -16
  542. esphome/components/web_server_idf/web_server_idf.h +11 -10
  543. esphome/components/wiegand/wiegand.cpp +2 -2
  544. esphome/components/wifi/__init__.py +18 -0
  545. esphome/components/wifi/wifi_component.cpp +17 -22
  546. esphome/components/wifi/wifi_component.h +27 -23
  547. esphome/components/wifi/wifi_component_esp32_arduino.cpp +52 -59
  548. esphome/components/wifi/wifi_component_esp8266.cpp +46 -46
  549. esphome/components/wifi/wifi_component_esp_idf.cpp +35 -36
  550. esphome/components/wifi/wifi_component_libretiny.cpp +26 -27
  551. esphome/components/wifi/wifi_component_pico_w.cpp +3 -3
  552. esphome/components/wifi_info/wifi_info_text_sensor.cpp +6 -6
  553. esphome/components/wireguard/__init__.py +2 -11
  554. esphome/components/xiaomi_ble/xiaomi_ble.cpp +13 -1
  555. esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
  556. esphome/components/xiaomi_cgd1/xiaomi_cgd1.h +0 -1
  557. esphome/components/xiaomi_cgdk2/xiaomi_cgdk2.h +0 -1
  558. esphome/components/xiaomi_cgg1/xiaomi_cgg1.h +0 -1
  559. esphome/components/xiaomi_cgpr1/xiaomi_cgpr1.h +0 -1
  560. esphome/components/xiaomi_gcls002/xiaomi_gcls002.h +0 -1
  561. esphome/components/xiaomi_hhccjcy01/xiaomi_hhccjcy01.h +0 -1
  562. esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h +0 -1
  563. esphome/components/xiaomi_hhccpot002/xiaomi_hhccpot002.h +0 -1
  564. esphome/components/xiaomi_jqjcy01ym/xiaomi_jqjcy01ym.h +0 -1
  565. esphome/components/xiaomi_lywsd02/xiaomi_lywsd02.h +0 -1
  566. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +0 -1
  567. esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.h +0 -1
  568. esphome/components/xiaomi_lywsdcgq/xiaomi_lywsdcgq.h +0 -1
  569. esphome/components/xiaomi_mhoc303/xiaomi_mhoc303.h +0 -1
  570. esphome/components/xiaomi_mhoc401/xiaomi_mhoc401.h +0 -1
  571. esphome/components/xiaomi_miscale/xiaomi_miscale.h +0 -1
  572. esphome/components/xiaomi_mjyd02yla/xiaomi_mjyd02yla.h +0 -1
  573. esphome/components/xiaomi_mue4094rt/xiaomi_mue4094rt.h +0 -1
  574. esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.h +0 -1
  575. esphome/components/xiaomi_wx08zm/xiaomi_wx08zm.h +0 -1
  576. esphome/components/xiaomi_xmwsdj04mmc/__init__.py +0 -0
  577. esphome/components/xiaomi_xmwsdj04mmc/sensor.py +77 -0
  578. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp +77 -0
  579. esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.h +36 -0
  580. esphome/components/zio_ultrasonic/zio_ultrasonic.h +0 -2
  581. esphome/components/zyaura/zyaura.h +0 -1
  582. esphome/config.py +88 -22
  583. esphome/config_helpers.py +74 -1
  584. esphome/config_validation.py +12 -1
  585. esphome/const.py +65 -10
  586. esphome/core/__init__.py +18 -2
  587. esphome/core/application.cpp +169 -10
  588. esphome/core/application.h +145 -165
  589. esphome/core/area.h +19 -0
  590. esphome/core/automation.h +58 -9
  591. esphome/core/color.cpp +3 -5
  592. esphome/core/color.h +16 -16
  593. esphome/core/component.cpp +156 -22
  594. esphome/core/component.h +98 -4
  595. esphome/core/component_iterator.cpp +11 -9
  596. esphome/core/component_iterator.h +12 -10
  597. esphome/core/config.py +155 -6
  598. esphome/core/controller.cpp +4 -2
  599. esphome/core/controller.h +1 -1
  600. esphome/core/datatypes.h +2 -2
  601. esphome/core/defines.h +17 -2
  602. esphome/core/device.h +20 -0
  603. esphome/core/entity_base.cpp +20 -15
  604. esphome/core/entity_base.h +76 -0
  605. esphome/core/entity_helpers.py +168 -1
  606. esphome/core/event_pool.h +81 -0
  607. esphome/core/helpers.cpp +75 -230
  608. esphome/core/helpers.h +165 -105
  609. esphome/core/lock_free_queue.h +151 -0
  610. esphome/core/log.cpp +2 -2
  611. esphome/core/log.h +2 -0
  612. esphome/core/optional.h +5 -0
  613. esphome/core/ring_buffer.cpp +2 -2
  614. esphome/core/scheduler.cpp +275 -103
  615. esphome/core/scheduler.h +154 -17
  616. esphome/core/time.cpp +5 -5
  617. esphome/core/time.h +5 -5
  618. esphome/cpp_generator.py +17 -0
  619. esphome/cpp_helpers.py +0 -22
  620. esphome/cpp_types.py +3 -1
  621. esphome/dashboard/entries.py +1 -1
  622. esphome/dashboard/util/text.py +5 -21
  623. esphome/dashboard/web_server.py +9 -1
  624. esphome/helpers.py +47 -0
  625. esphome/loader.py +15 -1
  626. esphome/pins.py +14 -8
  627. esphome/platformio_api.py +2 -0
  628. esphome/wizard.py +17 -4
  629. esphome/writer.py +44 -3
  630. esphome/yaml_util.py +0 -2
  631. {esphome-2025.6.3.dist-info → esphome-2025.7.0.dist-info}/METADATA +10 -9
  632. {esphome-2025.6.3.dist-info → esphome-2025.7.0.dist-info}/RECORD +637 -578
  633. esphome/components/api/api_pb2_size.h +0 -361
  634. esphome/components/esp32_ble/ble_event_pool.h +0 -72
  635. esphome/components/esp32_ble/queue.h +0 -85
  636. esphome/components/esp32_hall/esp32_hall.cpp +0 -25
  637. esphome/components/esp32_hall/esp32_hall.h +0 -23
  638. esphome/components/esp32_touch/esp32_touch.cpp +0 -355
  639. esphome/components/ld2410/button/reset_button.cpp +0 -9
  640. esphome/components/ld2450/button/reset_button.cpp +0 -9
  641. esphome/components/openthread/tlv.py +0 -65
  642. /esphome/{dashboard/enum.py → enum.py} +0 -0
  643. {esphome-2025.6.3.dist-info → esphome-2025.7.0.dist-info}/WHEEL +0 -0
  644. {esphome-2025.6.3.dist-info → esphome-2025.7.0.dist-info}/entry_points.txt +0 -0
  645. {esphome-2025.6.3.dist-info → esphome-2025.7.0.dist-info}/licenses/LICENSE +0 -0
  646. {esphome-2025.6.3.dist-info → esphome-2025.7.0.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,13 @@ from esphome.config_helpers import Extend, Remove, merge_config
5
5
  import esphome.config_validation as cv
6
6
  from esphome.const import CONF_SUBSTITUTIONS, VALID_SUBSTITUTIONS_CHARACTERS
7
7
  from esphome.yaml_util import ESPHomeDataBase, make_data_base
8
+ from .jinja import (
9
+ Jinja,
10
+ JinjaStr,
11
+ has_jinja,
12
+ TemplateError,
13
+ TemplateRuntimeError,
14
+ )
8
15
 
9
16
  CODEOWNERS = ["@esphome/core"]
10
17
  _LOGGER = logging.getLogger(__name__)
@@ -28,7 +35,7 @@ def validate_substitution_key(value):
28
35
 
29
36
  CONFIG_SCHEMA = cv.Schema(
30
37
  {
31
- validate_substitution_key: cv.string_strict,
38
+ validate_substitution_key: object,
32
39
  }
33
40
  )
34
41
 
@@ -37,7 +44,42 @@ async def to_code(config):
37
44
  pass
38
45
 
39
46
 
40
- def _expand_substitutions(substitutions, value, path, ignore_missing):
47
+ def _expand_jinja(value, orig_value, path, jinja, ignore_missing):
48
+ if has_jinja(value):
49
+ # If the original value passed in to this function is a JinjaStr, it means it contains an unresolved
50
+ # Jinja expression from a previous pass.
51
+ if isinstance(orig_value, JinjaStr):
52
+ # Rebuild the JinjaStr in case it was lost while replacing substitutions.
53
+ value = JinjaStr(value, orig_value.upvalues)
54
+ try:
55
+ # Invoke the jinja engine to evaluate the expression.
56
+ value, err = jinja.expand(value)
57
+ if err is not None:
58
+ if not ignore_missing and "password" not in path:
59
+ _LOGGER.warning(
60
+ "Found '%s' (see %s) which looks like an expression,"
61
+ " but could not resolve all the variables: %s",
62
+ value,
63
+ "->".join(str(x) for x in path),
64
+ err.message,
65
+ )
66
+ except (
67
+ TemplateError,
68
+ TemplateRuntimeError,
69
+ RuntimeError,
70
+ ArithmeticError,
71
+ AttributeError,
72
+ TypeError,
73
+ ) as err:
74
+ raise cv.Invalid(
75
+ f"{type(err).__name__} Error evaluating jinja expression '{value}': {str(err)}."
76
+ f" See {'->'.join(str(x) for x in path)}",
77
+ path,
78
+ )
79
+ return value
80
+
81
+
82
+ def _expand_substitutions(substitutions, value, path, jinja, ignore_missing):
41
83
  if "$" not in value:
42
84
  return value
43
85
 
@@ -47,7 +89,8 @@ def _expand_substitutions(substitutions, value, path, ignore_missing):
47
89
  while True:
48
90
  m = cv.VARIABLE_PROG.search(value, i)
49
91
  if not m:
50
- # Nothing more to match. Done
92
+ # No more variable substitutions found. See if the remainder looks like a jinja template
93
+ value = _expand_jinja(value, orig_value, path, jinja, ignore_missing)
51
94
  break
52
95
 
53
96
  i, j = m.span(0)
@@ -67,8 +110,15 @@ def _expand_substitutions(substitutions, value, path, ignore_missing):
67
110
  continue
68
111
 
69
112
  sub = substitutions[name]
113
+
114
+ if i == 0 and j == len(value):
115
+ # The variable spans the whole expression, e.g., "${varName}". Return its resolved value directly
116
+ # to conserve its type.
117
+ value = sub
118
+ break
119
+
70
120
  tail = value[j:]
71
- value = value[:i] + sub
121
+ value = value[:i] + str(sub)
72
122
  i = len(value)
73
123
  value += tail
74
124
 
@@ -77,36 +127,43 @@ def _expand_substitutions(substitutions, value, path, ignore_missing):
77
127
  if isinstance(orig_value, ESPHomeDataBase):
78
128
  # even though string can get larger or smaller, the range should point
79
129
  # to original document marks
80
- return make_data_base(value, orig_value)
130
+ value = make_data_base(value, orig_value)
81
131
 
82
132
  return value
83
133
 
84
134
 
85
- def _substitute_item(substitutions, item, path, ignore_missing):
135
+ def _substitute_item(substitutions, item, path, jinja, ignore_missing):
86
136
  if isinstance(item, list):
87
137
  for i, it in enumerate(item):
88
- sub = _substitute_item(substitutions, it, path + [i], ignore_missing)
138
+ sub = _substitute_item(substitutions, it, path + [i], jinja, ignore_missing)
89
139
  if sub is not None:
90
140
  item[i] = sub
91
141
  elif isinstance(item, dict):
92
142
  replace_keys = []
93
143
  for k, v in item.items():
94
144
  if path or k != CONF_SUBSTITUTIONS:
95
- sub = _substitute_item(substitutions, k, path + [k], ignore_missing)
145
+ sub = _substitute_item(
146
+ substitutions, k, path + [k], jinja, ignore_missing
147
+ )
96
148
  if sub is not None:
97
149
  replace_keys.append((k, sub))
98
- sub = _substitute_item(substitutions, v, path + [k], ignore_missing)
150
+ sub = _substitute_item(substitutions, v, path + [k], jinja, ignore_missing)
99
151
  if sub is not None:
100
152
  item[k] = sub
101
153
  for old, new in replace_keys:
102
- item[new] = merge_config(item.get(old), item.get(new))
103
- del item[old]
154
+ if str(new) == str(old):
155
+ item[new] = item[old]
156
+ else:
157
+ item[new] = merge_config(item.get(old), item.get(new))
158
+ del item[old]
104
159
  elif isinstance(item, str):
105
- sub = _expand_substitutions(substitutions, item, path, ignore_missing)
106
- if sub != item:
160
+ sub = _expand_substitutions(substitutions, item, path, jinja, ignore_missing)
161
+ if isinstance(sub, JinjaStr) or sub != item:
107
162
  return sub
108
163
  elif isinstance(item, (core.Lambda, Extend, Remove)):
109
- sub = _expand_substitutions(substitutions, item.value, path, ignore_missing)
164
+ sub = _expand_substitutions(
165
+ substitutions, item.value, path, jinja, ignore_missing
166
+ )
110
167
  if sub != item:
111
168
  item.value = sub
112
169
  return None
@@ -116,11 +173,11 @@ def do_substitution_pass(config, command_line_substitutions, ignore_missing=Fals
116
173
  if CONF_SUBSTITUTIONS not in config and not command_line_substitutions:
117
174
  return
118
175
 
119
- substitutions = config.get(CONF_SUBSTITUTIONS)
120
- if substitutions is None:
121
- substitutions = command_line_substitutions
122
- elif command_line_substitutions:
123
- substitutions = {**substitutions, **command_line_substitutions}
176
+ # Merge substitutions in config, overriding with substitutions coming from command line:
177
+ substitutions = {
178
+ **config.get(CONF_SUBSTITUTIONS, {}),
179
+ **(command_line_substitutions or {}),
180
+ }
124
181
  with cv.prepend_path("substitutions"):
125
182
  if not isinstance(substitutions, dict):
126
183
  raise cv.Invalid(
@@ -133,7 +190,7 @@ def do_substitution_pass(config, command_line_substitutions, ignore_missing=Fals
133
190
  sub = validate_substitution_key(key)
134
191
  if sub != key:
135
192
  replace_keys.append((key, sub))
136
- substitutions[key] = cv.string_strict(value)
193
+ substitutions[key] = value
137
194
  for old, new in replace_keys:
138
195
  substitutions[new] = substitutions[old]
139
196
  del substitutions[old]
@@ -141,4 +198,7 @@ def do_substitution_pass(config, command_line_substitutions, ignore_missing=Fals
141
198
  config[CONF_SUBSTITUTIONS] = substitutions
142
199
  # Move substitutions to the first place to replace substitutions in them correctly
143
200
  config.move_to_end(CONF_SUBSTITUTIONS, False)
144
- _substitute_item(substitutions, config, [], ignore_missing)
201
+
202
+ # Create a Jinja environment that will consider substitutions in scope:
203
+ jinja = Jinja(substitutions)
204
+ _substitute_item(substitutions, config, [], jinja, ignore_missing)
@@ -0,0 +1,99 @@
1
+ import logging
2
+ import math
3
+ import re
4
+ import jinja2 as jinja
5
+ from jinja2.nativetypes import NativeEnvironment
6
+
7
+ TemplateError = jinja.TemplateError
8
+ TemplateSyntaxError = jinja.TemplateSyntaxError
9
+ TemplateRuntimeError = jinja.TemplateRuntimeError
10
+ UndefinedError = jinja.UndefinedError
11
+ Undefined = jinja.Undefined
12
+
13
+ _LOGGER = logging.getLogger(__name__)
14
+
15
+ DETECT_JINJA = r"(\$\{)"
16
+ detect_jinja_re = re.compile(
17
+ r"<%.+?%>" # Block form expression: <% ... %>
18
+ r"|\$\{[^}]+\}", # Braced form expression: ${ ... }
19
+ flags=re.MULTILINE,
20
+ )
21
+
22
+
23
+ def has_jinja(st):
24
+ return detect_jinja_re.search(st) is not None
25
+
26
+
27
+ class JinjaStr(str):
28
+ """
29
+ Wraps a string containing an unresolved Jinja expression,
30
+ storing the variables visible to it when it failed to resolve.
31
+ For example, an expression inside a package, `${ A * B }` may fail
32
+ to resolve at package parsing time if `A` is a local package var
33
+ but `B` is a substitution defined in the root yaml.
34
+ Therefore, we store the value of `A` as an upvalue bound
35
+ to the original string so we may be able to resolve `${ A * B }`
36
+ later in the main substitutions pass.
37
+ """
38
+
39
+ def __new__(cls, value: str, upvalues=None):
40
+ obj = super().__new__(cls, value)
41
+ obj.upvalues = upvalues or {}
42
+ return obj
43
+
44
+ def __init__(self, value: str, upvalues=None):
45
+ self.upvalues = upvalues or {}
46
+
47
+
48
+ class Jinja:
49
+ """
50
+ Wraps a Jinja environment
51
+ """
52
+
53
+ def __init__(self, context_vars):
54
+ self.env = NativeEnvironment(
55
+ trim_blocks=True,
56
+ lstrip_blocks=True,
57
+ block_start_string="<%",
58
+ block_end_string="%>",
59
+ line_statement_prefix="#",
60
+ line_comment_prefix="##",
61
+ variable_start_string="${",
62
+ variable_end_string="}",
63
+ undefined=jinja.StrictUndefined,
64
+ )
65
+ self.env.add_extension("jinja2.ext.do")
66
+ self.env.globals["math"] = math # Inject entire math module
67
+ self.context_vars = {**context_vars}
68
+ self.env.globals = {**self.env.globals, **self.context_vars}
69
+
70
+ def expand(self, content_str):
71
+ """
72
+ Renders a string that may contain Jinja expressions or statements
73
+ Returns the resulting processed string if all values could be resolved.
74
+ Otherwise, it returns a tagged (JinjaStr) string that captures variables
75
+ in scope (upvalues), like a closure for later evaluation.
76
+ """
77
+ result = None
78
+ override_vars = {}
79
+ if isinstance(content_str, JinjaStr):
80
+ # If `value` is already a JinjaStr, it means we are trying to evaluate it again
81
+ # in a parent pass.
82
+ # Hopefully, all required variables are visible now.
83
+ override_vars = content_str.upvalues
84
+ try:
85
+ template = self.env.from_string(content_str)
86
+ result = template.render(override_vars)
87
+ if isinstance(result, Undefined):
88
+ # This happens when the expression is simply an undefined variable. Jinja does not
89
+ # raise an exception, instead we get "Undefined".
90
+ # Trigger an UndefinedError exception so we skip to below.
91
+ print("" + result)
92
+ except (TemplateSyntaxError, UndefinedError) as err:
93
+ # `content_str` contains a Jinja expression that refers to a variable that is undefined
94
+ # in this scope. Perhaps it refers to a root substitution that is not visible yet.
95
+ # Therefore, return the original `content_str` as a JinjaStr, which contains the variables
96
+ # that are actually visible to it at this point to postpone evaluation.
97
+ return JinjaStr(content_str, {**self.context_vars, **override_vars}), err
98
+
99
+ return result, None
@@ -1,5 +1,6 @@
1
1
  #include "sun.h"
2
2
  #include "esphome/core/log.h"
3
+ #include <numbers>
3
4
 
4
5
  /*
5
6
  The formulas/algorithms in this module are based on the book
@@ -18,14 +19,12 @@ using namespace esphome::sun::internal;
18
19
 
19
20
  static const char *const TAG = "sun";
20
21
 
21
- #undef PI
22
22
  #undef degrees
23
23
  #undef radians
24
24
  #undef sq
25
25
 
26
- static const num_t PI = 3.141592653589793;
27
- inline num_t degrees(num_t rad) { return rad * 180 / PI; }
28
- inline num_t radians(num_t deg) { return deg * PI / 180; }
26
+ inline num_t degrees(num_t rad) { return rad * 180 / std::numbers::pi; }
27
+ inline num_t radians(num_t deg) { return deg * std::numbers::pi / 180; }
29
28
  inline num_t arcdeg(num_t deg, num_t minutes, num_t seconds) { return deg + minutes / 60 + seconds / 3600; }
30
29
  inline num_t sq(num_t x) { return x * x; }
31
30
  inline num_t cb(num_t x) { return x * x * x; }
@@ -20,8 +20,8 @@ from esphome.const import (
20
20
  DEVICE_CLASS_SWITCH,
21
21
  )
22
22
  from esphome.core import CORE, coroutine_with_priority
23
+ from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
23
24
  from esphome.cpp_generator import MockObjClass
24
- from esphome.cpp_helpers import setup_entity
25
25
 
26
26
  CODEOWNERS = ["@esphome/core"]
27
27
  IS_PLATFORM_COMPONENT = True
@@ -91,6 +91,9 @@ _SWITCH_SCHEMA = (
91
91
  )
92
92
 
93
93
 
94
+ _SWITCH_SCHEMA.add_extra(entity_duplicate_validator("switch"))
95
+
96
+
94
97
  def switch_schema(
95
98
  class_: MockObjClass,
96
99
  *,
@@ -131,7 +134,7 @@ SWITCH_SCHEMA.add_extra(cv.deprecated_schema_constant("switch"))
131
134
 
132
135
 
133
136
  async def setup_switch_core_(var, config):
134
- await setup_entity(var, config)
137
+ await setup_entity(var, config, "switch")
135
138
 
136
139
  if (inverted := config.get(CONF_INVERTED)) is not None:
137
140
  cg.add(var.set_inverted(inverted))
@@ -12,7 +12,6 @@ class SwitchBinarySensor : public binary_sensor::BinarySensor, public Component
12
12
  void set_source(Switch *source) { source_ = source; }
13
13
  void setup() override;
14
14
  void dump_config() override;
15
- float get_setup_priority() const override { return setup_priority::DATA; }
16
15
 
17
16
  protected:
18
17
  Switch *source_;
@@ -0,0 +1,317 @@
1
+ from esphome import automation, pins
2
+ import esphome.codegen as cg
3
+ from esphome.components import spi
4
+ import esphome.config_validation as cv
5
+ from esphome.const import CONF_BUSY_PIN, CONF_DATA, CONF_FREQUENCY, CONF_ID
6
+ from esphome.core import TimePeriod
7
+
8
+ MULTI_CONF = True
9
+ CODEOWNERS = ["@swoboda1337"]
10
+ DEPENDENCIES = ["spi"]
11
+
12
+ CONF_SX126X_ID = "sx126x_id"
13
+
14
+ CONF_BANDWIDTH = "bandwidth"
15
+ CONF_BITRATE = "bitrate"
16
+ CONF_CODING_RATE = "coding_rate"
17
+ CONF_CRC_ENABLE = "crc_enable"
18
+ CONF_DEVIATION = "deviation"
19
+ CONF_DIO1_PIN = "dio1_pin"
20
+ CONF_HW_VERSION = "hw_version"
21
+ CONF_MODULATION = "modulation"
22
+ CONF_ON_PACKET = "on_packet"
23
+ CONF_PA_POWER = "pa_power"
24
+ CONF_PA_RAMP = "pa_ramp"
25
+ CONF_PAYLOAD_LENGTH = "payload_length"
26
+ CONF_PREAMBLE_DETECT = "preamble_detect"
27
+ CONF_PREAMBLE_SIZE = "preamble_size"
28
+ CONF_RST_PIN = "rst_pin"
29
+ CONF_RX_START = "rx_start"
30
+ CONF_RF_SWITCH = "rf_switch"
31
+ CONF_SHAPING = "shaping"
32
+ CONF_SPREADING_FACTOR = "spreading_factor"
33
+ CONF_SYNC_VALUE = "sync_value"
34
+ CONF_TCXO_VOLTAGE = "tcxo_voltage"
35
+ CONF_TCXO_DELAY = "tcxo_delay"
36
+
37
+ sx126x_ns = cg.esphome_ns.namespace("sx126x")
38
+ SX126x = sx126x_ns.class_("SX126x", cg.Component, spi.SPIDevice)
39
+ SX126xListener = sx126x_ns.class_("SX126xListener")
40
+ SX126xBw = sx126x_ns.enum("SX126xBw")
41
+ SX126xPacketType = sx126x_ns.enum("SX126xPacketType")
42
+ SX126xTcxoCtrl = sx126x_ns.enum("SX126xTcxoCtrl")
43
+ SX126xRampTime = sx126x_ns.enum("SX126xRampTime")
44
+ SX126xPulseShape = sx126x_ns.enum("SX126xPulseShape")
45
+ SX126xLoraCr = sx126x_ns.enum("SX126xLoraCr")
46
+
47
+ BW = {
48
+ "4_8kHz": SX126xBw.SX126X_BW_4800,
49
+ "5_8kHz": SX126xBw.SX126X_BW_5800,
50
+ "7_3kHz": SX126xBw.SX126X_BW_7300,
51
+ "9_7kHz": SX126xBw.SX126X_BW_9700,
52
+ "11_7kHz": SX126xBw.SX126X_BW_11700,
53
+ "14_6kHz": SX126xBw.SX126X_BW_14600,
54
+ "19_5kHz": SX126xBw.SX126X_BW_19500,
55
+ "23_4kHz": SX126xBw.SX126X_BW_23400,
56
+ "29_3kHz": SX126xBw.SX126X_BW_29300,
57
+ "39_0kHz": SX126xBw.SX126X_BW_39000,
58
+ "46_9kHz": SX126xBw.SX126X_BW_46900,
59
+ "58_6kHz": SX126xBw.SX126X_BW_58600,
60
+ "78_2kHz": SX126xBw.SX126X_BW_78200,
61
+ "93_8kHz": SX126xBw.SX126X_BW_93800,
62
+ "117_3kHz": SX126xBw.SX126X_BW_117300,
63
+ "156_2kHz": SX126xBw.SX126X_BW_156200,
64
+ "187_2kHz": SX126xBw.SX126X_BW_187200,
65
+ "234_3kHz": SX126xBw.SX126X_BW_234300,
66
+ "312_0kHz": SX126xBw.SX126X_BW_312000,
67
+ "373_6kHz": SX126xBw.SX126X_BW_373600,
68
+ "467_0kHz": SX126xBw.SX126X_BW_467000,
69
+ "7_8kHz": SX126xBw.SX126X_BW_7810,
70
+ "10_4kHz": SX126xBw.SX126X_BW_10420,
71
+ "15_6kHz": SX126xBw.SX126X_BW_15630,
72
+ "20_8kHz": SX126xBw.SX126X_BW_20830,
73
+ "31_3kHz": SX126xBw.SX126X_BW_31250,
74
+ "41_7kHz": SX126xBw.SX126X_BW_41670,
75
+ "62_5kHz": SX126xBw.SX126X_BW_62500,
76
+ "125_0kHz": SX126xBw.SX126X_BW_125000,
77
+ "250_0kHz": SX126xBw.SX126X_BW_250000,
78
+ "500_0kHz": SX126xBw.SX126X_BW_500000,
79
+ }
80
+
81
+ CODING_RATE = {
82
+ "CR_4_5": SX126xLoraCr.LORA_CR_4_5,
83
+ "CR_4_6": SX126xLoraCr.LORA_CR_4_6,
84
+ "CR_4_7": SX126xLoraCr.LORA_CR_4_7,
85
+ "CR_4_8": SX126xLoraCr.LORA_CR_4_8,
86
+ }
87
+
88
+ MOD = {
89
+ "LORA": SX126xPacketType.PACKET_TYPE_LORA,
90
+ "FSK": SX126xPacketType.PACKET_TYPE_GFSK,
91
+ }
92
+
93
+ TCXO_VOLTAGE = {
94
+ "1_6V": SX126xTcxoCtrl.TCXO_CTRL_1_6V,
95
+ "1_7V": SX126xTcxoCtrl.TCXO_CTRL_1_7V,
96
+ "1_8V": SX126xTcxoCtrl.TCXO_CTRL_1_8V,
97
+ "2_2V": SX126xTcxoCtrl.TCXO_CTRL_2_2V,
98
+ "2_4V": SX126xTcxoCtrl.TCXO_CTRL_2_4V,
99
+ "2_7V": SX126xTcxoCtrl.TCXO_CTRL_2_7V,
100
+ "3_0V": SX126xTcxoCtrl.TCXO_CTRL_3_0V,
101
+ "3_3V": SX126xTcxoCtrl.TCXO_CTRL_3_3V,
102
+ "NONE": SX126xTcxoCtrl.TCXO_CTRL_NONE,
103
+ }
104
+
105
+ RAMP = {
106
+ "10us": SX126xRampTime.PA_RAMP_10,
107
+ "20us": SX126xRampTime.PA_RAMP_20,
108
+ "40us": SX126xRampTime.PA_RAMP_40,
109
+ "80us": SX126xRampTime.PA_RAMP_80,
110
+ "200us": SX126xRampTime.PA_RAMP_200,
111
+ "800us": SX126xRampTime.PA_RAMP_800,
112
+ "1700us": SX126xRampTime.PA_RAMP_1700,
113
+ "3400us": SX126xRampTime.PA_RAMP_3400,
114
+ }
115
+
116
+ SHAPING = {
117
+ "GAUSSIAN_BT_0_3": SX126xPulseShape.GAUSSIAN_BT_0_3,
118
+ "GAUSSIAN_BT_0_5": SX126xPulseShape.GAUSSIAN_BT_0_5,
119
+ "GAUSSIAN_BT_0_7": SX126xPulseShape.GAUSSIAN_BT_0_7,
120
+ "GAUSSIAN_BT_1_0": SX126xPulseShape.GAUSSIAN_BT_1_0,
121
+ "NONE": SX126xPulseShape.NO_FILTER,
122
+ }
123
+
124
+ RunImageCalAction = sx126x_ns.class_(
125
+ "RunImageCalAction", automation.Action, cg.Parented.template(SX126x)
126
+ )
127
+ SendPacketAction = sx126x_ns.class_(
128
+ "SendPacketAction", automation.Action, cg.Parented.template(SX126x)
129
+ )
130
+ SetModeTxAction = sx126x_ns.class_(
131
+ "SetModeTxAction", automation.Action, cg.Parented.template(SX126x)
132
+ )
133
+ SetModeRxAction = sx126x_ns.class_(
134
+ "SetModeRxAction", automation.Action, cg.Parented.template(SX126x)
135
+ )
136
+ SetModeSleepAction = sx126x_ns.class_(
137
+ "SetModeSleepAction", automation.Action, cg.Parented.template(SX126x)
138
+ )
139
+ SetModeStandbyAction = sx126x_ns.class_(
140
+ "SetModeStandbyAction", automation.Action, cg.Parented.template(SX126x)
141
+ )
142
+
143
+
144
+ def validate_raw_data(value):
145
+ if isinstance(value, str):
146
+ return value.encode("utf-8")
147
+ if isinstance(value, list):
148
+ return cv.Schema([cv.hex_uint8_t])(value)
149
+ raise cv.Invalid(
150
+ "data must either be a string wrapped in quotes or a list of bytes"
151
+ )
152
+
153
+
154
+ def validate_config(config):
155
+ lora_bws = [
156
+ "7_8kHz",
157
+ "10_4kHz",
158
+ "15_6kHz",
159
+ "20_8kHz",
160
+ "31_3kHz",
161
+ "41_7kHz",
162
+ "62_5kHz",
163
+ "125_0kHz",
164
+ "250_0kHz",
165
+ "500_0kHz",
166
+ ]
167
+ if config[CONF_MODULATION] == "LORA":
168
+ if config[CONF_BANDWIDTH] not in lora_bws:
169
+ raise cv.Invalid(f"{config[CONF_BANDWIDTH]} is not available with LORA")
170
+ if config[CONF_PREAMBLE_SIZE] < 6:
171
+ raise cv.Invalid("Minimum 'preamble_size' is 6 with LORA")
172
+ if config[CONF_SPREADING_FACTOR] == 6 and config[CONF_PAYLOAD_LENGTH] == 0:
173
+ raise cv.Invalid("Payload length must be set when spreading factor is 6")
174
+ else:
175
+ if config[CONF_BANDWIDTH] in lora_bws:
176
+ raise cv.Invalid(f"{config[CONF_BANDWIDTH]} is not available with FSK")
177
+ if config[CONF_PREAMBLE_DETECT] > len(config[CONF_SYNC_VALUE]):
178
+ raise cv.Invalid("Preamble detection length must be <= sync value length")
179
+ return config
180
+
181
+
182
+ CONFIG_SCHEMA = (
183
+ cv.Schema(
184
+ {
185
+ cv.GenerateID(): cv.declare_id(SX126x),
186
+ cv.Optional(CONF_BANDWIDTH, default="125_0kHz"): cv.enum(BW),
187
+ cv.Optional(CONF_BITRATE, default=4800): cv.int_range(min=600, max=300000),
188
+ cv.Required(CONF_BUSY_PIN): pins.internal_gpio_input_pin_schema,
189
+ cv.Optional(CONF_CODING_RATE, default="CR_4_5"): cv.enum(CODING_RATE),
190
+ cv.Optional(CONF_CRC_ENABLE, default=False): cv.boolean,
191
+ cv.Optional(CONF_DEVIATION, default=5000): cv.int_range(min=0, max=100000),
192
+ cv.Required(CONF_DIO1_PIN): pins.internal_gpio_input_pin_schema,
193
+ cv.Required(CONF_FREQUENCY): cv.int_range(min=137000000, max=1020000000),
194
+ cv.Required(CONF_HW_VERSION): cv.one_of(
195
+ "sx1261", "sx1262", "sx1268", "llcc68", lower=True
196
+ ),
197
+ cv.Required(CONF_MODULATION): cv.enum(MOD),
198
+ cv.Optional(CONF_ON_PACKET): automation.validate_automation(single=True),
199
+ cv.Optional(CONF_PA_POWER, default=17): cv.int_range(min=-3, max=22),
200
+ cv.Optional(CONF_PA_RAMP, default="40us"): cv.enum(RAMP),
201
+ cv.Optional(CONF_PAYLOAD_LENGTH, default=0): cv.int_range(min=0, max=256),
202
+ cv.Optional(CONF_PREAMBLE_DETECT, default=2): cv.int_range(min=0, max=4),
203
+ cv.Optional(CONF_PREAMBLE_SIZE, default=8): cv.int_range(min=1, max=65535),
204
+ cv.Required(CONF_RST_PIN): pins.internal_gpio_output_pin_schema,
205
+ cv.Optional(CONF_RX_START, default=True): cv.boolean,
206
+ cv.Required(CONF_RF_SWITCH): cv.boolean,
207
+ cv.Optional(CONF_SHAPING, default="NONE"): cv.enum(SHAPING),
208
+ cv.Optional(CONF_SPREADING_FACTOR, default=7): cv.int_range(min=6, max=12),
209
+ cv.Optional(CONF_SYNC_VALUE, default=[]): cv.ensure_list(cv.hex_uint8_t),
210
+ cv.Optional(CONF_TCXO_VOLTAGE, default="NONE"): cv.enum(TCXO_VOLTAGE),
211
+ cv.Optional(CONF_TCXO_DELAY, default="5ms"): cv.All(
212
+ cv.positive_time_period_microseconds,
213
+ cv.Range(max=TimePeriod(microseconds=262144000)),
214
+ ),
215
+ },
216
+ )
217
+ .extend(cv.COMPONENT_SCHEMA)
218
+ .extend(spi.spi_device_schema(True, 8e6, "mode0"))
219
+ .add_extra(validate_config)
220
+ )
221
+
222
+
223
+ async def to_code(config):
224
+ var = cg.new_Pvariable(config[CONF_ID])
225
+ await cg.register_component(var, config)
226
+ await spi.register_spi_device(var, config)
227
+ if CONF_ON_PACKET in config:
228
+ await automation.build_automation(
229
+ var.get_packet_trigger(),
230
+ [
231
+ (cg.std_vector.template(cg.uint8), "x"),
232
+ (cg.float_, "rssi"),
233
+ (cg.float_, "snr"),
234
+ ],
235
+ config[CONF_ON_PACKET],
236
+ )
237
+ if CONF_DIO1_PIN in config:
238
+ dio1_pin = await cg.gpio_pin_expression(config[CONF_DIO1_PIN])
239
+ cg.add(var.set_dio1_pin(dio1_pin))
240
+ rst_pin = await cg.gpio_pin_expression(config[CONF_RST_PIN])
241
+ cg.add(var.set_rst_pin(rst_pin))
242
+ busy_pin = await cg.gpio_pin_expression(config[CONF_BUSY_PIN])
243
+ cg.add(var.set_busy_pin(busy_pin))
244
+ cg.add(var.set_bandwidth(config[CONF_BANDWIDTH]))
245
+ cg.add(var.set_frequency(config[CONF_FREQUENCY]))
246
+ cg.add(var.set_hw_version(config[CONF_HW_VERSION]))
247
+ cg.add(var.set_deviation(config[CONF_DEVIATION]))
248
+ cg.add(var.set_modulation(config[CONF_MODULATION]))
249
+ cg.add(var.set_pa_ramp(config[CONF_PA_RAMP]))
250
+ cg.add(var.set_pa_power(config[CONF_PA_POWER]))
251
+ cg.add(var.set_shaping(config[CONF_SHAPING]))
252
+ cg.add(var.set_bitrate(config[CONF_BITRATE]))
253
+ cg.add(var.set_crc_enable(config[CONF_CRC_ENABLE]))
254
+ cg.add(var.set_payload_length(config[CONF_PAYLOAD_LENGTH]))
255
+ cg.add(var.set_preamble_size(config[CONF_PREAMBLE_SIZE]))
256
+ cg.add(var.set_preamble_detect(config[CONF_PREAMBLE_DETECT]))
257
+ cg.add(var.set_coding_rate(config[CONF_CODING_RATE]))
258
+ cg.add(var.set_spreading_factor(config[CONF_SPREADING_FACTOR]))
259
+ cg.add(var.set_sync_value(config[CONF_SYNC_VALUE]))
260
+ cg.add(var.set_rx_start(config[CONF_RX_START]))
261
+ cg.add(var.set_rf_switch(config[CONF_RF_SWITCH]))
262
+ cg.add(var.set_tcxo_voltage(config[CONF_TCXO_VOLTAGE]))
263
+ cg.add(var.set_tcxo_delay(config[CONF_TCXO_DELAY]))
264
+
265
+
266
+ NO_ARGS_ACTION_SCHEMA = automation.maybe_simple_id(
267
+ {
268
+ cv.GenerateID(): cv.use_id(SX126x),
269
+ }
270
+ )
271
+
272
+
273
+ @automation.register_action(
274
+ "sx126x.run_image_cal", RunImageCalAction, NO_ARGS_ACTION_SCHEMA
275
+ )
276
+ @automation.register_action(
277
+ "sx126x.set_mode_tx", SetModeTxAction, NO_ARGS_ACTION_SCHEMA
278
+ )
279
+ @automation.register_action(
280
+ "sx126x.set_mode_rx", SetModeRxAction, NO_ARGS_ACTION_SCHEMA
281
+ )
282
+ @automation.register_action(
283
+ "sx126x.set_mode_sleep", SetModeSleepAction, NO_ARGS_ACTION_SCHEMA
284
+ )
285
+ @automation.register_action(
286
+ "sx126x.set_mode_standby", SetModeStandbyAction, NO_ARGS_ACTION_SCHEMA
287
+ )
288
+ async def no_args_action_to_code(config, action_id, template_arg, args):
289
+ var = cg.new_Pvariable(action_id, template_arg)
290
+ await cg.register_parented(var, config[CONF_ID])
291
+ return var
292
+
293
+
294
+ SEND_PACKET_ACTION_SCHEMA = cv.maybe_simple_value(
295
+ {
296
+ cv.GenerateID(): cv.use_id(SX126x),
297
+ cv.Required(CONF_DATA): cv.templatable(validate_raw_data),
298
+ },
299
+ key=CONF_DATA,
300
+ )
301
+
302
+
303
+ @automation.register_action(
304
+ "sx126x.send_packet", SendPacketAction, SEND_PACKET_ACTION_SCHEMA
305
+ )
306
+ async def send_packet_action_to_code(config, action_id, template_arg, args):
307
+ var = cg.new_Pvariable(action_id, template_arg)
308
+ await cg.register_parented(var, config[CONF_ID])
309
+ data = config[CONF_DATA]
310
+ if isinstance(data, bytes):
311
+ data = list(data)
312
+ if cg.is_template(data):
313
+ templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8))
314
+ cg.add(var.set_data_template(templ))
315
+ else:
316
+ cg.add(var.set_data_static(data))
317
+ return var