esphome 2024.10.3__py3-none-any.whl → 2024.11.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 (228) hide show
  1. esphome/__main__.py +22 -4
  2. esphome/automation.py +29 -2
  3. esphome/components/animation/__init__.py +5 -8
  4. esphome/components/animation/animation.cpp +1 -1
  5. esphome/components/audio/__init__.py +9 -0
  6. esphome/components/audio/audio.h +21 -0
  7. esphome/components/axs15231/__init__.py +6 -0
  8. esphome/components/axs15231/touchscreen/__init__.py +36 -0
  9. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +64 -0
  10. esphome/components/axs15231/touchscreen/axs15231_touchscreen.h +27 -0
  11. esphome/components/bme68x_bsec2/__init__.py +1 -1
  12. esphome/components/bytebuffer/__init__.py +5 -0
  13. esphome/components/bytebuffer/bytebuffer.h +421 -0
  14. esphome/components/climate/__init__.py +14 -13
  15. esphome/components/datetime/__init__.py +3 -3
  16. esphome/components/debug/debug_esp32.cpp +16 -8
  17. esphome/components/dfplayer/dfplayer.cpp +132 -6
  18. esphome/components/dfplayer/dfplayer.h +19 -53
  19. esphome/components/display/display.cpp +142 -0
  20. esphome/components/display/display.h +7 -0
  21. esphome/components/es8311/__init__.py +0 -0
  22. esphome/components/es8311/audio_dac.py +70 -0
  23. esphome/components/es8311/es8311.cpp +227 -0
  24. esphome/components/es8311/es8311.h +135 -0
  25. esphome/components/es8311/es8311_const.h +195 -0
  26. esphome/components/esp32/boards.py +199 -1
  27. esphome/components/esp32/gpio.py +3 -1
  28. esphome/components/esp32_ble/const_esp32c6.h +7 -0
  29. esphome/components/esp32_ble_client/ble_client_base.h +1 -1
  30. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -1
  31. esphome/components/esp32_rmt_led_strip/led_strip.cpp +2 -2
  32. esphome/components/esp32_rmt_led_strip/led_strip.h +2 -0
  33. esphome/components/esp32_rmt_led_strip/light.py +3 -1
  34. esphome/components/esp8266/gpio.py +7 -5
  35. esphome/components/ethernet/__init__.py +55 -1
  36. esphome/components/ethernet/ethernet_component.cpp +14 -1
  37. esphome/components/ethernet/ethernet_component.h +7 -1
  38. esphome/components/font/__init__.py +213 -108
  39. esphome/components/gp8403/output/__init__.py +1 -1
  40. esphome/components/host/gpio.py +6 -4
  41. esphome/components/http_request/__init__.py +12 -0
  42. esphome/components/http_request/http_request.h +65 -3
  43. esphome/components/http_request/http_request_arduino.cpp +2 -3
  44. esphome/components/http_request/http_request_idf.cpp +6 -14
  45. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  46. esphome/components/http_request/update/http_request_update.cpp +1 -1
  47. esphome/components/i2c_device/__init__.py +26 -0
  48. esphome/components/i2c_device/i2c_device.cpp +17 -0
  49. esphome/components/i2c_device/i2c_device.h +18 -0
  50. esphome/components/i2s_audio/__init__.py +1 -3
  51. esphome/components/i2s_audio/speaker/__init__.py +12 -4
  52. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +432 -197
  53. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +91 -32
  54. esphome/components/ili9xxx/display.py +5 -1
  55. esphome/components/image/__init__.py +5 -8
  56. esphome/components/image/image.cpp +14 -14
  57. esphome/components/image/image.h +20 -24
  58. esphome/components/internal_temperature/internal_temperature.cpp +51 -2
  59. esphome/components/internal_temperature/internal_temperature.h +1 -0
  60. esphome/components/libretiny/gpio.py +4 -2
  61. esphome/components/light/__init__.py +32 -1
  62. esphome/components/light/automation.py +39 -32
  63. esphome/components/light/effects.py +36 -36
  64. esphome/components/light/light_state.cpp +6 -16
  65. esphome/components/light/light_state.h +34 -0
  66. esphome/components/light/types.py +3 -1
  67. esphome/components/logger/logger_esp32.cpp +15 -0
  68. esphome/components/lvgl/__init__.py +202 -95
  69. esphome/components/lvgl/automation.py +42 -40
  70. esphome/components/lvgl/binary_sensor/__init__.py +8 -15
  71. esphome/components/lvgl/defines.py +14 -8
  72. esphome/components/lvgl/encoders.py +11 -8
  73. esphome/components/lvgl/keypads.py +77 -0
  74. esphome/components/lvgl/light/__init__.py +6 -8
  75. esphome/components/lvgl/lv_validation.py +2 -4
  76. esphome/components/lvgl/lvcode.py +3 -9
  77. esphome/components/lvgl/lvgl_esphome.cpp +210 -89
  78. esphome/components/lvgl/lvgl_esphome.h +113 -30
  79. esphome/components/lvgl/lvgl_proxy.h +17 -0
  80. esphome/components/lvgl/number/__init__.py +10 -15
  81. esphome/components/lvgl/schemas.py +4 -2
  82. esphome/components/lvgl/select/__init__.py +12 -37
  83. esphome/components/lvgl/select/lvgl_select.h +27 -33
  84. esphome/components/lvgl/sensor/__init__.py +8 -14
  85. esphome/components/lvgl/styles.py +3 -4
  86. esphome/components/lvgl/switch/__init__.py +8 -13
  87. esphome/components/lvgl/text/__init__.py +5 -6
  88. esphome/components/lvgl/text_sensor/__init__.py +15 -15
  89. esphome/components/lvgl/touchscreens.py +2 -3
  90. esphome/components/lvgl/trigger.py +7 -9
  91. esphome/components/lvgl/types.py +9 -3
  92. esphome/components/lvgl/widgets/__init__.py +32 -21
  93. esphome/components/lvgl/widgets/dropdown.py +22 -10
  94. esphome/components/lvgl/widgets/msgbox.py +6 -5
  95. esphome/components/lvgl/widgets/obj.py +4 -2
  96. esphome/components/lvgl/widgets/page.py +3 -2
  97. esphome/components/lvgl/widgets/qrcode.py +54 -0
  98. esphome/components/lvgl/widgets/roller.py +21 -14
  99. esphome/components/lvgl/widgets/tileview.py +2 -1
  100. esphome/components/max17043/__init__.py +1 -0
  101. esphome/components/max17043/automation.h +20 -0
  102. esphome/components/max17043/max17043.cpp +98 -0
  103. esphome/components/max17043/max17043.h +29 -0
  104. esphome/components/max17043/sensor.py +77 -0
  105. esphome/components/media_player/__init__.py +11 -0
  106. esphome/components/media_player/automation.h +10 -0
  107. esphome/components/media_player/media_player.cpp +4 -0
  108. esphome/components/midea/air_conditioner.cpp +17 -1
  109. esphome/components/mlx90393/sensor.py +1 -1
  110. esphome/components/modbus_controller/__init__.py +31 -1
  111. esphome/components/modbus_controller/automation.h +16 -0
  112. esphome/components/modbus_controller/const.py +2 -0
  113. esphome/components/modbus_controller/modbus_controller.cpp +14 -2
  114. esphome/components/modbus_controller/modbus_controller.h +9 -0
  115. esphome/components/mopeka_pro_check/mopeka_pro_check.cpp +40 -21
  116. esphome/components/mopeka_pro_check/mopeka_pro_check.h +9 -2
  117. esphome/components/mopeka_pro_check/sensor.py +41 -0
  118. esphome/components/mqtt/__init__.py +36 -0
  119. esphome/components/mqtt/mqtt_client.cpp +27 -3
  120. esphome/components/mqtt/mqtt_client.h +27 -2
  121. esphome/components/mqtt/mqtt_climate.cpp +4 -2
  122. esphome/components/mqtt/mqtt_component.cpp +6 -0
  123. esphome/components/mqtt/mqtt_component.h +4 -0
  124. esphome/components/mqtt/mqtt_const.h +6 -0
  125. esphome/components/online_image/online_image.cpp +2 -8
  126. esphome/components/online_image/online_image.h +2 -6
  127. esphome/components/opentherm/__init__.py +35 -9
  128. esphome/components/opentherm/binary_sensor/__init__.py +33 -0
  129. esphome/components/opentherm/const.py +11 -0
  130. esphome/components/opentherm/generate.py +142 -0
  131. esphome/components/opentherm/hub.cpp +130 -24
  132. esphome/components/opentherm/hub.h +62 -9
  133. esphome/components/opentherm/input.h +18 -0
  134. esphome/components/opentherm/input.py +51 -0
  135. esphome/components/opentherm/number/__init__.py +74 -0
  136. esphome/components/opentherm/number/number.cpp +40 -0
  137. esphome/components/opentherm/number/number.h +31 -0
  138. esphome/components/opentherm/opentherm.cpp +30 -0
  139. esphome/components/opentherm/opentherm.h +34 -2
  140. esphome/components/opentherm/opentherm_macros.h +151 -0
  141. esphome/components/opentherm/output/__init__.py +47 -0
  142. esphome/components/opentherm/output/output.cpp +18 -0
  143. esphome/components/opentherm/output/output.h +33 -0
  144. esphome/components/opentherm/schema.py +814 -0
  145. esphome/components/opentherm/sensor/__init__.py +51 -0
  146. esphome/components/opentherm/switch/__init__.py +43 -0
  147. esphome/components/opentherm/switch/switch.cpp +28 -0
  148. esphome/components/opentherm/switch/switch.h +20 -0
  149. esphome/components/opentherm/validate.py +31 -0
  150. esphome/components/pcd8544/display.py +8 -4
  151. esphome/components/prometheus/prometheus_handler.cpp +176 -14
  152. esphome/components/prometheus/prometheus_handler.h +25 -7
  153. esphome/components/qspi_amoled/display.py +1 -141
  154. esphome/components/qspi_dbi/display.py +185 -0
  155. esphome/components/qspi_dbi/models.py +64 -0
  156. esphome/components/{qspi_amoled/qspi_amoled.cpp → qspi_dbi/qspi_dbi.cpp} +95 -46
  157. esphome/components/{qspi_amoled/qspi_amoled.h → qspi_dbi/qspi_dbi.h} +26 -15
  158. esphome/components/rp2040/__init__.py +6 -3
  159. esphome/components/rp2040/gpio.py +5 -3
  160. esphome/components/rtttl/rtttl.cpp +4 -1
  161. esphome/components/rtttl/rtttl.h +1 -0
  162. esphome/components/sdl/sdl_esphome.cpp +22 -5
  163. esphome/components/sdl/sdl_esphome.h +1 -0
  164. esphome/components/sensor/__init__.py +18 -8
  165. esphome/components/sensor/filter.cpp +19 -18
  166. esphome/components/sensor/filter.h +9 -10
  167. esphome/components/sgp4x/sgp4x.cpp +40 -74
  168. esphome/components/sgp4x/sgp4x.h +5 -3
  169. esphome/components/speaker/__init__.py +51 -5
  170. esphome/components/speaker/automation.h +25 -0
  171. esphome/components/speaker/speaker.h +72 -1
  172. esphome/components/spi/__init__.py +15 -14
  173. esphome/components/spi_device/__init__.py +4 -15
  174. esphome/components/ssd1306_spi/display.py +6 -2
  175. esphome/components/ssd1322_spi/display.py +6 -2
  176. esphome/components/ssd1325_spi/display.py +6 -2
  177. esphome/components/ssd1327_spi/display.py +6 -2
  178. esphome/components/ssd1331_spi/display.py +6 -2
  179. esphome/components/ssd1351_spi/display.py +6 -2
  180. esphome/components/st7567_spi/display.py +6 -2
  181. esphome/components/st7701s/display.py +5 -1
  182. esphome/components/st7735/display.py +10 -5
  183. esphome/components/st7789v/display.py +12 -7
  184. esphome/components/statsd/statsd.cpp +2 -0
  185. esphome/components/statsd/statsd.h +2 -0
  186. esphome/components/sun/sun.h +3 -0
  187. esphome/components/tc74/__init__.py +1 -0
  188. esphome/components/tc74/sensor.py +32 -0
  189. esphome/components/tc74/tc74.cpp +68 -0
  190. esphome/components/tc74/tc74.h +28 -0
  191. esphome/components/touchscreen/__init__.py +41 -50
  192. esphome/components/touchscreen/touchscreen.h +4 -8
  193. esphome/components/udp/udp_component.cpp +6 -3
  194. esphome/components/udp/udp_component.h +4 -2
  195. esphome/components/waveshare_epaper/display.py +6 -2
  196. esphome/components/web_server/web_server.cpp +22 -0
  197. esphome/components/web_server/web_server.h +3 -0
  198. esphome/components/weikai/weikai.h +2 -2
  199. esphome/components/wifi/wifi_component.cpp +2 -2
  200. esphome/components/wifi/wifi_component_esp32_arduino.cpp +4 -4
  201. esphome/components/wifi/wifi_component_esp8266.cpp +4 -4
  202. esphome/components/wifi/wifi_component_esp_idf.cpp +2 -2
  203. esphome/components/xpt2046/touchscreen/__init__.py +7 -32
  204. esphome/config_validation.py +3 -1
  205. esphome/const.py +8 -1
  206. esphome/core/defines.h +8 -2
  207. esphome/core/helpers.cpp +32 -17
  208. esphome/core/helpers.h +32 -16
  209. esphome/core/ring_buffer.cpp +2 -2
  210. esphome/core/ring_buffer.h +2 -2
  211. esphome/dashboard/core.py +25 -0
  212. esphome/dashboard/status/mdns.py +3 -4
  213. esphome/dashboard/web_server.py +54 -19
  214. esphome/espota2.py +36 -35
  215. esphome/helpers.py +68 -16
  216. esphome/mqtt.py +9 -2
  217. esphome/storage_json.py +4 -0
  218. esphome/writer.py +7 -18
  219. esphome/zeroconf.py +8 -6
  220. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/METADATA +7 -5
  221. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/RECORD +226 -180
  222. esphome/core/bytebuffer.cpp +0 -167
  223. esphome/core/bytebuffer.h +0 -144
  224. /esphome/components/{qspi_amoled → qspi_dbi}/__init__.py +0 -0
  225. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/LICENSE +0 -0
  226. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/WHEEL +0 -0
  227. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/entry_points.txt +0 -0
  228. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/top_level.txt +0 -0
@@ -137,8 +137,8 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
137
137
  // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#_CPPv417wifi_sta_config_t
138
138
  wifi_config_t conf;
139
139
  memset(&conf, 0, sizeof(conf));
140
- strncpy(reinterpret_cast<char *>(conf.sta.ssid), ap.get_ssid().c_str(), sizeof(conf.sta.ssid));
141
- strncpy(reinterpret_cast<char *>(conf.sta.password), ap.get_password().c_str(), sizeof(conf.sta.password));
140
+ snprintf(reinterpret_cast<char *>(conf.sta.ssid), sizeof(conf.sta.ssid), "%s", ap.get_ssid().c_str());
141
+ snprintf(reinterpret_cast<char *>(conf.sta.password), sizeof(conf.sta.password), "%s", ap.get_password().c_str());
142
142
 
143
143
  // The weakest authmode to accept in the fast scan mode
144
144
  if (ap.get_password().empty()) {
@@ -746,7 +746,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) {
746
746
 
747
747
  wifi_config_t conf;
748
748
  memset(&conf, 0, sizeof(conf));
749
- strncpy(reinterpret_cast<char *>(conf.ap.ssid), ap.get_ssid().c_str(), sizeof(conf.ap.ssid));
749
+ snprintf(reinterpret_cast<char *>(conf.ap.ssid), sizeof(conf.ap.ssid), "%s", ap.get_ssid().c_str());
750
750
  conf.ap.channel = ap.get_channel().value_or(1);
751
751
  conf.ap.ssid_hidden = ap.get_ssid().size();
752
752
  conf.ap.max_connection = 5;
@@ -757,7 +757,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) {
757
757
  *conf.ap.password = 0;
758
758
  } else {
759
759
  conf.ap.authmode = WIFI_AUTH_WPA2_PSK;
760
- strncpy(reinterpret_cast<char *>(conf.ap.password), ap.get_password().c_str(), sizeof(conf.ap.password));
760
+ snprintf(reinterpret_cast<char *>(conf.ap.password), sizeof(conf.ap.password), "%s", ap.get_password().c_str());
761
761
  }
762
762
 
763
763
  // pairwise cipher of SoftAP, group cipher will be derived using this.
@@ -236,8 +236,8 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
236
236
 
237
237
  struct station_config conf {};
238
238
  memset(&conf, 0, sizeof(conf));
239
- strncpy(reinterpret_cast<char *>(conf.ssid), ap.get_ssid().c_str(), sizeof(conf.ssid));
240
- strncpy(reinterpret_cast<char *>(conf.password), ap.get_password().c_str(), sizeof(conf.password));
239
+ snprintf(reinterpret_cast<char *>(conf.ssid), sizeof(conf.ssid), "%s", ap.get_ssid().c_str());
240
+ snprintf(reinterpret_cast<char *>(conf.password), sizeof(conf.password), "%s", ap.get_password().c_str());
241
241
 
242
242
  if (ap.get_bssid().has_value()) {
243
243
  conf.bssid_set = 1;
@@ -775,7 +775,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) {
775
775
  return false;
776
776
 
777
777
  struct softap_config conf {};
778
- strncpy(reinterpret_cast<char *>(conf.ssid), ap.get_ssid().c_str(), sizeof(conf.ssid));
778
+ snprintf(reinterpret_cast<char *>(conf.ssid), sizeof(conf.ssid), "%s", ap.get_ssid().c_str());
779
779
  conf.ssid_len = static_cast<uint8>(ap.get_ssid().size());
780
780
  conf.channel = ap.get_channel().value_or(1);
781
781
  conf.ssid_hidden = ap.get_hidden();
@@ -787,7 +787,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) {
787
787
  *conf.password = 0;
788
788
  } else {
789
789
  conf.authmode = AUTH_WPA2_PSK;
790
- strncpy(reinterpret_cast<char *>(conf.password), ap.get_password().c_str(), sizeof(conf.password));
790
+ snprintf(reinterpret_cast<char *>(conf.password), sizeof(conf.password), "%s", ap.get_password().c_str());
791
791
  }
792
792
 
793
793
  ETS_UART_INTR_DISABLE();
@@ -289,8 +289,8 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
289
289
  // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#_CPPv417wifi_sta_config_t
290
290
  wifi_config_t conf;
291
291
  memset(&conf, 0, sizeof(conf));
292
- strncpy(reinterpret_cast<char *>(conf.sta.ssid), ap.get_ssid().c_str(), sizeof(conf.sta.ssid));
293
- strncpy(reinterpret_cast<char *>(conf.sta.password), ap.get_password().c_str(), sizeof(conf.sta.password));
292
+ snprintf(reinterpret_cast<char *>(conf.sta.ssid), sizeof(conf.sta.ssid), "%s", ap.get_ssid().c_str());
293
+ snprintf(reinterpret_cast<char *>(conf.sta.password), sizeof(conf.sta.password), "%s", ap.get_password().c_str());
294
294
 
295
295
  // The weakest authmode to accept in the fast scan mode
296
296
  if (ap.get_password().empty()) {
@@ -1,9 +1,8 @@
1
- import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
-
4
1
  from esphome import pins
2
+ import esphome.codegen as cg
5
3
  from esphome.components import spi, touchscreen
6
- from esphome.const import CONF_ID, CONF_THRESHOLD, CONF_INTERRUPT_PIN
4
+ import esphome.config_validation as cv
5
+ from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_THRESHOLD
7
6
 
8
7
  CODEOWNERS = ["@numo68", "@nielsnl68"]
9
8
  DEPENDENCIES = ["spi"]
@@ -15,13 +14,9 @@ XPT2046Component = XPT2046_ns.class_(
15
14
  spi.SPIDevice,
16
15
  )
17
16
 
18
- CONF_CALIBRATION_X_MIN = "calibration_x_min"
19
- CONF_CALIBRATION_X_MAX = "calibration_x_max"
20
- CONF_CALIBRATION_Y_MIN = "calibration_y_min"
21
- CONF_CALIBRATION_Y_MAX = "calibration_y_max"
22
-
23
17
  CONFIG_SCHEMA = cv.All(
24
- touchscreen.TOUCHSCREEN_SCHEMA.extend(
18
+ touchscreen.touchscreen_schema(calibration_required=True)
19
+ .extend(
25
20
  cv.Schema(
26
21
  {
27
22
  cv.GenerateID(): cv.declare_id(XPT2046Component),
@@ -29,30 +24,10 @@ CONFIG_SCHEMA = cv.All(
29
24
  pins.internal_gpio_input_pin_schema
30
25
  ),
31
26
  cv.Optional(CONF_THRESHOLD, default=400): cv.int_range(min=0, max=4095),
32
- cv.Optional(
33
- touchscreen.CONF_CALIBRATION
34
- ): touchscreen.calibration_schema(4095),
35
- cv.Optional(CONF_CALIBRATION_X_MIN): cv.invalid(
36
- "Deprecated: use the new 'calibration' configuration variable"
37
- ),
38
- cv.Optional(CONF_CALIBRATION_X_MAX): cv.invalid(
39
- "Deprecated: use the new 'calibration' configuration variable"
40
- ),
41
- cv.Optional(CONF_CALIBRATION_Y_MIN): cv.invalid(
42
- "Deprecated: use the new 'calibration' configuration variable"
43
- ),
44
- cv.Optional(CONF_CALIBRATION_Y_MAX): cv.invalid(
45
- "Deprecated: use the new 'calibration' configuration variable"
46
- ),
47
- cv.Optional(CONF_CALIBRATION_Y_MAX): cv.invalid(
48
- "Deprecated: use the new 'calibration' configuration variable"
49
- ),
50
- cv.Optional("report_interval"): cv.invalid(
51
- "Deprecated: use the 'update_interval' configuration variable"
52
- ),
53
27
  },
54
28
  )
55
- ).extend(spi.spi_device_schema()),
29
+ )
30
+ .extend(spi.spi_device_schema()),
56
31
  )
57
32
 
58
33
 
@@ -40,6 +40,7 @@ from esphome.const import (
40
40
  CONF_SECOND,
41
41
  CONF_SETUP_PRIORITY,
42
42
  CONF_STATE_TOPIC,
43
+ CONF_SUBSCRIBE_QOS,
43
44
  CONF_TOPIC,
44
45
  CONF_TYPE,
45
46
  CONF_TYPE_ID,
@@ -1893,9 +1894,10 @@ MQTT_COMPONENT_AVAILABILITY_SCHEMA = Schema(
1893
1894
 
1894
1895
  MQTT_COMPONENT_SCHEMA = Schema(
1895
1896
  {
1896
- Optional(CONF_QOS): All(requires_component("mqtt"), int_range(min=0, max=2)),
1897
+ Optional(CONF_QOS): All(requires_component("mqtt"), mqtt_qos),
1897
1898
  Optional(CONF_RETAIN): All(requires_component("mqtt"), boolean),
1898
1899
  Optional(CONF_DISCOVERY): All(requires_component("mqtt"), boolean),
1900
+ Optional(CONF_SUBSCRIBE_QOS): All(requires_component("mqtt"), mqtt_qos),
1899
1901
  Optional(CONF_STATE_TOPIC): All(requires_component("mqtt"), publish_topic),
1900
1902
  Optional(CONF_AVAILABILITY): All(
1901
1903
  requires_component("mqtt"), Any(None, MQTT_COMPONENT_AVAILABILITY_SCHEMA)
esphome/const.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Constants used by esphome."""
2
2
 
3
- __version__ = "2024.10.3"
3
+ __version__ = "2024.11.0b1"
4
4
 
5
5
  ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
6
6
  VALID_SUBSTITUTIONS_CHARACTERS = (
@@ -49,6 +49,7 @@ CONF_ADDRESS = "address"
49
49
  CONF_ADDRESSABLE_LIGHT_ID = "addressable_light_id"
50
50
  CONF_ADVANCED = "advanced"
51
51
  CONF_AFTER = "after"
52
+ CONF_ALL = "all"
52
53
  CONF_ALLOW_OTHER_USES = "allow_other_uses"
53
54
  CONF_ALPHA = "alpha"
54
55
  CONF_ALTITUDE = "altitude"
@@ -57,6 +58,7 @@ CONF_AMMONIA = "ammonia"
57
58
  CONF_ANALOG = "analog"
58
59
  CONF_AND = "and"
59
60
  CONF_ANGLE = "angle"
61
+ CONF_ANY = "any"
60
62
  CONF_AP = "ap"
61
63
  CONF_APPARENT_POWER = "apparent_power"
62
64
  CONF_ARDUINO_VERSION = "arduino_version"
@@ -90,6 +92,7 @@ CONF_BINARY_SENSORS = "binary_sensors"
90
92
  CONF_BINDKEY = "bindkey"
91
93
  CONF_BIRTH_MESSAGE = "birth_message"
92
94
  CONF_BIT_DEPTH = "bit_depth"
95
+ CONF_BITS_PER_SAMPLE = "bits_per_sample"
93
96
  CONF_BLOCK = "block"
94
97
  CONF_BLUE = "blue"
95
98
  CONF_BOARD = "board"
@@ -396,8 +399,10 @@ CONF_INCLUDES = "includes"
396
399
  CONF_INDEX = "index"
397
400
  CONF_INDOOR = "indoor"
398
401
  CONF_INFRARED = "infrared"
402
+ CONF_INIT_SEQUENCE = "init_sequence"
399
403
  CONF_INITIAL_MODE = "initial_mode"
400
404
  CONF_INITIAL_OPTION = "initial_option"
405
+ CONF_INITIAL_STATE = "initial_state"
401
406
  CONF_INITIAL_VALUE = "initial_value"
402
407
  CONF_INPUT = "input"
403
408
  CONF_INTEGRATION_TIME = "integration_time"
@@ -662,6 +667,7 @@ CONF_PMC_1_0 = "pmc_1_0"
662
667
  CONF_PMC_10_0 = "pmc_10_0"
663
668
  CONF_PMC_2_5 = "pmc_2_5"
664
669
  CONF_PMC_4_0 = "pmc_4_0"
670
+ CONF_POLLING_INTERVAL = "polling_interval"
665
671
  CONF_PORT = "port"
666
672
  CONF_POSITION = "position"
667
673
  CONF_POSITION_ACTION = "position_action"
@@ -815,6 +821,7 @@ CONF_STOP = "stop"
815
821
  CONF_STOP_ACTION = "stop_action"
816
822
  CONF_STORE_BASELINE = "store_baseline"
817
823
  CONF_SUBNET = "subnet"
824
+ CONF_SUBSCRIBE_QOS = "subscribe_qos"
818
825
  CONF_SUBSTITUTIONS = "substitutions"
819
826
  CONF_SUM = "sum"
820
827
  CONF_SUPPLEMENTAL_COOLING_ACTION = "supplemental_cooling_action"
esphome/core/defines.h CHANGED
@@ -44,10 +44,12 @@
44
44
  #define USE_LVGL_ANIMIMG
45
45
  #define USE_LVGL_BINARY_SENSOR
46
46
  #define USE_LVGL_BUTTONMATRIX
47
+ #define USE_LVGL_DROPDOWN
47
48
  #define USE_LVGL_FONT
48
49
  #define USE_LVGL_IMAGE
49
50
  #define USE_LVGL_KEY_LISTENER
50
51
  #define USE_LVGL_KEYBOARD
52
+ #define USE_LVGL_ROLLER
51
53
  #define USE_LVGL_ROTARY_ENCODER
52
54
  #define USE_LVGL_TOUCHSCREEN
53
55
  #define USE_MD5
@@ -84,8 +86,6 @@
84
86
  #ifdef USE_ARDUINO
85
87
  #define USE_CAPTIVE_PORTAL
86
88
  #define USE_PROMETHEUS
87
- #define USE_WEBSERVER
88
- #define USE_WEBSERVER_PORT 80 // NOLINT
89
89
  #define USE_WIFI_WPA2_EAP
90
90
  #endif
91
91
 
@@ -109,6 +109,8 @@
109
109
  #define USE_SPEAKER
110
110
  #define USE_SPI
111
111
  #define USE_VOICE_ASSISTANT
112
+ #define USE_WEBSERVER
113
+ #define USE_WEBSERVER_PORT 80 // NOLINT
112
114
  #define USE_WIFI_11KV_SUPPORT
113
115
 
114
116
  #ifdef USE_ARDUINO
@@ -145,6 +147,8 @@
145
147
  #define USE_SHD_FIRMWARE_DATA \
146
148
  {}
147
149
 
150
+ #define USE_WEBSERVER
151
+ #define USE_WEBSERVER_PORT 80 // NOLINT
148
152
  #endif
149
153
 
150
154
  #ifdef USE_RP2040
@@ -156,6 +160,8 @@
156
160
 
157
161
  #ifdef USE_LIBRETINY
158
162
  #define USE_SOCKET_IMPL_LWIP_SOCKETS
163
+ #define USE_WEBSERVER
164
+ #define USE_WEBSERVER_PORT 80 // NOLINT
159
165
  #endif
160
166
 
161
167
  #ifdef USE_HOST
esphome/core/helpers.cpp CHANGED
@@ -10,6 +10,7 @@
10
10
  #include <cstdarg>
11
11
  #include <cstdio>
12
12
  #include <cstring>
13
+ #include <strings.h>
13
14
 
14
15
  #ifdef USE_HOST
15
16
  #ifndef _WIN32
@@ -188,37 +189,39 @@ uint32_t fnv1_hash(const std::string &str) {
188
189
  return hash;
189
190
  }
190
191
 
191
- uint32_t random_uint32() {
192
192
  #ifdef USE_ESP32
193
- return esp_random();
193
+ uint32_t random_uint32() { return esp_random(); }
194
194
  #elif defined(USE_ESP8266)
195
- return os_random();
195
+ uint32_t random_uint32() { return os_random(); }
196
196
  #elif defined(USE_RP2040)
197
+ uint32_t random_uint32() {
197
198
  uint32_t result = 0;
198
199
  for (uint8_t i = 0; i < 32; i++) {
199
200
  result <<= 1;
200
201
  result |= rosc_hw->randombit;
201
202
  }
202
203
  return result;
204
+ }
203
205
  #elif defined(USE_LIBRETINY)
204
- return rand();
206
+ uint32_t random_uint32() { return rand(); }
205
207
  #elif defined(USE_HOST)
208
+ uint32_t random_uint32() {
206
209
  std::random_device dev;
207
210
  std::mt19937 rng(dev());
208
211
  std::uniform_int_distribution<uint32_t> dist(0, std::numeric_limits<uint32_t>::max());
209
212
  return dist(rng);
210
- #else
211
- #error "No random source available for this configuration."
212
- #endif
213
213
  }
214
+ #endif
214
215
  float random_float() { return static_cast<float>(random_uint32()) / static_cast<float>(UINT32_MAX); }
215
- bool random_bytes(uint8_t *data, size_t len) {
216
216
  #ifdef USE_ESP32
217
+ bool random_bytes(uint8_t *data, size_t len) {
217
218
  esp_fill_random(data, len);
218
219
  return true;
220
+ }
219
221
  #elif defined(USE_ESP8266)
220
- return os_get_random(data, len) == 0;
222
+ bool random_bytes(uint8_t *data, size_t len) { return os_get_random(data, len) == 0; }
221
223
  #elif defined(USE_RP2040)
224
+ bool random_bytes(uint8_t *data, size_t len) {
222
225
  while (len-- != 0) {
223
226
  uint8_t result = 0;
224
227
  for (uint8_t i = 0; i < 8; i++) {
@@ -228,10 +231,14 @@ bool random_bytes(uint8_t *data, size_t len) {
228
231
  *data++ = result;
229
232
  }
230
233
  return true;
234
+ }
231
235
  #elif defined(USE_LIBRETINY)
236
+ bool random_bytes(uint8_t *data, size_t len) {
232
237
  lt_rand_bytes(data, len);
233
238
  return true;
239
+ }
234
240
  #elif defined(USE_HOST)
241
+ bool random_bytes(uint8_t *data, size_t len) {
235
242
  FILE *fp = fopen("/dev/urandom", "r");
236
243
  if (fp == nullptr) {
237
244
  ESP_LOGW(TAG, "Could not open /dev/urandom, errno=%d", errno);
@@ -244,10 +251,8 @@ bool random_bytes(uint8_t *data, size_t len) {
244
251
  }
245
252
  fclose(fp);
246
253
  return true;
247
- #else
248
- #error "No random source available for this configuration."
249
- #endif
250
254
  }
255
+ #endif
251
256
 
252
257
  // Strings
253
258
 
@@ -619,11 +624,13 @@ void hsv_to_rgb(int hue, float saturation, float value, float &red, float &green
619
624
  #if defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_HOST)
620
625
  // ESP8266 doesn't have mutexes, but that shouldn't be an issue as it's single-core and non-preemptive OS.
621
626
  Mutex::Mutex() {}
627
+ Mutex::~Mutex() {}
622
628
  void Mutex::lock() {}
623
629
  bool Mutex::try_lock() { return true; }
624
630
  void Mutex::unlock() {}
625
631
  #elif defined(USE_ESP32) || defined(USE_LIBRETINY)
626
632
  Mutex::Mutex() { handle_ = xSemaphoreCreateMutex(); }
633
+ Mutex::~Mutex() {}
627
634
  void Mutex::lock() { xSemaphoreTake(this->handle_, portMAX_DELAY); }
628
635
  bool Mutex::try_lock() { return xSemaphoreTake(this->handle_, 0) == pdTRUE; }
629
636
  void Mutex::unlock() { xSemaphoreGive(this->handle_); }
@@ -657,11 +664,13 @@ void HighFrequencyLoopRequester::stop() {
657
664
  }
658
665
  bool HighFrequencyLoopRequester::is_high_frequency() { return num_requests > 0; }
659
666
 
660
- void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter)
661
667
  #if defined(USE_HOST)
668
+ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter)
662
669
  static const uint8_t esphome_host_mac_address[6] = USE_ESPHOME_HOST_MAC_ADDRESS;
663
670
  memcpy(mac, esphome_host_mac_address, sizeof(esphome_host_mac_address));
671
+ }
664
672
  #elif defined(USE_ESP32)
673
+ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter)
665
674
  #if defined(CONFIG_SOC_IEEE802154_SUPPORTED)
666
675
  // When CONFIG_SOC_IEEE802154_SUPPORTED is defined, esp_efuse_mac_get_default
667
676
  // returns the 802.15.4 EUI-64 address, so we read directly from eFuse instead.
@@ -677,16 +686,22 @@ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parame
677
686
  esp_efuse_mac_get_default(mac);
678
687
  }
679
688
  #endif
689
+ }
680
690
  #elif defined(USE_ESP8266)
691
+ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter)
681
692
  wifi_get_macaddr(STATION_IF, mac);
682
- #elif defined(USE_RP2040) && defined(USE_WIFI)
693
+ }
694
+ #elif defined(USE_RP2040)
695
+ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter)
696
+ #ifdef USE_WIFI
683
697
  WiFi.macAddress(mac);
698
+ #endif
699
+ }
684
700
  #elif defined(USE_LIBRETINY)
701
+ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter)
685
702
  WiFi.macAddress(mac);
686
- #else
687
- // this should be an error, but that messes with CI checks. #error No mac address method defined
688
- #endif
689
703
  }
704
+ #endif
690
705
 
691
706
  std::string get_mac_address() {
692
707
  uint8_t mac[6];
esphome/core/helpers.h CHANGED
@@ -7,6 +7,7 @@
7
7
  #include <string>
8
8
  #include <type_traits>
9
9
  #include <vector>
10
+ #include <limits>
10
11
 
11
12
  #include "esphome/core/optional.h"
12
13
 
@@ -545,6 +546,7 @@ class Mutex {
545
546
  public:
546
547
  Mutex();
547
548
  Mutex(const Mutex &) = delete;
549
+ ~Mutex();
548
550
  void lock();
549
551
  bool try_lock();
550
552
  void unlock();
@@ -554,6 +556,8 @@ class Mutex {
554
556
  private:
555
557
  #if defined(USE_ESP32) || defined(USE_LIBRETINY)
556
558
  SemaphoreHandle_t handle_;
559
+ #else
560
+ void *handle_; // d-pointer to store private data on new platforms
557
561
  #endif
558
562
  };
559
563
 
@@ -651,35 +655,45 @@ void delay_microseconds_safe(uint32_t us);
651
655
  /// @name Memory management
652
656
  ///@{
653
657
 
654
- /** An STL allocator that uses SPI RAM.
658
+ /** An STL allocator that uses SPI or internal RAM.
659
+ * Returns `nullptr` in case no memory is available.
655
660
  *
656
- * By setting flags, it can be configured to don't try main memory if SPI RAM is full or unavailable, and to return
657
- * `nulllptr` instead of aborting when no memory is available.
661
+ * By setting flags, it can be configured to:
662
+ * - perform external allocation falling back to main memory if SPI RAM is full or unavailable
663
+ * - perform external allocation only
664
+ * - perform internal allocation only
658
665
  */
659
- template<class T> class ExternalRAMAllocator {
666
+ template<class T> class RAMAllocator {
660
667
  public:
661
668
  using value_type = T;
662
669
 
663
670
  enum Flags {
664
- NONE = 0,
665
- REFUSE_INTERNAL = 1 << 0, ///< Refuse falling back to internal memory when external RAM is full or unavailable.
666
- ALLOW_FAILURE = 1 << 1, ///< Don't abort when memory allocation fails.
671
+ NONE = 0, // Perform external allocation and fall back to internal memory
672
+ ALLOC_EXTERNAL = 1 << 0, // Perform external allocation only.
673
+ ALLOC_INTERNAL = 1 << 1, // Perform internal allocation only.
674
+ ALLOW_FAILURE = 1 << 2, // Does nothing. Kept for compatibility.
667
675
  };
668
676
 
669
- ExternalRAMAllocator() = default;
670
- ExternalRAMAllocator(Flags flags) : flags_{flags} {}
671
- template<class U> constexpr ExternalRAMAllocator(const ExternalRAMAllocator<U> &other) : flags_{other.flags_} {}
677
+ RAMAllocator() = default;
678
+ RAMAllocator(uint8_t flags) : flags_{flags} {}
679
+ template<class U> constexpr RAMAllocator(const RAMAllocator<U> &other) : flags_{other.flags_} {}
672
680
 
673
681
  T *allocate(size_t n) {
674
682
  size_t size = n * sizeof(T);
675
683
  T *ptr = nullptr;
676
684
  #ifdef USE_ESP32
677
- ptr = static_cast<T *>(heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
678
- #endif
679
- if (ptr == nullptr && (this->flags_ & Flags::REFUSE_INTERNAL) == 0)
685
+ // External allocation by default or if explicitely requested
686
+ if ((this->flags_ & Flags::ALLOC_EXTERNAL) || ((this->flags_ & Flags::ALLOC_INTERNAL) == 0)) {
687
+ ptr = static_cast<T *>(heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
688
+ }
689
+ // Fallback to internal allocation if explicitely requested or no flag is specified
690
+ if (ptr == nullptr && ((this->flags_ & Flags::ALLOC_INTERNAL) || (this->flags_ & Flags::ALLOC_EXTERNAL) == 0)) {
680
691
  ptr = static_cast<T *>(malloc(size)); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
681
- if (ptr == nullptr && (this->flags_ & Flags::ALLOW_FAILURE) == 0)
682
- abort();
692
+ }
693
+ #else
694
+ // Ignore ALLOC_EXTERNAL/ALLOC_INTERNAL flags if external allocation is not supported
695
+ ptr = static_cast<T *>(malloc(size)); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
696
+ #endif
683
697
  return ptr;
684
698
  }
685
699
 
@@ -688,9 +702,11 @@ template<class T> class ExternalRAMAllocator {
688
702
  }
689
703
 
690
704
  private:
691
- Flags flags_{Flags::ALLOW_FAILURE};
705
+ uint8_t flags_{Flags::ALLOW_FAILURE};
692
706
  };
693
707
 
708
+ template<class T> using ExternalRAMAllocator = RAMAllocator<T>;
709
+
694
710
  /// @}
695
711
 
696
712
  /// @name Internal functions
@@ -46,7 +46,7 @@ size_t RingBuffer::read(void *data, size_t len, TickType_t ticks_to_wait) {
46
46
  return bytes_read;
47
47
  }
48
48
 
49
- size_t RingBuffer::write(void *data, size_t len) {
49
+ size_t RingBuffer::write(const void *data, size_t len) {
50
50
  size_t free = this->free();
51
51
  if (free < len) {
52
52
  size_t needed = len - free;
@@ -56,7 +56,7 @@ size_t RingBuffer::write(void *data, size_t len) {
56
56
  return xStreamBufferSend(this->handle_, data, len, 0);
57
57
  }
58
58
 
59
- size_t RingBuffer::write_without_replacement(void *data, size_t len, TickType_t ticks_to_wait) {
59
+ size_t RingBuffer::write_without_replacement(const void *data, size_t len, TickType_t ticks_to_wait) {
60
60
  return xStreamBufferSend(this->handle_, data, len, ticks_to_wait);
61
61
  }
62
62
 
@@ -37,7 +37,7 @@ class RingBuffer {
37
37
  * @param len Number of bytes to write
38
38
  * @return Number of bytes written
39
39
  */
40
- size_t write(void *data, size_t len);
40
+ size_t write(const void *data, size_t len);
41
41
 
42
42
  /**
43
43
  * @brief Writes to the ring buffer without overwriting oldest data.
@@ -50,7 +50,7 @@ class RingBuffer {
50
50
  * @param ticks_to_wait Maximum number of FreeRTOS ticks to wait (default: 0)
51
51
  * @return Number of bytes written
52
52
  */
53
- size_t write_without_replacement(void *data, size_t len, TickType_t ticks_to_wait = 0);
53
+ size_t write_without_replacement(const void *data, size_t len, TickType_t ticks_to_wait = 0);
54
54
 
55
55
  /**
56
56
  * @brief Returns the number of available bytes in the ring buffer.
esphome/dashboard/core.py CHANGED
@@ -5,10 +5,14 @@ from collections.abc import Coroutine
5
5
  import contextlib
6
6
  from dataclasses import dataclass
7
7
  from functools import partial
8
+ import json
8
9
  import logging
10
+ from pathlib import Path
9
11
  import threading
10
12
  from typing import TYPE_CHECKING, Any, Callable
11
13
 
14
+ from esphome.storage_json import ignored_devices_storage_path
15
+
12
16
  from ..zeroconf import DiscoveredImport
13
17
  from .dns import DNSCache
14
18
  from .entries import DashboardEntries
@@ -20,6 +24,8 @@ if TYPE_CHECKING:
20
24
 
21
25
  _LOGGER = logging.getLogger(__name__)
22
26
 
27
+ IGNORED_DEVICES_STORAGE_PATH = "ignored-devices.json"
28
+
23
29
 
24
30
  @dataclass
25
31
  class Event:
@@ -74,6 +80,7 @@ class ESPHomeDashboard:
74
80
  "settings",
75
81
  "dns_cache",
76
82
  "_background_tasks",
83
+ "ignored_devices",
77
84
  )
78
85
 
79
86
  def __init__(self) -> None:
@@ -89,12 +96,30 @@ class ESPHomeDashboard:
89
96
  self.settings = DashboardSettings()
90
97
  self.dns_cache = DNSCache()
91
98
  self._background_tasks: set[asyncio.Task] = set()
99
+ self.ignored_devices: set[str] = set()
92
100
 
93
101
  async def async_setup(self) -> None:
94
102
  """Setup the dashboard."""
95
103
  self.loop = asyncio.get_running_loop()
96
104
  self.ping_request = asyncio.Event()
97
105
  self.entries = DashboardEntries(self)
106
+ self.load_ignored_devices()
107
+
108
+ def load_ignored_devices(self) -> None:
109
+ storage_path = Path(ignored_devices_storage_path())
110
+ try:
111
+ with storage_path.open("r", encoding="utf-8") as f_handle:
112
+ data = json.load(f_handle)
113
+ self.ignored_devices = set(data.get("ignored_devices", set()))
114
+ except FileNotFoundError:
115
+ pass
116
+
117
+ def save_ignored_devices(self) -> None:
118
+ storage_path = Path(ignored_devices_storage_path())
119
+ with storage_path.open("w", encoding="utf-8") as f_handle:
120
+ json.dump(
121
+ {"ignored_devices": sorted(self.ignored_devices)}, indent=2, fp=f_handle
122
+ )
98
123
 
99
124
  async def async_run(self) -> None:
100
125
  """Run the dashboard."""
@@ -26,7 +26,7 @@ class MDNSStatus:
26
26
  self.host_mdns_state: dict[str, bool | None] = {}
27
27
  self._loop = asyncio.get_running_loop()
28
28
 
29
- async def async_resolve_host(self, host_name: str) -> str | None:
29
+ async def async_resolve_host(self, host_name: str) -> list[str] | None:
30
30
  """Resolve a host name to an address in a thread-safe manner."""
31
31
  if aiozc := self.aiozc:
32
32
  return await aiozc.async_resolve_host(host_name)
@@ -50,13 +50,12 @@ class MDNSStatus:
50
50
  poll_names.setdefault(entry.name, set()).add(entry)
51
51
  elif (online := host_mdns_state.get(entry.name, SENTINEL)) != SENTINEL:
52
52
  entries.async_set_state(entry, bool_to_entry_state(online))
53
-
54
53
  if poll_names and self.aiozc:
55
54
  results = await asyncio.gather(
56
55
  *(self.aiozc.async_resolve_host(name) for name in poll_names)
57
56
  )
58
- for name, address in zip(poll_names, results):
59
- result = bool(address)
57
+ for name, address_list in zip(poll_names, results):
58
+ result = bool(address_list)
60
59
  host_mdns_state[name] = result
61
60
  for entry in poll_names[name]:
62
61
  entries.async_set_state(entry, bool_to_entry_state(result))