esphome 2024.10.3__py3-none-any.whl → 2024.11.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 (234) 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/bme68x_bsec2/bme68x_bsec2.cpp +50 -47
  13. esphome/components/bme68x_bsec2/bme68x_bsec2.h +0 -2
  14. esphome/components/bytebuffer/__init__.py +5 -0
  15. esphome/components/bytebuffer/bytebuffer.h +421 -0
  16. esphome/components/climate/__init__.py +14 -13
  17. esphome/components/datetime/__init__.py +3 -3
  18. esphome/components/debug/debug_esp32.cpp +16 -8
  19. esphome/components/dfplayer/dfplayer.cpp +132 -6
  20. esphome/components/dfplayer/dfplayer.h +19 -53
  21. esphome/components/display/display.cpp +142 -0
  22. esphome/components/display/display.h +7 -0
  23. esphome/components/es8311/__init__.py +0 -0
  24. esphome/components/es8311/audio_dac.py +70 -0
  25. esphome/components/es8311/es8311.cpp +227 -0
  26. esphome/components/es8311/es8311.h +135 -0
  27. esphome/components/es8311/es8311_const.h +195 -0
  28. esphome/components/esp32/boards.py +199 -1
  29. esphome/components/esp32/gpio.py +3 -1
  30. esphome/components/esp32_ble/const_esp32c6.h +7 -0
  31. esphome/components/esp32_ble_client/ble_client_base.h +1 -1
  32. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +3 -0
  33. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -1
  34. esphome/components/esp32_rmt_led_strip/led_strip.cpp +2 -2
  35. esphome/components/esp32_rmt_led_strip/led_strip.h +2 -0
  36. esphome/components/esp32_rmt_led_strip/light.py +3 -1
  37. esphome/components/esp8266/gpio.py +7 -5
  38. esphome/components/ethernet/__init__.py +55 -1
  39. esphome/components/ethernet/ethernet_component.cpp +14 -1
  40. esphome/components/ethernet/ethernet_component.h +7 -1
  41. esphome/components/font/__init__.py +213 -108
  42. esphome/components/gp8403/output/__init__.py +1 -1
  43. esphome/components/host/gpio.py +6 -4
  44. esphome/components/http_request/__init__.py +12 -0
  45. esphome/components/http_request/http_request.h +65 -3
  46. esphome/components/http_request/http_request_arduino.cpp +4 -3
  47. esphome/components/http_request/http_request_idf.cpp +12 -14
  48. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  49. esphome/components/http_request/update/http_request_update.cpp +1 -1
  50. esphome/components/i2c_device/__init__.py +26 -0
  51. esphome/components/i2c_device/i2c_device.cpp +17 -0
  52. esphome/components/i2c_device/i2c_device.h +18 -0
  53. esphome/components/i2s_audio/__init__.py +1 -3
  54. esphome/components/i2s_audio/speaker/__init__.py +12 -4
  55. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +426 -200
  56. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +92 -33
  57. esphome/components/ili9xxx/display.py +5 -1
  58. esphome/components/image/__init__.py +5 -8
  59. esphome/components/image/image.cpp +14 -14
  60. esphome/components/image/image.h +20 -24
  61. esphome/components/internal_temperature/internal_temperature.cpp +51 -2
  62. esphome/components/internal_temperature/internal_temperature.h +1 -0
  63. esphome/components/ld2420/ld2420.cpp +1 -1
  64. esphome/components/libretiny/gpio.py +4 -2
  65. esphome/components/light/__init__.py +32 -1
  66. esphome/components/light/automation.py +39 -32
  67. esphome/components/light/effects.py +36 -36
  68. esphome/components/light/light_state.cpp +6 -16
  69. esphome/components/light/light_state.h +34 -0
  70. esphome/components/light/types.py +3 -1
  71. esphome/components/logger/logger_esp32.cpp +15 -0
  72. esphome/components/lvgl/__init__.py +202 -95
  73. esphome/components/lvgl/automation.py +42 -40
  74. esphome/components/lvgl/binary_sensor/__init__.py +8 -15
  75. esphome/components/lvgl/defines.py +14 -8
  76. esphome/components/lvgl/encoders.py +11 -8
  77. esphome/components/lvgl/keypads.py +77 -0
  78. esphome/components/lvgl/light/__init__.py +6 -8
  79. esphome/components/lvgl/lv_validation.py +2 -4
  80. esphome/components/lvgl/lvcode.py +3 -9
  81. esphome/components/lvgl/lvgl_esphome.cpp +210 -89
  82. esphome/components/lvgl/lvgl_esphome.h +113 -30
  83. esphome/components/lvgl/lvgl_proxy.h +17 -0
  84. esphome/components/lvgl/number/__init__.py +10 -15
  85. esphome/components/lvgl/schemas.py +4 -2
  86. esphome/components/lvgl/select/__init__.py +12 -37
  87. esphome/components/lvgl/select/lvgl_select.h +27 -33
  88. esphome/components/lvgl/sensor/__init__.py +8 -14
  89. esphome/components/lvgl/styles.py +3 -4
  90. esphome/components/lvgl/switch/__init__.py +8 -13
  91. esphome/components/lvgl/text/__init__.py +5 -6
  92. esphome/components/lvgl/text_sensor/__init__.py +15 -15
  93. esphome/components/lvgl/touchscreens.py +2 -3
  94. esphome/components/lvgl/trigger.py +7 -9
  95. esphome/components/lvgl/types.py +9 -3
  96. esphome/components/lvgl/widgets/__init__.py +32 -21
  97. esphome/components/lvgl/widgets/dropdown.py +22 -10
  98. esphome/components/lvgl/widgets/msgbox.py +6 -5
  99. esphome/components/lvgl/widgets/obj.py +4 -2
  100. esphome/components/lvgl/widgets/page.py +3 -2
  101. esphome/components/lvgl/widgets/qrcode.py +54 -0
  102. esphome/components/lvgl/widgets/roller.py +21 -14
  103. esphome/components/lvgl/widgets/tileview.py +2 -1
  104. esphome/components/max17043/__init__.py +1 -0
  105. esphome/components/max17043/automation.h +20 -0
  106. esphome/components/max17043/max17043.cpp +98 -0
  107. esphome/components/max17043/max17043.h +29 -0
  108. esphome/components/max17043/sensor.py +77 -0
  109. esphome/components/media_player/__init__.py +11 -0
  110. esphome/components/media_player/automation.h +10 -0
  111. esphome/components/media_player/media_player.cpp +4 -0
  112. esphome/components/midea/air_conditioner.cpp +17 -1
  113. esphome/components/mlx90393/sensor.py +1 -1
  114. esphome/components/modbus_controller/__init__.py +31 -1
  115. esphome/components/modbus_controller/automation.h +16 -0
  116. esphome/components/modbus_controller/const.py +2 -0
  117. esphome/components/modbus_controller/modbus_controller.cpp +14 -2
  118. esphome/components/modbus_controller/modbus_controller.h +9 -0
  119. esphome/components/mopeka_pro_check/mopeka_pro_check.cpp +40 -21
  120. esphome/components/mopeka_pro_check/mopeka_pro_check.h +9 -2
  121. esphome/components/mopeka_pro_check/sensor.py +41 -0
  122. esphome/components/mqtt/__init__.py +36 -0
  123. esphome/components/mqtt/mqtt_client.cpp +27 -3
  124. esphome/components/mqtt/mqtt_client.h +27 -2
  125. esphome/components/mqtt/mqtt_climate.cpp +4 -2
  126. esphome/components/mqtt/mqtt_component.cpp +6 -0
  127. esphome/components/mqtt/mqtt_component.h +4 -0
  128. esphome/components/mqtt/mqtt_const.h +6 -0
  129. esphome/components/online_image/online_image.cpp +2 -8
  130. esphome/components/online_image/online_image.h +2 -6
  131. esphome/components/opentherm/__init__.py +35 -9
  132. esphome/components/opentherm/binary_sensor/__init__.py +33 -0
  133. esphome/components/opentherm/const.py +11 -0
  134. esphome/components/opentherm/generate.py +142 -0
  135. esphome/components/opentherm/hub.cpp +130 -24
  136. esphome/components/opentherm/hub.h +62 -9
  137. esphome/components/opentherm/input.h +18 -0
  138. esphome/components/opentherm/input.py +51 -0
  139. esphome/components/opentherm/number/__init__.py +74 -0
  140. esphome/components/opentherm/number/number.cpp +40 -0
  141. esphome/components/opentherm/number/number.h +31 -0
  142. esphome/components/opentherm/opentherm.cpp +30 -0
  143. esphome/components/opentherm/opentherm.h +34 -2
  144. esphome/components/opentherm/opentherm_macros.h +151 -0
  145. esphome/components/opentherm/output/__init__.py +47 -0
  146. esphome/components/opentherm/output/output.cpp +18 -0
  147. esphome/components/opentherm/output/output.h +33 -0
  148. esphome/components/opentherm/schema.py +814 -0
  149. esphome/components/opentherm/sensor/__init__.py +51 -0
  150. esphome/components/opentherm/switch/__init__.py +43 -0
  151. esphome/components/opentherm/switch/switch.cpp +28 -0
  152. esphome/components/opentherm/switch/switch.h +20 -0
  153. esphome/components/opentherm/validate.py +31 -0
  154. esphome/components/pcd8544/display.py +8 -4
  155. esphome/components/prometheus/prometheus_handler.cpp +176 -14
  156. esphome/components/prometheus/prometheus_handler.h +25 -7
  157. esphome/components/qspi_amoled/display.py +1 -141
  158. esphome/components/qspi_dbi/display.py +185 -0
  159. esphome/components/qspi_dbi/models.py +64 -0
  160. esphome/components/{qspi_amoled/qspi_amoled.cpp → qspi_dbi/qspi_dbi.cpp} +95 -46
  161. esphome/components/{qspi_amoled/qspi_amoled.h → qspi_dbi/qspi_dbi.h} +26 -15
  162. esphome/components/rp2040/__init__.py +6 -3
  163. esphome/components/rp2040/gpio.py +5 -3
  164. esphome/components/rtttl/rtttl.cpp +4 -1
  165. esphome/components/rtttl/rtttl.h +1 -0
  166. esphome/components/sdl/sdl_esphome.cpp +22 -5
  167. esphome/components/sdl/sdl_esphome.h +1 -0
  168. esphome/components/sdm_meter/sdm_meter.cpp +1 -1
  169. esphome/components/sensor/__init__.py +18 -8
  170. esphome/components/sensor/filter.cpp +19 -18
  171. esphome/components/sensor/filter.h +9 -10
  172. esphome/components/sgp4x/sgp4x.cpp +40 -74
  173. esphome/components/sgp4x/sgp4x.h +5 -3
  174. esphome/components/speaker/__init__.py +51 -5
  175. esphome/components/speaker/automation.h +25 -0
  176. esphome/components/speaker/speaker.h +72 -1
  177. esphome/components/spi/__init__.py +15 -14
  178. esphome/components/spi_device/__init__.py +4 -15
  179. esphome/components/ssd1306_spi/display.py +6 -2
  180. esphome/components/ssd1322_spi/display.py +6 -2
  181. esphome/components/ssd1325_spi/display.py +6 -2
  182. esphome/components/ssd1327_spi/display.py +6 -2
  183. esphome/components/ssd1331_spi/display.py +6 -2
  184. esphome/components/ssd1351_spi/display.py +6 -2
  185. esphome/components/st7567_spi/display.py +6 -2
  186. esphome/components/st7701s/display.py +5 -1
  187. esphome/components/st7735/display.py +10 -5
  188. esphome/components/st7789v/display.py +12 -7
  189. esphome/components/statsd/statsd.cpp +2 -0
  190. esphome/components/statsd/statsd.h +2 -0
  191. esphome/components/sun/sun.h +3 -0
  192. esphome/components/tc74/__init__.py +1 -0
  193. esphome/components/tc74/sensor.py +32 -0
  194. esphome/components/tc74/tc74.cpp +68 -0
  195. esphome/components/tc74/tc74.h +28 -0
  196. esphome/components/touchscreen/__init__.py +41 -50
  197. esphome/components/touchscreen/touchscreen.h +4 -8
  198. esphome/components/tuya/fan/tuya_fan.cpp +1 -1
  199. esphome/components/udp/udp_component.cpp +6 -3
  200. esphome/components/udp/udp_component.h +4 -2
  201. esphome/components/waveshare_epaper/display.py +6 -2
  202. esphome/components/web_server/web_server.cpp +22 -0
  203. esphome/components/web_server/web_server.h +3 -0
  204. esphome/components/weikai/weikai.h +2 -2
  205. esphome/components/wifi/wifi_component.cpp +2 -2
  206. esphome/components/wifi/wifi_component_esp32_arduino.cpp +4 -4
  207. esphome/components/wifi/wifi_component_esp8266.cpp +4 -4
  208. esphome/components/wifi/wifi_component_esp_idf.cpp +2 -2
  209. esphome/components/xpt2046/touchscreen/__init__.py +7 -32
  210. esphome/config_validation.py +3 -1
  211. esphome/const.py +9 -2
  212. esphome/core/defines.h +8 -2
  213. esphome/core/helpers.cpp +32 -17
  214. esphome/core/helpers.h +32 -16
  215. esphome/core/ring_buffer.cpp +2 -2
  216. esphome/core/ring_buffer.h +2 -2
  217. esphome/dashboard/core.py +25 -0
  218. esphome/dashboard/status/mdns.py +3 -4
  219. esphome/dashboard/web_server.py +54 -19
  220. esphome/espota2.py +36 -35
  221. esphome/helpers.py +68 -16
  222. esphome/mqtt.py +9 -2
  223. esphome/storage_json.py +4 -0
  224. esphome/writer.py +7 -18
  225. esphome/zeroconf.py +8 -6
  226. {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/METADATA +7 -5
  227. {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/RECORD +232 -186
  228. esphome/core/bytebuffer.cpp +0 -167
  229. esphome/core/bytebuffer.h +0 -144
  230. /esphome/components/{qspi_amoled → qspi_dbi}/__init__.py +0 -0
  231. {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/LICENSE +0 -0
  232. {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/WHEEL +0 -0
  233. {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/entry_points.txt +0 -0
  234. {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
- import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
1
  from esphome import pins
2
+ import esphome.codegen as cg
4
3
  from esphome.components import spi, ssd1327_base
4
+ import esphome.config_validation as cv
5
5
  from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES
6
6
 
7
7
  CODEOWNERS = ["@kbx81"]
@@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All(
24
24
  cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA),
25
25
  )
26
26
 
27
+ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema(
28
+ "ssd1327_spi", require_miso=False, require_mosi=True
29
+ )
30
+
27
31
 
28
32
  async def to_code(config):
29
33
  var = cg.new_Pvariable(config[CONF_ID])
@@ -1,7 +1,7 @@
1
- import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
1
  from esphome import pins
2
+ import esphome.codegen as cg
4
3
  from esphome.components import spi, ssd1331_base
4
+ import esphome.config_validation as cv
5
5
  from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES
6
6
 
7
7
  CODEOWNERS = ["@kbx81"]
@@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All(
24
24
  cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA),
25
25
  )
26
26
 
27
+ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema(
28
+ "ssd1331_spi", require_miso=False, require_mosi=True
29
+ )
30
+
27
31
 
28
32
  async def to_code(config):
29
33
  var = cg.new_Pvariable(config[CONF_ID])
@@ -1,7 +1,7 @@
1
- import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
1
  from esphome import pins
2
+ import esphome.codegen as cg
4
3
  from esphome.components import spi, ssd1351_base
4
+ import esphome.config_validation as cv
5
5
  from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES
6
6
 
7
7
  CODEOWNERS = ["@kbx81"]
@@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All(
24
24
  cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA),
25
25
  )
26
26
 
27
+ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema(
28
+ "ssd1351_spi", require_miso=False, require_mosi=True
29
+ )
30
+
27
31
 
28
32
  async def to_code(config):
29
33
  var = cg.new_Pvariable(config[CONF_ID])
@@ -1,7 +1,7 @@
1
- import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
1
  from esphome import pins
2
+ import esphome.codegen as cg
4
3
  from esphome.components import spi, st7567_base
4
+ import esphome.config_validation as cv
5
5
  from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES
6
6
 
7
7
  CODEOWNERS = ["@latonita"]
@@ -24,6 +24,10 @@ CONFIG_SCHEMA = cv.All(
24
24
  cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA),
25
25
  )
26
26
 
27
+ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema(
28
+ "st7567_spi", require_miso=False, require_mosi=True
29
+ )
30
+
27
31
 
28
32
  async def to_code(config):
29
33
  var = cg.new_Pvariable(config[CONF_ID])
@@ -18,6 +18,7 @@ from esphome.const import (
18
18
  CONF_HSYNC_PIN,
19
19
  CONF_ID,
20
20
  CONF_IGNORE_STRAPPING_WARNING,
21
+ CONF_INIT_SEQUENCE,
21
22
  CONF_INVERT_COLORS,
22
23
  CONF_LAMBDA,
23
24
  CONF_MIRROR_X,
@@ -35,7 +36,6 @@ from esphome.core import TimePeriod
35
36
 
36
37
  from .init_sequences import ST7701S_INITS, cmd
37
38
 
38
- CONF_INIT_SEQUENCE = "init_sequence"
39
39
  CONF_DE_PIN = "de_pin"
40
40
  CONF_PCLK_PIN = "pclk_pin"
41
41
 
@@ -167,6 +167,10 @@ CONFIG_SCHEMA = cv.All(
167
167
  cv.only_with_esp_idf,
168
168
  )
169
169
 
170
+ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema(
171
+ "st7701s", require_miso=False, require_mosi=True
172
+ )
173
+
170
174
 
171
175
  async def to_code(config):
172
176
  var = cg.new_Pvariable(config[CONF_ID])
@@ -1,17 +1,17 @@
1
+ from esphome import pins
1
2
  import esphome.codegen as cg
3
+ from esphome.components import display, spi
2
4
  import esphome.config_validation as cv
3
- from esphome import pins
4
- from esphome.components import spi
5
- from esphome.components import display
6
5
  from esphome.const import (
7
6
  CONF_DC_PIN,
8
7
  CONF_ID,
8
+ CONF_INVERT_COLORS,
9
9
  CONF_LAMBDA,
10
10
  CONF_MODEL,
11
- CONF_RESET_PIN,
12
11
  CONF_PAGES,
13
- CONF_INVERT_COLORS,
12
+ CONF_RESET_PIN,
14
13
  )
14
+
15
15
  from . import st7735_ns
16
16
 
17
17
  CODEOWNERS = ["@SenexCrenshaw"]
@@ -68,6 +68,11 @@ CONFIG_SCHEMA = cv.All(
68
68
  )
69
69
 
70
70
 
71
+ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema(
72
+ "st7735", require_miso=False, require_mosi=True
73
+ )
74
+
75
+
71
76
  async def setup_st7735(var, config):
72
77
  await display.register_display(var, config)
73
78
 
@@ -1,22 +1,23 @@
1
+ from esphome import pins
1
2
  import esphome.codegen as cg
3
+ from esphome.components import display, power_supply, spi
2
4
  import esphome.config_validation as cv
3
- from esphome import pins
4
- from esphome.components import display, spi, power_supply
5
5
  from esphome.const import (
6
6
  CONF_BACKLIGHT_PIN,
7
+ CONF_CS_PIN,
7
8
  CONF_DC_PIN,
8
9
  CONF_HEIGHT,
9
10
  CONF_ID,
10
11
  CONF_LAMBDA,
11
12
  CONF_MODEL,
12
- CONF_RESET_PIN,
13
- CONF_WIDTH,
14
- CONF_POWER_SUPPLY,
15
- CONF_ROTATION,
16
- CONF_CS_PIN,
17
13
  CONF_OFFSET_HEIGHT,
18
14
  CONF_OFFSET_WIDTH,
15
+ CONF_POWER_SUPPLY,
16
+ CONF_RESET_PIN,
17
+ CONF_ROTATION,
18
+ CONF_WIDTH,
19
19
  )
20
+
20
21
  from . import st7789v_ns
21
22
 
22
23
  CONF_EIGHTBITCOLOR = "eightbitcolor"
@@ -168,6 +169,10 @@ CONFIG_SCHEMA = cv.All(
168
169
  validate_st7789v,
169
170
  )
170
171
 
172
+ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema(
173
+ "st7789v", require_miso=False, require_mosi=True
174
+ )
175
+
171
176
 
172
177
  async def to_code(config):
173
178
  var = cg.new_Pvariable(config[CONF_ID])
@@ -2,6 +2,7 @@
2
2
 
3
3
  #include "statsd.h"
4
4
 
5
+ #ifdef USE_NETWORK
5
6
  namespace esphome {
6
7
  namespace statsd {
7
8
 
@@ -154,3 +155,4 @@ void StatsdComponent::send_(std::string *out) {
154
155
 
155
156
  } // namespace statsd
156
157
  } // namespace esphome
158
+ #endif
@@ -3,6 +3,7 @@
3
3
  #include <vector>
4
4
 
5
5
  #include "esphome/core/defines.h"
6
+ #ifdef USE_NETWORK
6
7
  #include "esphome/core/component.h"
7
8
  #include "esphome/components/socket/socket.h"
8
9
  #include "esphome/components/network/ip_address.h"
@@ -84,3 +85,4 @@ class StatsdComponent : public PollingComponent {
84
85
 
85
86
  } // namespace statsd
86
87
  } // namespace esphome
88
+ #endif
@@ -59,6 +59,9 @@ class Sun {
59
59
  void set_latitude(double latitude) { location_.latitude = latitude; }
60
60
  void set_longitude(double longitude) { location_.longitude = longitude; }
61
61
 
62
+ // Check if the sun is above the horizon, with a default elevation angle of -0.83333 (standard for sunrise/set).
63
+ bool is_above_horizon(double elevation = -0.83333) { return this->elevation() > elevation; }
64
+
62
65
  optional<ESPTime> sunrise(double elevation);
63
66
  optional<ESPTime> sunset(double elevation);
64
67
  optional<ESPTime> sunrise(ESPTime date, double elevation);
@@ -0,0 +1 @@
1
+ CODEOWNERS = ["@sethgirvan"]
@@ -0,0 +1,32 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components import i2c, sensor
3
+ import esphome.config_validation as cv
4
+ from esphome.const import (
5
+ DEVICE_CLASS_TEMPERATURE,
6
+ STATE_CLASS_MEASUREMENT,
7
+ UNIT_CELSIUS,
8
+ )
9
+
10
+ CODEOWNERS = ["@sethgirvan"]
11
+ DEPENDENCIES = ["i2c"]
12
+
13
+ tc74_ns = cg.esphome_ns.namespace("tc74")
14
+ TC74Component = tc74_ns.class_("TC74Component", cg.PollingComponent, i2c.I2CDevice)
15
+
16
+ CONFIG_SCHEMA = (
17
+ sensor.sensor_schema(
18
+ TC74Component,
19
+ unit_of_measurement=UNIT_CELSIUS,
20
+ accuracy_decimals=1,
21
+ device_class=DEVICE_CLASS_TEMPERATURE,
22
+ state_class=STATE_CLASS_MEASUREMENT,
23
+ )
24
+ .extend(cv.polling_component_schema("60s"))
25
+ .extend(i2c.i2c_device_schema(0x48))
26
+ )
27
+
28
+
29
+ async def to_code(config):
30
+ var = await sensor.new_sensor(config)
31
+ await cg.register_component(var, config)
32
+ await i2c.register_i2c_device(var, config)
@@ -0,0 +1,68 @@
1
+ // Based on the TC74 datasheet https://ww1.microchip.com/downloads/en/DeviceDoc/21462D.pdf
2
+
3
+ #include "tc74.h"
4
+ #include "esphome/core/log.h"
5
+
6
+ namespace esphome {
7
+ namespace tc74 {
8
+
9
+ static const char *const TAG = "tc74";
10
+
11
+ static const uint8_t TC74_REGISTER_TEMPERATURE = 0x00;
12
+ static const uint8_t TC74_REGISTER_CONFIGURATION = 0x01;
13
+ static const uint8_t TC74_DATA_READY_MASK = 0x40;
14
+
15
+ // It is possible the "Data Ready" bit will not be set if the TC74 has not been powered on for at least 250ms, so it not
16
+ // being set does not constitute a failure.
17
+ void TC74Component::setup() {
18
+ ESP_LOGCONFIG(TAG, "Setting up TC74...");
19
+ uint8_t config_reg;
20
+ if (this->read_register(TC74_REGISTER_CONFIGURATION, &config_reg, 1) != i2c::ERROR_OK) {
21
+ this->mark_failed();
22
+ return;
23
+ }
24
+ this->data_ready_ = config_reg & TC74_DATA_READY_MASK;
25
+ }
26
+
27
+ void TC74Component::update() { this->read_temperature_(); }
28
+
29
+ void TC74Component::dump_config() {
30
+ LOG_SENSOR("", "TC74", this);
31
+ LOG_I2C_DEVICE(this);
32
+ if (this->is_failed()) {
33
+ ESP_LOGE(TAG, "Connection with TC74 failed!");
34
+ }
35
+ LOG_UPDATE_INTERVAL(this);
36
+ }
37
+
38
+ void TC74Component::read_temperature_() {
39
+ if (!this->data_ready_) {
40
+ uint8_t config_reg;
41
+ if (this->read_register(TC74_REGISTER_CONFIGURATION, &config_reg, 1) != i2c::ERROR_OK) {
42
+ this->status_set_warning();
43
+ return;
44
+ }
45
+
46
+ if (config_reg & TC74_DATA_READY_MASK) {
47
+ this->data_ready_ = true;
48
+ } else {
49
+ ESP_LOGD(TAG, "TC74 not ready");
50
+ return;
51
+ }
52
+ }
53
+
54
+ uint8_t temperature_reg;
55
+ if (this->read_register(TC74_REGISTER_TEMPERATURE, &temperature_reg, 1) != i2c::ERROR_OK) {
56
+ this->status_set_warning();
57
+ return;
58
+ }
59
+
60
+ ESP_LOGD(TAG, "Got Temperature=%d °C", temperature_reg);
61
+ this->publish_state(temperature_reg);
62
+ this->status_clear_warning();
63
+ }
64
+
65
+ float TC74Component::get_setup_priority() const { return setup_priority::DATA; }
66
+
67
+ } // namespace tc74
68
+ } // namespace esphome
@@ -0,0 +1,28 @@
1
+ #pragma once
2
+
3
+ #include "esphome/core/component.h"
4
+ #include "esphome/components/sensor/sensor.h"
5
+ #include "esphome/components/i2c/i2c.h"
6
+
7
+ namespace esphome {
8
+ namespace tc74 {
9
+
10
+ class TC74Component : public PollingComponent, public i2c::I2CDevice, public sensor::Sensor {
11
+ public:
12
+ /// Setup the sensor and check connection.
13
+ void setup() override;
14
+ void dump_config() override;
15
+ /// Update the sensor value (temperature).
16
+ void update() override;
17
+
18
+ float get_setup_priority() const override;
19
+
20
+ protected:
21
+ /// Internal method to read the temperature from the component after it has been scheduled.
22
+ void read_temperature_();
23
+
24
+ bool data_ready_ = false;
25
+ };
26
+
27
+ } // namespace tc74
28
+ } // namespace esphome
@@ -1,21 +1,18 @@
1
- import esphome.config_validation as cv
1
+ from esphome import automation
2
2
  import esphome.codegen as cg
3
-
4
3
  from esphome.components import display
5
- from esphome import automation
6
-
4
+ import esphome.config_validation as cv
7
5
  from esphome.const import (
6
+ CONF_CALIBRATION,
8
7
  CONF_DISPLAY,
9
- CONF_ON_TOUCH,
8
+ CONF_MIRROR_X,
9
+ CONF_MIRROR_Y,
10
10
  CONF_ON_RELEASE,
11
+ CONF_ON_TOUCH,
11
12
  CONF_ON_UPDATE,
12
13
  CONF_SWAP_XY,
13
- CONF_MIRROR_X,
14
- CONF_MIRROR_Y,
15
14
  CONF_TRANSFORM,
16
- CONF_CALIBRATION,
17
15
  )
18
-
19
16
  from esphome.core import coroutine_with_priority
20
17
 
21
18
  CODEOWNERS = ["@jesserockz", "@nielsnl68"]
@@ -43,51 +40,45 @@ CONF_Y_MIN = "y_min"
43
40
  CONF_Y_MAX = "y_max"
44
41
 
45
42
 
46
- def validate_calibration(config):
47
- if CONF_CALIBRATION in config:
48
- calibration_config = config[CONF_CALIBRATION]
49
- if (
50
- cv.int_([CONF_X_MIN]) != 0
51
- and cv.int_(calibration_config[CONF_X_MAX]) != 0
52
- and abs(
53
- cv.int_(calibration_config[CONF_X_MIN])
54
- - cv.int_(calibration_config[CONF_X_MAX])
55
- )
56
- < 10
57
- ):
58
- raise cv.Invalid("Calibration X values difference must be more than 10")
59
-
60
- if (
61
- cv.int_(calibration_config[CONF_Y_MIN]) != 0
62
- and cv.int_(calibration_config[CONF_Y_MAX]) != 0
63
- and abs(
64
- cv.int_(calibration_config[CONF_Y_MIN])
65
- - cv.int_(calibration_config[CONF_Y_MAX])
66
- )
67
- < 10
68
- ):
69
- raise cv.Invalid("Calibration Y values difference must be more than 10")
70
-
71
- return config
43
+ def validate_calibration(calibration_config):
44
+ x_min = calibration_config[CONF_X_MIN]
45
+ x_max = calibration_config[CONF_X_MAX]
46
+ y_min = calibration_config[CONF_Y_MIN]
47
+ y_max = calibration_config[CONF_Y_MAX]
48
+ if x_max < x_min:
49
+ raise cv.Invalid(
50
+ "x_min must be smaller than x_max. To mirror the direction use the 'transform' options"
51
+ )
52
+ if y_max < y_min:
53
+ raise cv.Invalid(
54
+ "y_min must be smaller than y_max. To mirror the direction use the 'transform' options"
55
+ )
56
+ x_delta = x_max - x_min
57
+ y_delta = y_max - y_min
58
+ if x_delta < 10 or y_delta < 10:
59
+ raise cv.Invalid("Calibration value range must be greater than 10")
60
+ return calibration_config
72
61
 
73
62
 
74
- def calibration_schema(default_max_values):
75
- return cv.Schema(
63
+ CALIBRATION_SCHEMA = cv.All(
64
+ cv.Schema(
76
65
  {
77
- cv.Optional(CONF_X_MIN, default=0): cv.int_range(min=0, max=4095),
78
- cv.Optional(CONF_X_MAX, default=default_max_values): cv.int_range(
79
- min=0, max=4095
80
- ),
81
- cv.Optional(CONF_Y_MIN, default=0): cv.int_range(min=0, max=4095),
82
- cv.Optional(CONF_Y_MAX, default=default_max_values): cv.int_range(
83
- min=0, max=4095
84
- ),
85
- },
86
- validate_calibration,
87
- )
66
+ cv.Required(CONF_X_MIN): cv.int_range(min=0, max=4095),
67
+ cv.Required(CONF_X_MAX): cv.int_range(min=0, max=4095),
68
+ cv.Required(CONF_Y_MIN): cv.int_range(min=0, max=4095),
69
+ cv.Required(CONF_Y_MAX): cv.int_range(min=0, max=4095),
70
+ }
71
+ ),
72
+ validate_calibration,
73
+ )
88
74
 
89
75
 
90
- def touchscreen_schema(default_touch_timeout):
76
+ def touchscreen_schema(default_touch_timeout=cv.UNDEFINED, calibration_required=False):
77
+ calibration = (
78
+ cv.Required(CONF_CALIBRATION)
79
+ if calibration_required
80
+ else cv.Optional(CONF_CALIBRATION)
81
+ )
91
82
  return cv.Schema(
92
83
  {
93
84
  cv.GenerateID(CONF_DISPLAY): cv.use_id(display.Display),
@@ -102,7 +93,7 @@ def touchscreen_schema(default_touch_timeout):
102
93
  cv.positive_time_period_milliseconds,
103
94
  cv.Range(max=cv.TimePeriod(milliseconds=65535)),
104
95
  ),
105
- cv.Optional(CONF_CALIBRATION): calibration_schema(0),
96
+ calibration: CALIBRATION_SCHEMA,
106
97
  cv.Optional(CONF_ON_TOUCH): automation.validate_automation(single=True),
107
98
  cv.Optional(CONF_ON_UPDATE): automation.validate_automation(single=True),
108
99
  cv.Optional(CONF_ON_RELEASE): automation.validate_automation(single=True),
@@ -53,14 +53,10 @@ class Touchscreen : public PollingComponent {
53
53
  void set_swap_xy(bool swap) { this->swap_x_y_ = swap; }
54
54
 
55
55
  void set_calibration(int16_t x_min, int16_t x_max, int16_t y_min, int16_t y_max) {
56
- this->x_raw_min_ = std::min(x_min, x_max);
57
- this->x_raw_max_ = std::max(x_min, x_max);
58
- this->y_raw_min_ = std::min(y_min, y_max);
59
- this->y_raw_max_ = std::max(y_min, y_max);
60
- if (x_min > x_max)
61
- this->invert_x_ = true;
62
- if (y_min > y_max)
63
- this->invert_y_ = true;
56
+ this->x_raw_min_ = x_min;
57
+ this->x_raw_max_ = x_max;
58
+ this->y_raw_min_ = y_min;
59
+ this->y_raw_max_ = y_max;
64
60
  }
65
61
 
66
62
  Trigger<TouchPoint, const TouchPoints_t &> *get_touch_trigger() { return &this->touch_trigger_; }
@@ -86,7 +86,7 @@ void TuyaFan::control(const fan::FanCall &call) {
86
86
  if (this->oscillation_id_.has_value() && call.get_oscillating().has_value()) {
87
87
  if (this->oscillation_type_ == TuyaDatapointType::ENUM) {
88
88
  this->parent_->set_enum_datapoint_value(*this->oscillation_id_, *call.get_oscillating());
89
- } else if (this->speed_type_ == TuyaDatapointType::BOOLEAN) {
89
+ } else if (this->oscillation_type_ == TuyaDatapointType::BOOLEAN) {
90
90
  this->parent_->set_boolean_datapoint_value(*this->oscillation_id_, *call.get_oscillating());
91
91
  }
92
92
  }
@@ -261,7 +261,8 @@ void UDPComponent::setup() {
261
261
  return;
262
262
  }
263
263
  }
264
- #else
264
+ #endif
265
+ #ifdef USE_SOCKET_IMPL_LWIP_TCP
265
266
  // 8266 and RP2040 `Duino
266
267
  for (const auto &address : this->addresses_) {
267
268
  auto ipaddr = IPAddress();
@@ -370,7 +371,8 @@ void UDPComponent::loop() {
370
371
  for (;;) {
371
372
  #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
372
373
  auto len = this->listen_socket_->read(buf, sizeof(buf));
373
- #else
374
+ #endif
375
+ #ifdef USE_SOCKET_IMPL_LWIP_TCP
374
376
  auto len = this->udp_client_.parsePacket();
375
377
  if (len > 0)
376
378
  len = this->udp_client_.read(buf, sizeof(buf));
@@ -587,7 +589,8 @@ void UDPComponent::send_packet_(void *data, size_t len) {
587
589
  if (result < 0)
588
590
  ESP_LOGW(TAG, "sendto() error %d", errno);
589
591
  }
590
- #else
592
+ #endif
593
+ #ifdef USE_SOCKET_IMPL_LWIP_TCP
591
594
  auto iface = IPAddress(0, 0, 0, 0);
592
595
  for (const auto &saddr : this->ipaddrs_) {
593
596
  if (this->udp_client_.beginPacketMulticast(saddr, this->port_, iface, 128) != 0) {
@@ -9,7 +9,8 @@
9
9
  #endif
10
10
  #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
11
11
  #include "esphome/components/socket/socket.h"
12
- #else
12
+ #endif
13
+ #ifdef USE_SOCKET_IMPL_LWIP_TCP
13
14
  #include <WiFiUdp.h>
14
15
  #endif
15
16
  #include <vector>
@@ -125,7 +126,8 @@ class UDPComponent : public PollingComponent {
125
126
  std::unique_ptr<socket::Socket> broadcast_socket_ = nullptr;
126
127
  std::unique_ptr<socket::Socket> listen_socket_ = nullptr;
127
128
  std::vector<struct sockaddr> sockaddrs_{};
128
- #else
129
+ #endif
130
+ #ifdef USE_SOCKET_IMPL_LWIP_TCP
129
131
  std::vector<IPAddress> ipaddrs_{};
130
132
  WiFiUDP udp_client_{};
131
133
  #endif
@@ -1,7 +1,7 @@
1
- import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
1
  from esphome import core, pins
2
+ import esphome.codegen as cg
4
3
  from esphome.components import display, spi
4
+ import esphome.config_validation as cv
5
5
  from esphome.const import (
6
6
  CONF_BUSY_PIN,
7
7
  CONF_DC_PIN,
@@ -187,6 +187,10 @@ CONFIG_SCHEMA = cv.All(
187
187
  cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA),
188
188
  )
189
189
 
190
+ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema(
191
+ "waveshare_epaper", require_miso=False, require_mosi=True
192
+ )
193
+
190
194
 
191
195
  async def to_code(config):
192
196
  model_type, model = MODELS[config[CONF_MODEL]]
@@ -1441,7 +1441,24 @@ std::string WebServer::alarm_control_panel_json(alarm_control_panel::AlarmContro
1441
1441
  void WebServer::on_event(event::Event *obj, const std::string &event_type) {
1442
1442
  this->events_.send(this->event_json(obj, event_type, DETAIL_STATE).c_str(), "state");
1443
1443
  }
1444
+ void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match) {
1445
+ for (event::Event *obj : App.get_events()) {
1446
+ if (obj->get_object_id() != match.id)
1447
+ continue;
1444
1448
 
1449
+ if (request->method() == HTTP_GET && match.method.empty()) {
1450
+ auto detail = DETAIL_STATE;
1451
+ auto *param = request->getParam("detail");
1452
+ if (param && param->value() == "all") {
1453
+ detail = DETAIL_ALL;
1454
+ }
1455
+ std::string data = this->event_json(obj, "", detail);
1456
+ request->send(200, "application/json", data.c_str());
1457
+ return;
1458
+ }
1459
+ }
1460
+ request->send(404);
1461
+ }
1445
1462
  std::string WebServer::event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config) {
1446
1463
  return json::build_json([this, obj, event_type, start_config](JsonObject root) {
1447
1464
  set_json_id(root, obj, "event-" + obj->get_object_id(), start_config);
@@ -1651,6 +1668,11 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) {
1651
1668
  return true;
1652
1669
  #endif
1653
1670
 
1671
+ #ifdef USE_EVENT
1672
+ if (request->method() == HTTP_GET && match.domain == "event")
1673
+ return true;
1674
+ #endif
1675
+
1654
1676
  #ifdef USE_UPDATE
1655
1677
  if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "update")
1656
1678
  return true;
@@ -322,6 +322,9 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
322
322
  #ifdef USE_EVENT
323
323
  void on_event(event::Event *obj, const std::string &event_type) override;
324
324
 
325
+ /// Handle a event request under '/event<id>'.
326
+ void handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match);
327
+
325
328
  /// Dump the event details with its value as a JSON string.
326
329
  std::string event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config);
327
330
  #endif
@@ -209,7 +209,7 @@ class WeikaiComponent : public Component {
209
209
 
210
210
  /// @brief store the name for the component
211
211
  /// @param name the name as defined by the python code generator
212
- void set_name(std::string name) { this->name_ = std::move(name); }
212
+ void set_name(std::string &&name) { this->name_ = std::move(name); }
213
213
 
214
214
  /// @brief Get the name of the component
215
215
  /// @return the name
@@ -308,7 +308,7 @@ class WeikaiChannel : public uart::UARTComponent {
308
308
 
309
309
  /// @brief The name as generated by the Python code generator
310
310
  /// @param name of the channel
311
- void set_channel_name(std::string name) { this->name_ = std::move(name); }
311
+ void set_channel_name(std::string &&name) { this->name_ = std::move(name); }
312
312
 
313
313
  /// @brief Get the channel name
314
314
  /// @return the name
@@ -297,8 +297,8 @@ void WiFiComponent::set_sta(const WiFiAP &ap) {
297
297
  void WiFiComponent::clear_sta() { this->sta_.clear(); }
298
298
  void WiFiComponent::save_wifi_sta(const std::string &ssid, const std::string &password) {
299
299
  SavedWifiSettings save{};
300
- strncpy(save.ssid, ssid.c_str(), sizeof(save.ssid));
301
- strncpy(save.password, password.c_str(), sizeof(save.password));
300
+ snprintf(save.ssid, sizeof(save.ssid), "%s", ssid.c_str());
301
+ snprintf(save.password, sizeof(save.password), "%s", password.c_str());
302
302
  this->pref_.save(&save);
303
303
  // ensure it's written immediately
304
304
  global_preferences->sync();