esphome 2025.9.2__py3-none-any.whl → 2025.10.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 (344) hide show
  1. esphome/__main__.py +87 -31
  2. esphome/address_cache.py +142 -0
  3. esphome/automation.py +130 -32
  4. esphome/build_gen/platformio.py +1 -3
  5. esphome/codegen.py +1 -0
  6. esphome/components/animation/animation.cpp +2 -2
  7. esphome/components/api/__init__.py +167 -3
  8. esphome/components/api/api_connection.cpp +84 -41
  9. esphome/components/api/api_connection.h +22 -16
  10. esphome/components/api/api_frame_helper.cpp +33 -19
  11. esphome/components/api/api_frame_helper.h +19 -4
  12. esphome/components/api/api_frame_helper_noise.cpp +41 -53
  13. esphome/components/api/api_frame_helper_noise.h +1 -1
  14. esphome/components/api/api_frame_helper_plaintext.cpp +22 -31
  15. esphome/components/api/api_frame_helper_plaintext.h +1 -1
  16. esphome/components/api/api_pb2.cpp +189 -15
  17. esphome/components/api/api_pb2.h +132 -20
  18. esphome/components/api/api_pb2_dump.cpp +97 -9
  19. esphome/components/api/api_pb2_service.cpp +118 -160
  20. esphome/components/api/api_pb2_service.h +31 -3
  21. esphome/components/api/api_server.cpp +78 -11
  22. esphome/components/api/api_server.h +32 -4
  23. esphome/components/api/custom_api_device.h +8 -8
  24. esphome/components/api/homeassistant_service.h +123 -6
  25. esphome/components/api/proto.h +6 -2
  26. esphome/components/api/user_services.h +2 -2
  27. esphome/components/as7341/sensor.py +1 -1
  28. esphome/components/audio/__init__.py +1 -1
  29. esphome/components/audio/audio.cpp +1 -1
  30. esphome/components/audio/audio_decoder.cpp +9 -9
  31. esphome/components/bl0906/bl0906.cpp +2 -2
  32. esphome/components/bl0942/bl0942.cpp +2 -2
  33. esphome/components/ble_client/__init__.py +1 -1
  34. esphome/components/bluetooth_proxy/__init__.py +4 -30
  35. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +11 -4
  36. esphome/components/bluetooth_proxy/bluetooth_connection.h +2 -2
  37. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +2 -2
  38. esphome/components/camera_encoder/__init__.py +2 -4
  39. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +4 -2
  40. esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +3 -1
  41. esphome/components/canbus/canbus.cpp +7 -5
  42. esphome/components/canbus/canbus.h +4 -4
  43. esphome/components/captive_portal/__init__.py +18 -1
  44. esphome/components/captive_portal/captive_portal.cpp +40 -46
  45. esphome/components/captive_portal/captive_portal.h +20 -22
  46. esphome/components/captive_portal/dns_server_esp32_idf.cpp +205 -0
  47. esphome/components/captive_portal/dns_server_esp32_idf.h +27 -0
  48. esphome/components/ccs811/ccs811.cpp +1 -1
  49. esphome/components/climate/climate.cpp +10 -7
  50. esphome/components/cm1106/cm1106.cpp +1 -1
  51. esphome/components/copy/lock/copy_lock.cpp +1 -1
  52. esphome/components/cover/cover.cpp +1 -0
  53. esphome/components/daikin_arc/daikin_arc.cpp +19 -12
  54. esphome/components/deep_sleep/__init__.py +9 -2
  55. esphome/components/deep_sleep/deep_sleep_component.h +11 -9
  56. esphome/components/deep_sleep/deep_sleep_esp32.cpp +51 -27
  57. esphome/components/ektf2232/touchscreen/__init__.py +8 -5
  58. esphome/components/ektf2232/touchscreen/ektf2232.cpp +4 -4
  59. esphome/components/ektf2232/touchscreen/ektf2232.h +2 -2
  60. esphome/components/epaper_spi/__init__.py +1 -0
  61. esphome/components/epaper_spi/display.py +80 -0
  62. esphome/components/epaper_spi/epaper_spi.cpp +227 -0
  63. esphome/components/epaper_spi/epaper_spi.h +93 -0
  64. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.cpp +42 -0
  65. esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.h +45 -0
  66. esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +135 -0
  67. esphome/components/epaper_spi/epaper_spi_spectra_e6.h +23 -0
  68. esphome/components/es7210/es7210.cpp +3 -3
  69. esphome/components/esp32/__init__.py +254 -339
  70. esphome/components/esp32/boards.py +81 -0
  71. esphome/components/esp32/preferences.cpp +23 -17
  72. esphome/components/esp32_ble/__init__.py +159 -44
  73. esphome/components/esp32_ble/ble.cpp +47 -3
  74. esphome/components/esp32_ble/ble.h +18 -0
  75. esphome/components/esp32_ble/ble_advertising.cpp +7 -3
  76. esphome/components/esp32_ble/ble_advertising.h +4 -0
  77. esphome/components/esp32_ble/ble_uuid.cpp +16 -42
  78. esphome/components/esp32_ble_beacon/__init__.py +3 -4
  79. esphome/components/esp32_ble_client/ble_client_base.cpp +14 -12
  80. esphome/components/esp32_ble_server/__init__.py +28 -14
  81. esphome/components/esp32_ble_server/ble_characteristic.cpp +67 -57
  82. esphome/components/esp32_ble_server/ble_characteristic.h +27 -16
  83. esphome/components/esp32_ble_server/ble_descriptor.cpp +4 -3
  84. esphome/components/esp32_ble_server/ble_descriptor.h +13 -9
  85. esphome/components/esp32_ble_server/ble_server.cpp +59 -24
  86. esphome/components/esp32_ble_server/ble_server.h +38 -20
  87. esphome/components/esp32_ble_server/ble_server_automations.cpp +49 -33
  88. esphome/components/esp32_ble_server/ble_server_automations.h +39 -24
  89. esphome/components/esp32_ble_tracker/__init__.py +25 -80
  90. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -4
  91. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +0 -3
  92. esphome/components/esp32_camera/__init__.py +1 -3
  93. esphome/components/esp32_can/esp32_can.cpp +22 -4
  94. esphome/components/esp32_can/esp32_can.h +3 -0
  95. esphome/components/esp32_hosted/__init__.py +2 -1
  96. esphome/components/esp32_improv/esp32_improv_component.cpp +102 -44
  97. esphome/components/esp32_improv/esp32_improv_component.h +6 -1
  98. esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
  99. esphome/components/esp8266/__init__.py +3 -3
  100. esphome/components/esphome/ota/__init__.py +21 -2
  101. esphome/components/esphome/ota/ota_esphome.cpp +455 -145
  102. esphome/components/esphome/ota/ota_esphome.h +49 -2
  103. esphome/components/ethernet/__init__.py +39 -22
  104. esphome/components/ethernet/ethernet_component.cpp +28 -5
  105. esphome/components/ethernet/ethernet_component.h +5 -1
  106. esphome/components/external_components/__init__.py +8 -6
  107. esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
  108. esphome/components/fingerprint_grow/fingerprint_grow.h +2 -1
  109. esphome/components/font/__init__.py +5 -5
  110. esphome/components/graph/graph.cpp +1 -1
  111. esphome/components/graphical_display_menu/graphical_display_menu.cpp +3 -2
  112. esphome/components/haier/hon_climate.cpp +2 -2
  113. esphome/components/haier/hon_climate.h +1 -1
  114. esphome/components/hdc1080/hdc1080.cpp +42 -34
  115. esphome/components/hdc1080/hdc1080.h +1 -3
  116. esphome/components/homeassistant/number/homeassistant_number.cpp +2 -2
  117. esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
  118. esphome/components/http_request/__init__.py +3 -3
  119. esphome/components/htu21d/htu21d.cpp +13 -18
  120. esphome/components/htu21d/htu21d.h +1 -1
  121. esphome/components/i2s_audio/__init__.py +1 -2
  122. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  123. esphome/components/ili9xxx/ili9xxx_display.cpp +2 -2
  124. esphome/components/improv_serial/improv_serial_component.cpp +12 -15
  125. esphome/components/improv_serial/improv_serial_component.h +6 -8
  126. esphome/components/json/json_util.cpp +35 -43
  127. esphome/components/json/json_util.h +57 -0
  128. esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +2 -2
  129. esphome/components/key_collector/key_collector.h +4 -4
  130. esphome/components/libretiny/__init__.py +6 -6
  131. esphome/components/libretiny/preferences.cpp +23 -16
  132. esphome/components/light/light_call.cpp +98 -120
  133. esphome/components/light/light_call.h +17 -7
  134. esphome/components/lm75b/__init__.py +0 -0
  135. esphome/components/lm75b/lm75b.cpp +39 -0
  136. esphome/components/lm75b/lm75b.h +19 -0
  137. esphome/components/lm75b/sensor.py +34 -0
  138. esphome/components/lock/lock.h +12 -6
  139. esphome/components/logger/__init__.py +15 -27
  140. esphome/components/logger/logger.cpp +10 -20
  141. esphome/components/logger/logger.h +105 -62
  142. esphome/components/logger/logger_esp32.cpp +0 -48
  143. esphome/components/logger/logger_zephyr.cpp +2 -3
  144. esphome/components/logger/select/logger_level_select.cpp +6 -7
  145. esphome/components/logger/select/logger_level_select.h +7 -0
  146. esphome/components/ltr501/ltr501.cpp +7 -6
  147. esphome/components/ltr_als_ps/ltr_als_ps.cpp +7 -6
  148. esphome/components/matrix_keypad/matrix_keypad.h +4 -4
  149. esphome/components/max7219digit/max7219digit.cpp +1 -1
  150. esphome/components/mcp2515/mcp2515.cpp +31 -3
  151. esphome/components/mcp2515/mcp2515_defs.h +3 -1
  152. esphome/components/md5/md5.cpp +0 -26
  153. esphome/components/md5/md5.h +10 -20
  154. esphome/components/mdns/__init__.py +19 -6
  155. esphome/components/mdns/mdns_component.cpp +27 -59
  156. esphome/components/mdns/mdns_component.h +23 -10
  157. esphome/components/mdns/mdns_esp32.cpp +7 -7
  158. esphome/components/mdns/mdns_esp8266.cpp +6 -6
  159. esphome/components/mdns/mdns_libretiny.cpp +3 -3
  160. esphome/components/mdns/mdns_rp2040.cpp +3 -3
  161. esphome/components/mipi/__init__.py +1 -5
  162. esphome/components/mipi_spi/display.py +24 -8
  163. esphome/components/mipi_spi/mipi_spi.h +3 -3
  164. esphome/components/mixer/speaker/mixer_speaker.cpp +3 -3
  165. esphome/components/mmc5603/mmc5603.cpp +3 -3
  166. esphome/components/modbus/modbus.cpp +27 -13
  167. esphome/components/modbus/modbus.h +5 -3
  168. esphome/components/modbus/modbus_definitions.h +86 -0
  169. esphome/components/modbus_controller/__init__.py +29 -1
  170. esphome/components/modbus_controller/const.py +4 -0
  171. esphome/components/modbus_controller/modbus_controller.cpp +38 -13
  172. esphome/components/modbus_controller/modbus_controller.h +18 -29
  173. esphome/components/mpr121/mpr121.cpp +41 -42
  174. esphome/components/mpr121/mpr121.h +0 -1
  175. esphome/components/nau7802/nau7802.cpp +2 -2
  176. esphome/components/network/__init__.py +7 -3
  177. esphome/components/nextion/display.py +4 -4
  178. esphome/components/nextion/nextion.cpp +8 -8
  179. esphome/components/number/__init__.py +2 -0
  180. esphome/components/number/number_call.cpp +23 -12
  181. esphome/components/number/number_call.h +5 -0
  182. esphome/components/online_image/bmp_image.cpp +2 -1
  183. esphome/components/online_image/jpeg_image.cpp +4 -2
  184. esphome/components/openthread/openthread.cpp +6 -7
  185. esphome/components/openthread/openthread.h +0 -1
  186. esphome/components/ota/ota_backend.h +1 -0
  187. esphome/components/packages/__init__.py +10 -8
  188. esphome/components/packet_transport/packet_transport.cpp +2 -0
  189. esphome/components/pid/pid_controller.cpp +1 -1
  190. esphome/components/prometheus/prometheus_handler.cpp +239 -239
  191. esphome/components/psram/__init__.py +30 -28
  192. esphome/components/qmc5883l/qmc5883l.cpp +15 -0
  193. esphome/components/qmc5883l/qmc5883l.h +3 -0
  194. esphome/components/qmc5883l/sensor.py +31 -12
  195. esphome/components/remote_base/gobox_protocol.cpp +3 -3
  196. esphome/components/remote_receiver/__init__.py +14 -2
  197. esphome/components/remote_receiver/{remote_receiver_esp8266.cpp → remote_receiver.cpp} +2 -2
  198. esphome/components/remote_receiver/remote_receiver.h +4 -0
  199. esphome/components/remote_receiver/remote_receiver_esp32.cpp +18 -1
  200. esphome/components/remote_transmitter/__init__.py +2 -2
  201. esphome/components/remote_transmitter/remote_transmitter.cpp +103 -0
  202. esphome/components/rp2040/__init__.py +11 -11
  203. esphome/components/rtttl/rtttl.cpp +2 -2
  204. esphome/components/scd30/sensor.py +1 -1
  205. esphome/components/script/__init__.py +1 -1
  206. esphome/components/script/script.h +7 -7
  207. esphome/components/select/select.cpp +5 -4
  208. esphome/components/select/select_call.cpp +1 -1
  209. esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
  210. esphome/components/sensor/__init__.py +2 -0
  211. esphome/components/sha256/__init__.py +22 -0
  212. esphome/components/sha256/sha256.cpp +116 -0
  213. esphome/components/sha256/sha256.h +60 -0
  214. esphome/components/sim800l/sim800l.cpp +8 -4
  215. esphome/components/socket/lwip_raw_tcp_impl.cpp +34 -6
  216. esphome/components/sonoff_d1/sonoff_d1.cpp +1 -1
  217. esphome/components/spi/__init__.py +0 -3
  218. esphome/components/split_buffer/__init__.py +5 -0
  219. esphome/components/split_buffer/split_buffer.cpp +133 -0
  220. esphome/components/split_buffer/split_buffer.h +40 -0
  221. esphome/components/sps30/sps30.cpp +14 -10
  222. esphome/components/sps30/sps30.h +2 -0
  223. esphome/components/st7567_i2c/st7567_i2c.cpp +3 -1
  224. esphome/components/st7789v/st7789v.cpp +3 -2
  225. esphome/components/statsd/statsd.cpp +1 -1
  226. esphome/components/substitutions/__init__.py +3 -1
  227. esphome/components/substitutions/jinja.py +13 -3
  228. esphome/components/sx126x/__init__.py +16 -0
  229. esphome/components/sx126x/sx126x.cpp +15 -1
  230. esphome/components/sx126x/sx126x.h +9 -1
  231. esphome/components/sx126x/sx126x_reg.h +2 -0
  232. esphome/components/text_sensor/text_sensor.cpp +16 -0
  233. esphome/components/text_sensor/text_sensor.h +3 -10
  234. esphome/components/tormatic/tormatic_cover.cpp +1 -1
  235. esphome/components/tuya/select/tuya_select.cpp +1 -1
  236. esphome/components/tuya/tuya.cpp +29 -4
  237. esphome/components/uart/__init__.py +36 -26
  238. esphome/components/uart/uart.h +6 -0
  239. esphome/components/uart/uart_component.cpp +8 -0
  240. esphome/components/uart/uart_component.h +28 -0
  241. esphome/components/uart/uart_component_esp_idf.cpp +64 -10
  242. esphome/components/uart/uart_component_esp_idf.h +5 -2
  243. esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
  244. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +1 -1
  245. esphome/components/uponor_smatrix/uponor_smatrix.cpp +3 -3
  246. esphome/components/usb_host/__init__.py +2 -1
  247. esphome/components/usb_host/usb_host.h +82 -13
  248. esphome/components/usb_host/usb_host_client.cpp +180 -24
  249. esphome/components/usb_host/usb_host_component.cpp +1 -1
  250. esphome/components/usb_uart/__init__.py +0 -1
  251. esphome/components/usb_uart/ch34x.cpp +4 -4
  252. esphome/components/usb_uart/cp210x.cpp +3 -3
  253. esphome/components/usb_uart/usb_uart.cpp +88 -32
  254. esphome/components/usb_uart/usb_uart.h +30 -6
  255. esphome/components/valve/valve.cpp +1 -0
  256. esphome/components/veml7700/veml7700.cpp +7 -6
  257. esphome/components/version/version_text_sensor.cpp +2 -1
  258. esphome/components/voice_assistant/voice_assistant.cpp +3 -3
  259. esphome/components/waveshare_epaper/waveshare_epaper.cpp +4 -4
  260. esphome/components/web_server/list_entities.cpp +3 -4
  261. esphome/components/web_server/list_entities.h +8 -10
  262. esphome/components/web_server/ota/__init__.py +1 -1
  263. esphome/components/web_server/ota/ota_web_server.cpp +9 -3
  264. esphome/components/web_server/web_server.cpp +509 -404
  265. esphome/components/web_server/web_server.h +5 -6
  266. esphome/components/web_server/web_server_v1.cpp +21 -19
  267. esphome/components/web_server_base/__init__.py +5 -2
  268. esphome/components/web_server_base/web_server_base.h +27 -7
  269. esphome/components/web_server_idf/__init__.py +1 -1
  270. esphome/components/web_server_idf/multipart.cpp +2 -2
  271. esphome/components/web_server_idf/multipart.h +2 -2
  272. esphome/components/web_server_idf/utils.cpp +2 -2
  273. esphome/components/web_server_idf/utils.h +2 -2
  274. esphome/components/web_server_idf/web_server_idf.cpp +118 -26
  275. esphome/components/web_server_idf/web_server_idf.h +12 -10
  276. esphome/components/wifi/__init__.py +13 -11
  277. esphome/components/wifi/wifi_component.cpp +73 -56
  278. esphome/components/wifi/wifi_component.h +4 -4
  279. esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
  280. esphome/components/wifi/wifi_component_esp_idf.cpp +24 -4
  281. esphome/components/wireguard/__init__.py +1 -1
  282. esphome/components/wts01/__init__.py +0 -0
  283. esphome/components/wts01/sensor.py +41 -0
  284. esphome/components/wts01/wts01.cpp +91 -0
  285. esphome/components/wts01/wts01.h +27 -0
  286. esphome/components/zephyr/__init__.py +5 -5
  287. esphome/components/zwave_proxy/__init__.py +43 -0
  288. esphome/components/zwave_proxy/zwave_proxy.cpp +346 -0
  289. esphome/components/zwave_proxy/zwave_proxy.h +93 -0
  290. esphome/config.py +79 -24
  291. esphome/config_validation.py +13 -15
  292. esphome/const.py +9 -2
  293. esphome/core/__init__.py +31 -22
  294. esphome/core/component.cpp +28 -18
  295. esphome/core/component_iterator.h +2 -1
  296. esphome/core/config.py +15 -15
  297. esphome/core/defines.h +19 -0
  298. esphome/core/hash_base.h +56 -0
  299. esphome/core/helpers.cpp +19 -3
  300. esphome/core/helpers.h +26 -0
  301. esphome/core/scheduler.cpp +5 -21
  302. esphome/core/scheduler.h +19 -8
  303. esphome/core/string_ref.h +1 -1
  304. esphome/core/time.cpp +5 -5
  305. esphome/cpp_generator.py +4 -29
  306. esphome/dashboard/const.py +21 -4
  307. esphome/dashboard/core.py +10 -8
  308. esphome/dashboard/dns.py +15 -0
  309. esphome/dashboard/entries.py +15 -21
  310. esphome/dashboard/models.py +76 -0
  311. esphome/dashboard/settings.py +7 -7
  312. esphome/dashboard/status/mdns.py +46 -2
  313. esphome/dashboard/web_server.py +367 -93
  314. esphome/espota2.py +111 -31
  315. esphome/external_files.py +6 -7
  316. esphome/git.py +8 -0
  317. esphome/helpers.py +124 -77
  318. esphome/loader.py +8 -9
  319. esphome/platformio_api.py +25 -18
  320. esphome/storage_json.py +26 -21
  321. esphome/types.py +30 -2
  322. esphome/util.py +32 -16
  323. esphome/vscode.py +8 -8
  324. esphome/wizard.py +10 -10
  325. esphome/writer.py +50 -15
  326. esphome/yaml_util.py +37 -31
  327. esphome/zeroconf.py +12 -3
  328. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/METADATA +11 -11
  329. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/RECORD +333 -313
  330. esphome/components/event_emitter/__init__.py +0 -5
  331. esphome/components/event_emitter/event_emitter.cpp +0 -14
  332. esphome/components/event_emitter/event_emitter.h +0 -63
  333. esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -125
  334. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +0 -107
  335. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +0 -110
  336. esphome/components/uart/uart_component_esp32_arduino.cpp +0 -214
  337. esphome/components/uart/uart_component_esp32_arduino.h +0 -60
  338. esphome/components/wifi/wifi_component_esp32_arduino.cpp +0 -860
  339. esphome/core/string_ref.cpp +0 -12
  340. esphome/dashboard/util/file.py +0 -63
  341. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/WHEEL +0 -0
  342. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/entry_points.txt +0 -0
  343. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/licenses/LICENSE +0 -0
  344. {esphome-2025.9.2.dist-info → esphome-2025.10.0b1.dist-info}/top_level.txt +0 -0
@@ -1,860 +0,0 @@
1
- #include "wifi_component.h"
2
-
3
- #ifdef USE_WIFI
4
- #ifdef USE_ESP32_FRAMEWORK_ARDUINO
5
-
6
- #include <esp_netif.h>
7
- #include <esp_wifi.h>
8
-
9
- #include <algorithm>
10
- #include <utility>
11
- #ifdef USE_WIFI_WPA2_EAP
12
- #include <esp_eap_client.h>
13
- #endif
14
-
15
- #ifdef USE_WIFI_AP
16
- #include "dhcpserver/dhcpserver.h"
17
- #endif // USE_WIFI_AP
18
-
19
- #include "lwip/apps/sntp.h"
20
- #include "lwip/dns.h"
21
- #include "lwip/err.h"
22
-
23
- #include "esphome/core/application.h"
24
- #include "esphome/core/hal.h"
25
- #include "esphome/core/helpers.h"
26
- #include "esphome/core/log.h"
27
- #include "esphome/core/util.h"
28
-
29
- namespace esphome {
30
- namespace wifi {
31
-
32
- static const char *const TAG = "wifi_esp32";
33
-
34
- static esp_netif_t *s_sta_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
35
- #ifdef USE_WIFI_AP
36
- static esp_netif_t *s_ap_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
37
- #endif // USE_WIFI_AP
38
-
39
- static bool s_sta_connecting = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
40
-
41
- void WiFiComponent::wifi_pre_setup_() {
42
- uint8_t mac[6];
43
- if (has_custom_mac_address()) {
44
- get_mac_address_raw(mac);
45
- set_mac_address(mac);
46
- }
47
- auto f = std::bind(&WiFiComponent::wifi_event_callback_, this, std::placeholders::_1, std::placeholders::_2);
48
- WiFi.onEvent(f);
49
- WiFi.persistent(false);
50
- // Make sure WiFi is in clean state before anything starts
51
- this->wifi_mode_(false, false);
52
- }
53
-
54
- bool WiFiComponent::wifi_mode_(optional<bool> sta, optional<bool> ap) {
55
- wifi_mode_t current_mode = WiFiClass::getMode();
56
- bool current_sta = current_mode == WIFI_MODE_STA || current_mode == WIFI_MODE_APSTA;
57
- bool current_ap = current_mode == WIFI_MODE_AP || current_mode == WIFI_MODE_APSTA;
58
-
59
- bool set_sta = sta.value_or(current_sta);
60
- bool set_ap = ap.value_or(current_ap);
61
-
62
- wifi_mode_t set_mode;
63
- if (set_sta && set_ap) {
64
- set_mode = WIFI_MODE_APSTA;
65
- } else if (set_sta && !set_ap) {
66
- set_mode = WIFI_MODE_STA;
67
- } else if (!set_sta && set_ap) {
68
- set_mode = WIFI_MODE_AP;
69
- } else {
70
- set_mode = WIFI_MODE_NULL;
71
- }
72
-
73
- if (current_mode == set_mode)
74
- return true;
75
-
76
- if (set_sta && !current_sta) {
77
- ESP_LOGV(TAG, "Enabling STA");
78
- } else if (!set_sta && current_sta) {
79
- ESP_LOGV(TAG, "Disabling STA");
80
- }
81
- if (set_ap && !current_ap) {
82
- ESP_LOGV(TAG, "Enabling AP");
83
- } else if (!set_ap && current_ap) {
84
- ESP_LOGV(TAG, "Disabling AP");
85
- }
86
-
87
- bool ret = WiFiClass::mode(set_mode);
88
-
89
- if (!ret) {
90
- ESP_LOGW(TAG, "Setting mode failed");
91
- return false;
92
- }
93
-
94
- // WiFiClass::mode above calls esp_netif_create_default_wifi_sta() and
95
- // esp_netif_create_default_wifi_ap(), which creates the interfaces.
96
- // s_sta_netif handle is set during ESPHOME_EVENT_ID_WIFI_STA_START event
97
-
98
- #ifdef USE_WIFI_AP
99
- if (set_ap)
100
- s_ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF");
101
- #endif
102
-
103
- return ret;
104
- }
105
-
106
- bool WiFiComponent::wifi_sta_pre_setup_() {
107
- if (!this->wifi_mode_(true, {}))
108
- return false;
109
-
110
- WiFi.setAutoReconnect(false);
111
- delay(10);
112
- return true;
113
- }
114
-
115
- bool WiFiComponent::wifi_apply_output_power_(float output_power) {
116
- int8_t val = static_cast<int8_t>(output_power * 4);
117
- return esp_wifi_set_max_tx_power(val) == ESP_OK;
118
- }
119
-
120
- bool WiFiComponent::wifi_apply_power_save_() {
121
- wifi_ps_type_t power_save;
122
- switch (this->power_save_) {
123
- case WIFI_POWER_SAVE_LIGHT:
124
- power_save = WIFI_PS_MIN_MODEM;
125
- break;
126
- case WIFI_POWER_SAVE_HIGH:
127
- power_save = WIFI_PS_MAX_MODEM;
128
- break;
129
- case WIFI_POWER_SAVE_NONE:
130
- default:
131
- power_save = WIFI_PS_NONE;
132
- break;
133
- }
134
- return esp_wifi_set_ps(power_save) == ESP_OK;
135
- }
136
-
137
- bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
138
- // enable STA
139
- if (!this->wifi_mode_(true, {}))
140
- return false;
141
-
142
- // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#_CPPv417wifi_sta_config_t
143
- wifi_config_t conf;
144
- memset(&conf, 0, sizeof(conf));
145
- if (ap.get_ssid().size() > sizeof(conf.sta.ssid)) {
146
- ESP_LOGE(TAG, "SSID too long");
147
- return false;
148
- }
149
- if (ap.get_password().size() > sizeof(conf.sta.password)) {
150
- ESP_LOGE(TAG, "Password too long");
151
- return false;
152
- }
153
- memcpy(reinterpret_cast<char *>(conf.sta.ssid), ap.get_ssid().c_str(), ap.get_ssid().size());
154
- memcpy(reinterpret_cast<char *>(conf.sta.password), ap.get_password().c_str(), ap.get_password().size());
155
-
156
- // The weakest authmode to accept in the fast scan mode
157
- if (ap.get_password().empty()) {
158
- conf.sta.threshold.authmode = WIFI_AUTH_OPEN;
159
- } else {
160
- conf.sta.threshold.authmode = WIFI_AUTH_WPA_WPA2_PSK;
161
- }
162
-
163
- #ifdef USE_WIFI_WPA2_EAP
164
- if (ap.get_eap().has_value()) {
165
- conf.sta.threshold.authmode = WIFI_AUTH_WPA2_ENTERPRISE;
166
- }
167
- #endif
168
-
169
- if (ap.get_bssid().has_value()) {
170
- conf.sta.bssid_set = true;
171
- memcpy(conf.sta.bssid, ap.get_bssid()->data(), 6);
172
- } else {
173
- conf.sta.bssid_set = false;
174
- }
175
- if (ap.get_channel().has_value()) {
176
- conf.sta.channel = *ap.get_channel();
177
- conf.sta.scan_method = WIFI_FAST_SCAN;
178
- } else {
179
- conf.sta.scan_method = WIFI_ALL_CHANNEL_SCAN;
180
- }
181
- // Listen interval for ESP32 station to receive beacon when WIFI_PS_MAX_MODEM is set.
182
- // Units: AP beacon intervals. Defaults to 3 if set to 0.
183
- conf.sta.listen_interval = 0;
184
-
185
- // Protected Management Frame
186
- // Device will prefer to connect in PMF mode if other device also advertises PMF capability.
187
- conf.sta.pmf_cfg.capable = true;
188
- conf.sta.pmf_cfg.required = false;
189
-
190
- // note, we do our own filtering
191
- // The minimum rssi to accept in the fast scan mode
192
- conf.sta.threshold.rssi = -127;
193
-
194
- conf.sta.threshold.authmode = WIFI_AUTH_OPEN;
195
-
196
- wifi_config_t current_conf;
197
- esp_err_t err;
198
- err = esp_wifi_get_config(WIFI_IF_STA, &current_conf);
199
- if (err != ERR_OK) {
200
- ESP_LOGW(TAG, "esp_wifi_get_config failed: %s", esp_err_to_name(err));
201
- // can continue
202
- }
203
-
204
- if (memcmp(&current_conf, &conf, sizeof(wifi_config_t)) != 0) { // NOLINT
205
- err = esp_wifi_disconnect();
206
- if (err != ESP_OK) {
207
- ESP_LOGV(TAG, "esp_wifi_disconnect failed: %s", esp_err_to_name(err));
208
- return false;
209
- }
210
- }
211
-
212
- err = esp_wifi_set_config(WIFI_IF_STA, &conf);
213
- if (err != ESP_OK) {
214
- ESP_LOGV(TAG, "esp_wifi_set_config failed: %s", esp_err_to_name(err));
215
- return false;
216
- }
217
-
218
- if (!this->wifi_sta_ip_config_(ap.get_manual_ip())) {
219
- return false;
220
- }
221
-
222
- // setup enterprise authentication if required
223
- #ifdef USE_WIFI_WPA2_EAP
224
- if (ap.get_eap().has_value()) {
225
- // note: all certificates and keys have to be null terminated. Lengths are appended by +1 to include \0.
226
- EAPAuth eap = ap.get_eap().value();
227
- err = esp_eap_client_set_identity((uint8_t *) eap.identity.c_str(), eap.identity.length());
228
- if (err != ESP_OK) {
229
- ESP_LOGV(TAG, "esp_eap_client_set_identity failed: %d", err);
230
- }
231
- int ca_cert_len = strlen(eap.ca_cert);
232
- int client_cert_len = strlen(eap.client_cert);
233
- int client_key_len = strlen(eap.client_key);
234
- if (ca_cert_len) {
235
- err = esp_eap_client_set_ca_cert((uint8_t *) eap.ca_cert, ca_cert_len + 1);
236
- if (err != ESP_OK) {
237
- ESP_LOGV(TAG, "esp_eap_client_set_ca_cert failed: %d", err);
238
- }
239
- }
240
- // workout what type of EAP this is
241
- // validation is not required as the config tool has already validated it
242
- if (client_cert_len && client_key_len) {
243
- // if we have certs, this must be EAP-TLS
244
- err = esp_eap_client_set_certificate_and_key((uint8_t *) eap.client_cert, client_cert_len + 1,
245
- (uint8_t *) eap.client_key, client_key_len + 1,
246
- (uint8_t *) eap.password.c_str(), strlen(eap.password.c_str()));
247
- if (err != ESP_OK) {
248
- ESP_LOGV(TAG, "esp_eap_client_set_certificate_and_key failed: %d", err);
249
- }
250
- } else {
251
- // in the absence of certs, assume this is username/password based
252
- err = esp_eap_client_set_username((uint8_t *) eap.username.c_str(), eap.username.length());
253
- if (err != ESP_OK) {
254
- ESP_LOGV(TAG, "esp_eap_client_set_username failed: %d", err);
255
- }
256
- err = esp_eap_client_set_password((uint8_t *) eap.password.c_str(), eap.password.length());
257
- if (err != ESP_OK) {
258
- ESP_LOGV(TAG, "esp_eap_client_set_password failed: %d", err);
259
- }
260
- }
261
- err = esp_wifi_sta_enterprise_enable();
262
- if (err != ESP_OK) {
263
- ESP_LOGV(TAG, "esp_wifi_sta_enterprise_enable failed: %d", err);
264
- }
265
- }
266
- #endif // USE_WIFI_WPA2_EAP
267
-
268
- this->wifi_apply_hostname_();
269
-
270
- s_sta_connecting = true;
271
-
272
- err = esp_wifi_connect();
273
- if (err != ESP_OK) {
274
- ESP_LOGW(TAG, "esp_wifi_connect failed: %s", esp_err_to_name(err));
275
- return false;
276
- }
277
-
278
- return true;
279
- }
280
-
281
- bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
282
- // enable STA
283
- if (!this->wifi_mode_(true, {}))
284
- return false;
285
-
286
- // Check if the STA interface is initialized before using it
287
- if (s_sta_netif == nullptr) {
288
- ESP_LOGW(TAG, "STA interface not initialized");
289
- return false;
290
- }
291
-
292
- esp_netif_dhcp_status_t dhcp_status;
293
- esp_err_t err = esp_netif_dhcpc_get_status(s_sta_netif, &dhcp_status);
294
- if (err != ESP_OK) {
295
- ESP_LOGV(TAG, "esp_netif_dhcpc_get_status failed: %s", esp_err_to_name(err));
296
- return false;
297
- }
298
-
299
- if (!manual_ip.has_value()) {
300
- // sntp_servermode_dhcp lwip/sntp.c (Required to lock TCPIP core functionality!)
301
- // https://github.com/esphome/issues/issues/6591
302
- // https://github.com/espressif/arduino-esp32/issues/10526
303
- {
304
- LwIPLock lock;
305
- // lwIP starts the SNTP client if it gets an SNTP server from DHCP. We don't need the time, and more importantly,
306
- // the built-in SNTP client has a memory leak in certain situations. Disable this feature.
307
- // https://github.com/esphome/issues/issues/2299
308
- sntp_servermode_dhcp(false);
309
- }
310
-
311
- // No manual IP is set; use DHCP client
312
- if (dhcp_status != ESP_NETIF_DHCP_STARTED) {
313
- err = esp_netif_dhcpc_start(s_sta_netif);
314
- if (err != ESP_OK) {
315
- ESP_LOGV(TAG, "Starting DHCP client failed: %d", err);
316
- }
317
- return err == ESP_OK;
318
- }
319
- return true;
320
- }
321
-
322
- esp_netif_ip_info_t info; // struct of ip4_addr_t with ip, netmask, gw
323
- info.ip = manual_ip->static_ip;
324
- info.gw = manual_ip->gateway;
325
- info.netmask = manual_ip->subnet;
326
- err = esp_netif_dhcpc_stop(s_sta_netif);
327
- if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) {
328
- ESP_LOGV(TAG, "Stopping DHCP client failed: %s", esp_err_to_name(err));
329
- }
330
-
331
- err = esp_netif_set_ip_info(s_sta_netif, &info);
332
- if (err != ESP_OK) {
333
- ESP_LOGV(TAG, "Setting manual IP info failed: %s", esp_err_to_name(err));
334
- }
335
-
336
- esp_netif_dns_info_t dns;
337
- if (manual_ip->dns1.is_set()) {
338
- dns.ip = manual_ip->dns1;
339
- esp_netif_set_dns_info(s_sta_netif, ESP_NETIF_DNS_MAIN, &dns);
340
- }
341
- if (manual_ip->dns2.is_set()) {
342
- dns.ip = manual_ip->dns2;
343
- esp_netif_set_dns_info(s_sta_netif, ESP_NETIF_DNS_BACKUP, &dns);
344
- }
345
-
346
- return true;
347
- }
348
-
349
- network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() {
350
- if (!this->has_sta())
351
- return {};
352
- network::IPAddresses addresses;
353
- esp_netif_ip_info_t ip;
354
- esp_err_t err = esp_netif_get_ip_info(s_sta_netif, &ip);
355
- if (err != ESP_OK) {
356
- ESP_LOGV(TAG, "esp_netif_get_ip_info failed: %s", esp_err_to_name(err));
357
- // TODO: do something smarter
358
- // return false;
359
- } else {
360
- addresses[0] = network::IPAddress(&ip.ip);
361
- }
362
- #if USE_NETWORK_IPV6
363
- struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES];
364
- uint8_t count = 0;
365
- count = esp_netif_get_all_ip6(s_sta_netif, if_ip6s);
366
- assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES);
367
- for (int i = 0; i < count; i++) {
368
- addresses[i + 1] = network::IPAddress(&if_ip6s[i]);
369
- }
370
- #endif /* USE_NETWORK_IPV6 */
371
- return addresses;
372
- }
373
-
374
- bool WiFiComponent::wifi_apply_hostname_() {
375
- // setting is done in SYSTEM_EVENT_STA_START callback
376
- return true;
377
- }
378
- const char *get_auth_mode_str(uint8_t mode) {
379
- switch (mode) {
380
- case WIFI_AUTH_OPEN:
381
- return "OPEN";
382
- case WIFI_AUTH_WEP:
383
- return "WEP";
384
- case WIFI_AUTH_WPA_PSK:
385
- return "WPA PSK";
386
- case WIFI_AUTH_WPA2_PSK:
387
- return "WPA2 PSK";
388
- case WIFI_AUTH_WPA_WPA2_PSK:
389
- return "WPA/WPA2 PSK";
390
- case WIFI_AUTH_WPA2_ENTERPRISE:
391
- return "WPA2 Enterprise";
392
- case WIFI_AUTH_WPA3_PSK:
393
- return "WPA3 PSK";
394
- case WIFI_AUTH_WPA2_WPA3_PSK:
395
- return "WPA2/WPA3 PSK";
396
- case WIFI_AUTH_WAPI_PSK:
397
- return "WAPI PSK";
398
- default:
399
- return "UNKNOWN";
400
- }
401
- }
402
-
403
- using esphome_ip4_addr_t = esp_ip4_addr_t;
404
-
405
- std::string format_ip4_addr(const esphome_ip4_addr_t &ip) {
406
- char buf[20];
407
- sprintf(buf, "%u.%u.%u.%u", uint8_t(ip.addr >> 0), uint8_t(ip.addr >> 8), uint8_t(ip.addr >> 16),
408
- uint8_t(ip.addr >> 24));
409
- return buf;
410
- }
411
- const char *get_op_mode_str(uint8_t mode) {
412
- switch (mode) {
413
- case WIFI_OFF:
414
- return "OFF";
415
- case WIFI_STA:
416
- return "STA";
417
- case WIFI_AP:
418
- return "AP";
419
- case WIFI_AP_STA:
420
- return "AP+STA";
421
- default:
422
- return "UNKNOWN";
423
- }
424
- }
425
- const char *get_disconnect_reason_str(uint8_t reason) {
426
- switch (reason) {
427
- case WIFI_REASON_AUTH_EXPIRE:
428
- return "Auth Expired";
429
- case WIFI_REASON_AUTH_LEAVE:
430
- return "Auth Leave";
431
- case WIFI_REASON_ASSOC_EXPIRE:
432
- return "Association Expired";
433
- case WIFI_REASON_ASSOC_TOOMANY:
434
- return "Too Many Associations";
435
- case WIFI_REASON_NOT_AUTHED:
436
- return "Not Authenticated";
437
- case WIFI_REASON_NOT_ASSOCED:
438
- return "Not Associated";
439
- case WIFI_REASON_ASSOC_LEAVE:
440
- return "Association Leave";
441
- case WIFI_REASON_ASSOC_NOT_AUTHED:
442
- return "Association not Authenticated";
443
- case WIFI_REASON_DISASSOC_PWRCAP_BAD:
444
- return "Disassociate Power Cap Bad";
445
- case WIFI_REASON_DISASSOC_SUPCHAN_BAD:
446
- return "Disassociate Supported Channel Bad";
447
- case WIFI_REASON_IE_INVALID:
448
- return "IE Invalid";
449
- case WIFI_REASON_MIC_FAILURE:
450
- return "Mic Failure";
451
- case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
452
- return "4-Way Handshake Timeout";
453
- case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT:
454
- return "Group Key Update Timeout";
455
- case WIFI_REASON_IE_IN_4WAY_DIFFERS:
456
- return "IE In 4-Way Handshake Differs";
457
- case WIFI_REASON_GROUP_CIPHER_INVALID:
458
- return "Group Cipher Invalid";
459
- case WIFI_REASON_PAIRWISE_CIPHER_INVALID:
460
- return "Pairwise Cipher Invalid";
461
- case WIFI_REASON_AKMP_INVALID:
462
- return "AKMP Invalid";
463
- case WIFI_REASON_UNSUPP_RSN_IE_VERSION:
464
- return "Unsupported RSN IE version";
465
- case WIFI_REASON_INVALID_RSN_IE_CAP:
466
- return "Invalid RSN IE Cap";
467
- case WIFI_REASON_802_1X_AUTH_FAILED:
468
- return "802.1x Authentication Failed";
469
- case WIFI_REASON_CIPHER_SUITE_REJECTED:
470
- return "Cipher Suite Rejected";
471
- case WIFI_REASON_BEACON_TIMEOUT:
472
- return "Beacon Timeout";
473
- case WIFI_REASON_NO_AP_FOUND:
474
- return "AP Not Found";
475
- case WIFI_REASON_AUTH_FAIL:
476
- return "Authentication Failed";
477
- case WIFI_REASON_ASSOC_FAIL:
478
- return "Association Failed";
479
- case WIFI_REASON_HANDSHAKE_TIMEOUT:
480
- return "Handshake Failed";
481
- case WIFI_REASON_CONNECTION_FAIL:
482
- return "Connection Failed";
483
- case WIFI_REASON_AP_TSF_RESET:
484
- return "AP TSF reset";
485
- case WIFI_REASON_ROAMING:
486
- return "Station Roaming";
487
- case WIFI_REASON_ASSOC_COMEBACK_TIME_TOO_LONG:
488
- return "Association comeback time too long";
489
- case WIFI_REASON_SA_QUERY_TIMEOUT:
490
- return "SA query timeout";
491
- case WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY:
492
- return "No AP found with compatible security";
493
- case WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD:
494
- return "No AP found in auth mode threshold";
495
- case WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD:
496
- return "No AP found in RSSI threshold";
497
- case WIFI_REASON_UNSPECIFIED:
498
- default:
499
- return "Unspecified";
500
- }
501
- }
502
-
503
- void WiFiComponent::wifi_loop_() {}
504
-
505
- #define ESPHOME_EVENT_ID_WIFI_READY ARDUINO_EVENT_WIFI_READY
506
- #define ESPHOME_EVENT_ID_WIFI_SCAN_DONE ARDUINO_EVENT_WIFI_SCAN_DONE
507
- #define ESPHOME_EVENT_ID_WIFI_STA_START ARDUINO_EVENT_WIFI_STA_START
508
- #define ESPHOME_EVENT_ID_WIFI_STA_STOP ARDUINO_EVENT_WIFI_STA_STOP
509
- #define ESPHOME_EVENT_ID_WIFI_STA_CONNECTED ARDUINO_EVENT_WIFI_STA_CONNECTED
510
- #define ESPHOME_EVENT_ID_WIFI_STA_DISCONNECTED ARDUINO_EVENT_WIFI_STA_DISCONNECTED
511
- #define ESPHOME_EVENT_ID_WIFI_STA_AUTHMODE_CHANGE ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE
512
- #define ESPHOME_EVENT_ID_WIFI_STA_GOT_IP ARDUINO_EVENT_WIFI_STA_GOT_IP
513
- #define ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6 ARDUINO_EVENT_WIFI_STA_GOT_IP6
514
- #define ESPHOME_EVENT_ID_WIFI_STA_LOST_IP ARDUINO_EVENT_WIFI_STA_LOST_IP
515
- #define ESPHOME_EVENT_ID_WIFI_AP_START ARDUINO_EVENT_WIFI_AP_START
516
- #define ESPHOME_EVENT_ID_WIFI_AP_STOP ARDUINO_EVENT_WIFI_AP_STOP
517
- #define ESPHOME_EVENT_ID_WIFI_AP_STACONNECTED ARDUINO_EVENT_WIFI_AP_STACONNECTED
518
- #define ESPHOME_EVENT_ID_WIFI_AP_STADISCONNECTED ARDUINO_EVENT_WIFI_AP_STADISCONNECTED
519
- #define ESPHOME_EVENT_ID_WIFI_AP_STAIPASSIGNED ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED
520
- #define ESPHOME_EVENT_ID_WIFI_AP_PROBEREQRECVED ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED
521
- #define ESPHOME_EVENT_ID_WIFI_AP_GOT_IP6 ARDUINO_EVENT_WIFI_AP_GOT_IP6
522
- using esphome_wifi_event_id_t = arduino_event_id_t;
523
- using esphome_wifi_event_info_t = arduino_event_info_t;
524
-
525
- void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_wifi_event_info_t info) {
526
- switch (event) {
527
- case ESPHOME_EVENT_ID_WIFI_READY: {
528
- ESP_LOGV(TAG, "Ready");
529
- break;
530
- }
531
- case ESPHOME_EVENT_ID_WIFI_SCAN_DONE: {
532
- auto it = info.wifi_scan_done;
533
- ESP_LOGV(TAG, "Scan done: status=%u number=%u scan_id=%u", it.status, it.number, it.scan_id);
534
-
535
- this->wifi_scan_done_callback_();
536
- break;
537
- }
538
- case ESPHOME_EVENT_ID_WIFI_STA_START: {
539
- ESP_LOGV(TAG, "STA start");
540
- // apply hostname
541
- s_sta_netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
542
- esp_err_t err = esp_netif_set_hostname(s_sta_netif, App.get_name().c_str());
543
- if (err != ERR_OK) {
544
- ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err));
545
- }
546
- break;
547
- }
548
- case ESPHOME_EVENT_ID_WIFI_STA_STOP: {
549
- ESP_LOGV(TAG, "STA stop");
550
- break;
551
- }
552
- case ESPHOME_EVENT_ID_WIFI_STA_CONNECTED: {
553
- auto it = info.wifi_sta_connected;
554
- char buf[33];
555
- memcpy(buf, it.ssid, it.ssid_len);
556
- buf[it.ssid_len] = '\0';
557
- ESP_LOGV(TAG, "Connected ssid='%s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", buf,
558
- format_mac_address_pretty(it.bssid).c_str(), it.channel, get_auth_mode_str(it.authmode));
559
- #if USE_NETWORK_IPV6
560
- this->set_timeout(100, [] { WiFi.enableIPv6(); });
561
- #endif /* USE_NETWORK_IPV6 */
562
-
563
- break;
564
- }
565
- case ESPHOME_EVENT_ID_WIFI_STA_DISCONNECTED: {
566
- auto it = info.wifi_sta_disconnected;
567
- char buf[33];
568
- memcpy(buf, it.ssid, it.ssid_len);
569
- buf[it.ssid_len] = '\0';
570
- if (it.reason == WIFI_REASON_NO_AP_FOUND) {
571
- ESP_LOGW(TAG, "Disconnected ssid='%s' reason='Probe Request Unsuccessful'", buf);
572
- } else {
573
- ESP_LOGW(TAG, "Disconnected ssid='%s' bssid=" LOG_SECRET("%s") " reason='%s'", buf,
574
- format_mac_address_pretty(it.bssid).c_str(), get_disconnect_reason_str(it.reason));
575
- }
576
-
577
- uint8_t reason = it.reason;
578
- if (reason == WIFI_REASON_AUTH_EXPIRE || reason == WIFI_REASON_BEACON_TIMEOUT ||
579
- reason == WIFI_REASON_NO_AP_FOUND || reason == WIFI_REASON_ASSOC_FAIL ||
580
- reason == WIFI_REASON_HANDSHAKE_TIMEOUT) {
581
- err_t err = esp_wifi_disconnect();
582
- if (err != ESP_OK) {
583
- ESP_LOGV(TAG, "Disconnect failed: %s", esp_err_to_name(err));
584
- }
585
- this->error_from_callback_ = true;
586
- }
587
-
588
- s_sta_connecting = false;
589
- break;
590
- }
591
- case ESPHOME_EVENT_ID_WIFI_STA_AUTHMODE_CHANGE: {
592
- auto it = info.wifi_sta_authmode_change;
593
- ESP_LOGV(TAG, "Authmode Change old=%s new=%s", get_auth_mode_str(it.old_mode), get_auth_mode_str(it.new_mode));
594
- // Mitigate CVE-2020-12638
595
- // https://lbsfilm.at/blog/wpa2-authenticationmode-downgrade-in-espressif-microprocessors
596
- if (it.old_mode != WIFI_AUTH_OPEN && it.new_mode == WIFI_AUTH_OPEN) {
597
- ESP_LOGW(TAG, "Potential Authmode downgrade detected, disconnecting");
598
- // we can't call retry_connect() from this context, so disconnect immediately
599
- // and notify main thread with error_from_callback_
600
- err_t err = esp_wifi_disconnect();
601
- if (err != ESP_OK) {
602
- ESP_LOGW(TAG, "Disconnect failed: %s", esp_err_to_name(err));
603
- }
604
- this->error_from_callback_ = true;
605
- }
606
- break;
607
- }
608
- case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP: {
609
- auto it = info.got_ip.ip_info;
610
- ESP_LOGV(TAG, "static_ip=%s gateway=%s", format_ip4_addr(it.ip).c_str(), format_ip4_addr(it.gw).c_str());
611
- this->got_ipv4_address_ = true;
612
- #if USE_NETWORK_IPV6
613
- s_sta_connecting = this->num_ipv6_addresses_ < USE_NETWORK_MIN_IPV6_ADDR_COUNT;
614
- #else
615
- s_sta_connecting = false;
616
- #endif /* USE_NETWORK_IPV6 */
617
- break;
618
- }
619
- #if USE_NETWORK_IPV6
620
- case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6: {
621
- auto it = info.got_ip6.ip6_info;
622
- ESP_LOGV(TAG, "IPv6 address=" IPV6STR, IPV62STR(it.ip));
623
- this->num_ipv6_addresses_++;
624
- s_sta_connecting = !(this->got_ipv4_address_ & (this->num_ipv6_addresses_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT));
625
- break;
626
- }
627
- #endif /* USE_NETWORK_IPV6 */
628
- case ESPHOME_EVENT_ID_WIFI_STA_LOST_IP: {
629
- ESP_LOGV(TAG, "Lost IP");
630
- this->got_ipv4_address_ = false;
631
- break;
632
- }
633
- case ESPHOME_EVENT_ID_WIFI_AP_START: {
634
- ESP_LOGV(TAG, "AP start");
635
- break;
636
- }
637
- case ESPHOME_EVENT_ID_WIFI_AP_STOP: {
638
- ESP_LOGV(TAG, "AP stop");
639
- break;
640
- }
641
- case ESPHOME_EVENT_ID_WIFI_AP_STACONNECTED: {
642
- auto it = info.wifi_sta_connected;
643
- auto &mac = it.bssid;
644
- ESP_LOGV(TAG, "AP client connected MAC=%s", format_mac_address_pretty(mac).c_str());
645
- break;
646
- }
647
- case ESPHOME_EVENT_ID_WIFI_AP_STADISCONNECTED: {
648
- auto it = info.wifi_sta_disconnected;
649
- auto &mac = it.bssid;
650
- ESP_LOGV(TAG, "AP client disconnected MAC=%s", format_mac_address_pretty(mac).c_str());
651
- break;
652
- }
653
- case ESPHOME_EVENT_ID_WIFI_AP_STAIPASSIGNED: {
654
- ESP_LOGV(TAG, "AP client assigned IP");
655
- break;
656
- }
657
- case ESPHOME_EVENT_ID_WIFI_AP_PROBEREQRECVED: {
658
- auto it = info.wifi_ap_probereqrecved;
659
- ESP_LOGVV(TAG, "AP receive Probe Request MAC=%s RSSI=%d", format_mac_address_pretty(it.mac).c_str(), it.rssi);
660
- break;
661
- }
662
- default:
663
- break;
664
- }
665
- }
666
-
667
- WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() {
668
- const auto status = WiFi.status();
669
- if (status == WL_CONNECT_FAILED || status == WL_CONNECTION_LOST) {
670
- return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED;
671
- }
672
- if (status == WL_NO_SSID_AVAIL) {
673
- return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND;
674
- }
675
- if (s_sta_connecting) {
676
- return WiFiSTAConnectStatus::CONNECTING;
677
- }
678
- if (status == WL_CONNECTED) {
679
- return WiFiSTAConnectStatus::CONNECTED;
680
- }
681
- return WiFiSTAConnectStatus::IDLE;
682
- }
683
- bool WiFiComponent::wifi_scan_start_(bool passive) {
684
- // enable STA
685
- if (!this->wifi_mode_(true, {}))
686
- return false;
687
-
688
- // need to use WiFi because of WiFiScanClass allocations :(
689
- int16_t err = WiFi.scanNetworks(true, true, passive, 200);
690
- if (err != WIFI_SCAN_RUNNING) {
691
- ESP_LOGV(TAG, "WiFi.scanNetworks failed: %d", err);
692
- return false;
693
- }
694
-
695
- return true;
696
- }
697
- void WiFiComponent::wifi_scan_done_callback_() {
698
- this->scan_result_.clear();
699
-
700
- int16_t num = WiFi.scanComplete();
701
- if (num < 0)
702
- return;
703
-
704
- this->scan_result_.reserve(static_cast<unsigned int>(num));
705
- for (int i = 0; i < num; i++) {
706
- String ssid = WiFi.SSID(i);
707
- wifi_auth_mode_t authmode = WiFi.encryptionType(i);
708
- int32_t rssi = WiFi.RSSI(i);
709
- uint8_t *bssid = WiFi.BSSID(i);
710
- int32_t channel = WiFi.channel(i);
711
-
712
- WiFiScanResult scan({bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]}, std::string(ssid.c_str()),
713
- channel, rssi, authmode != WIFI_AUTH_OPEN, ssid.length() == 0);
714
- this->scan_result_.push_back(scan);
715
- }
716
- WiFi.scanDelete();
717
- this->scan_done_ = true;
718
- }
719
-
720
- #ifdef USE_WIFI_AP
721
- bool WiFiComponent::wifi_ap_ip_config_(optional<ManualIP> manual_ip) {
722
- esp_err_t err;
723
-
724
- // enable AP
725
- if (!this->wifi_mode_({}, true))
726
- return false;
727
-
728
- // Check if the AP interface is initialized before using it
729
- if (s_ap_netif == nullptr) {
730
- ESP_LOGW(TAG, "AP interface not initialized");
731
- return false;
732
- }
733
-
734
- esp_netif_ip_info_t info;
735
- if (manual_ip.has_value()) {
736
- info.ip = manual_ip->static_ip;
737
- info.gw = manual_ip->gateway;
738
- info.netmask = manual_ip->subnet;
739
- } else {
740
- info.ip = network::IPAddress(192, 168, 4, 1);
741
- info.gw = network::IPAddress(192, 168, 4, 1);
742
- info.netmask = network::IPAddress(255, 255, 255, 0);
743
- }
744
-
745
- err = esp_netif_dhcps_stop(s_ap_netif);
746
- if (err != ESP_OK && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) {
747
- ESP_LOGE(TAG, "esp_netif_dhcps_stop failed: %s", esp_err_to_name(err));
748
- return false;
749
- }
750
-
751
- err = esp_netif_set_ip_info(s_ap_netif, &info);
752
- if (err != ESP_OK) {
753
- ESP_LOGE(TAG, "esp_netif_set_ip_info failed: %d", err);
754
- return false;
755
- }
756
-
757
- dhcps_lease_t lease;
758
- lease.enable = true;
759
- network::IPAddress start_address = network::IPAddress(&info.ip);
760
- start_address += 99;
761
- lease.start_ip = start_address;
762
- ESP_LOGV(TAG, "DHCP server IP lease start: %s", start_address.str().c_str());
763
- start_address += 10;
764
- lease.end_ip = start_address;
765
- ESP_LOGV(TAG, "DHCP server IP lease end: %s", start_address.str().c_str());
766
- err = esp_netif_dhcps_option(s_ap_netif, ESP_NETIF_OP_SET, ESP_NETIF_REQUESTED_IP_ADDRESS, &lease, sizeof(lease));
767
-
768
- if (err != ESP_OK) {
769
- ESP_LOGE(TAG, "esp_netif_dhcps_option failed: %d", err);
770
- return false;
771
- }
772
-
773
- err = esp_netif_dhcps_start(s_ap_netif);
774
-
775
- if (err != ESP_OK) {
776
- ESP_LOGE(TAG, "esp_netif_dhcps_start failed: %d", err);
777
- return false;
778
- }
779
-
780
- return true;
781
- }
782
-
783
- bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) {
784
- // enable AP
785
- if (!this->wifi_mode_({}, true))
786
- return false;
787
-
788
- wifi_config_t conf;
789
- memset(&conf, 0, sizeof(conf));
790
- if (ap.get_ssid().size() > sizeof(conf.ap.ssid)) {
791
- ESP_LOGE(TAG, "AP SSID too long");
792
- return false;
793
- }
794
- memcpy(reinterpret_cast<char *>(conf.ap.ssid), ap.get_ssid().c_str(), ap.get_ssid().size());
795
- conf.ap.channel = ap.get_channel().value_or(1);
796
- conf.ap.ssid_hidden = ap.get_ssid().size();
797
- conf.ap.max_connection = 5;
798
- conf.ap.beacon_interval = 100;
799
-
800
- if (ap.get_password().empty()) {
801
- conf.ap.authmode = WIFI_AUTH_OPEN;
802
- *conf.ap.password = 0;
803
- } else {
804
- conf.ap.authmode = WIFI_AUTH_WPA2_PSK;
805
- if (ap.get_password().size() > sizeof(conf.ap.password)) {
806
- ESP_LOGE(TAG, "AP password too long");
807
- return false;
808
- }
809
- memcpy(reinterpret_cast<char *>(conf.ap.password), ap.get_password().c_str(), ap.get_password().size());
810
- }
811
-
812
- // pairwise cipher of SoftAP, group cipher will be derived using this.
813
- conf.ap.pairwise_cipher = WIFI_CIPHER_TYPE_CCMP;
814
-
815
- esp_err_t err = esp_wifi_set_config(WIFI_IF_AP, &conf);
816
- if (err != ESP_OK) {
817
- ESP_LOGV(TAG, "esp_wifi_set_config failed: %d", err);
818
- return false;
819
- }
820
-
821
- yield();
822
-
823
- if (!this->wifi_ap_ip_config_(ap.get_manual_ip())) {
824
- ESP_LOGV(TAG, "wifi_ap_ip_config_ failed");
825
- return false;
826
- }
827
-
828
- return true;
829
- }
830
-
831
- network::IPAddress WiFiComponent::wifi_soft_ap_ip() {
832
- esp_netif_ip_info_t ip;
833
- esp_netif_get_ip_info(s_ap_netif, &ip);
834
- return network::IPAddress(&ip.ip);
835
- }
836
- #endif // USE_WIFI_AP
837
-
838
- bool WiFiComponent::wifi_disconnect_() { return esp_wifi_disconnect(); }
839
-
840
- bssid_t WiFiComponent::wifi_bssid() {
841
- bssid_t bssid{};
842
- uint8_t *raw_bssid = WiFi.BSSID();
843
- if (raw_bssid != nullptr) {
844
- for (size_t i = 0; i < bssid.size(); i++)
845
- bssid[i] = raw_bssid[i];
846
- }
847
- return bssid;
848
- }
849
- std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); }
850
- int8_t WiFiComponent::wifi_rssi() { return WiFi.RSSI(); }
851
- int32_t WiFiComponent::get_wifi_channel() { return WiFi.channel(); }
852
- network::IPAddress WiFiComponent::wifi_subnet_mask_() { return network::IPAddress(WiFi.subnetMask()); }
853
- network::IPAddress WiFiComponent::wifi_gateway_ip_() { return network::IPAddress(WiFi.gatewayIP()); }
854
- network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return network::IPAddress(WiFi.dnsIP(num)); }
855
-
856
- } // namespace wifi
857
- } // namespace esphome
858
-
859
- #endif // USE_ESP32_FRAMEWORK_ARDUINO
860
- #endif