esphome 2024.9.2__py3-none-any.whl → 2024.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 (188) hide show
  1. esphome/components/aic3204/__init__.py +0 -0
  2. esphome/components/aic3204/aic3204.cpp +173 -0
  3. esphome/components/aic3204/aic3204.h +88 -0
  4. esphome/components/aic3204/audio_dac.py +52 -0
  5. esphome/components/aic3204/automation.h +23 -0
  6. esphome/components/alarm_control_panel/__init__.py +3 -4
  7. esphome/components/animation/__init__.py +16 -12
  8. esphome/components/api/api_connection.cpp +2 -0
  9. esphome/components/api/api_connection.h +3 -1
  10. esphome/components/api/api_frame_helper.cpp +2 -1
  11. esphome/components/api/api_frame_helper.h +2 -1
  12. esphome/components/api/api_server.cpp +2 -0
  13. esphome/components/api/api_server.h +3 -1
  14. esphome/components/api/custom_api_device.h +3 -2
  15. esphome/components/api/homeassistant_service.h +4 -3
  16. esphome/components/api/list_entities.cpp +2 -0
  17. esphome/components/api/list_entities.h +3 -2
  18. esphome/components/api/subscribe_state.cpp +2 -0
  19. esphome/components/api/subscribe_state.h +3 -2
  20. esphome/components/audio_dac/__init__.py +57 -0
  21. esphome/components/audio_dac/audio_dac.h +23 -0
  22. esphome/components/audio_dac/automation.h +43 -0
  23. esphome/components/bang_bang/bang_bang_climate.cpp +5 -2
  24. esphome/components/bedjet/bedjet_codec.cpp +4 -2
  25. esphome/components/binary_sensor/__init__.py +3 -4
  26. esphome/components/button/__init__.py +3 -4
  27. esphome/components/ch422g/__init__.py +26 -17
  28. esphome/components/ch422g/ch422g.cpp +66 -49
  29. esphome/components/ch422g/ch422g.h +17 -19
  30. esphome/components/climate/__init__.py +3 -4
  31. esphome/components/cover/__init__.py +4 -5
  32. esphome/components/cse7766/cse7766.cpp +11 -0
  33. esphome/components/cse7766/cse7766.h +4 -0
  34. esphome/components/cse7766/sensor.py +13 -1
  35. esphome/components/cst816/touchscreen/__init__.py +7 -4
  36. esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +20 -19
  37. esphome/components/cst816/touchscreen/cst816_touchscreen.h +2 -0
  38. esphome/components/datetime/__init__.py +21 -14
  39. esphome/components/datetime/datetime_base.h +8 -1
  40. esphome/components/datetime/datetime_entity.cpp +2 -0
  41. esphome/components/datetime/datetime_entity.h +2 -0
  42. esphome/components/datetime/time_entity.cpp +2 -0
  43. esphome/components/datetime/time_entity.h +2 -0
  44. esphome/components/esp32/__init__.py +20 -4
  45. esphome/components/esp32_improv/__init__.py +82 -1
  46. esphome/components/esp32_improv/automation.h +72 -0
  47. esphome/components/esp32_improv/esp32_improv_component.cpp +13 -5
  48. esphome/components/esp32_improv/esp32_improv_component.h +15 -0
  49. esphome/components/ethernet/__init__.py +5 -0
  50. esphome/components/ethernet/ethernet_component.cpp +13 -0
  51. esphome/components/ethernet/ethernet_component.h +1 -0
  52. esphome/components/fan/__init__.py +3 -4
  53. esphome/components/gp2y1010au0f/__init__.py +0 -0
  54. esphome/components/gp2y1010au0f/gp2y1010au0f.cpp +67 -0
  55. esphome/components/gp2y1010au0f/gp2y1010au0f.h +52 -0
  56. esphome/components/gp2y1010au0f/sensor.py +61 -0
  57. esphome/components/gpio_expander/__init__.py +0 -0
  58. esphome/components/gpio_expander/cached_gpio.h +38 -0
  59. esphome/components/grove_gas_mc_v2/__init__.py +0 -0
  60. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +88 -0
  61. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +39 -0
  62. esphome/components/grove_gas_mc_v2/sensor.py +77 -0
  63. esphome/components/haier/climate.py +4 -3
  64. esphome/components/haier/haier_base.cpp +63 -8
  65. esphome/components/haier/haier_base.h +29 -3
  66. esphome/components/haier/hon_climate.cpp +122 -65
  67. esphome/components/haier/hon_climate.h +18 -2
  68. esphome/components/haier/smartair2_climate.cpp +21 -21
  69. esphome/components/haier/switch/__init__.py +91 -0
  70. esphome/components/haier/switch/beeper.cpp +14 -0
  71. esphome/components/haier/switch/beeper.h +18 -0
  72. esphome/components/haier/switch/display.cpp +14 -0
  73. esphome/components/haier/switch/display.h +18 -0
  74. esphome/components/haier/switch/health_mode.cpp +14 -0
  75. esphome/components/haier/switch/health_mode.h +18 -0
  76. esphome/components/haier/switch/quiet_mode.cpp +14 -0
  77. esphome/components/haier/switch/quiet_mode.h +18 -0
  78. esphome/components/hmac_md5/hmac_md5.cpp +2 -0
  79. esphome/components/hmac_md5/hmac_md5.h +2 -1
  80. esphome/components/i2s_audio/speaker/__init__.py +19 -0
  81. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  82. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +2 -0
  83. esphome/components/ili9xxx/ili9xxx_display.h +1 -0
  84. esphome/components/image/__init__.py +12 -12
  85. esphome/components/image/image.cpp +44 -0
  86. esphome/components/image/image.h +17 -2
  87. esphome/components/inkplate6/display.py +2 -0
  88. esphome/components/inkplate6/inkplate.h +30 -2
  89. esphome/components/light/__init__.py +3 -4
  90. esphome/components/lock/__init__.py +3 -4
  91. esphome/components/lvgl/__init__.py +16 -5
  92. esphome/components/lvgl/defines.py +1 -0
  93. esphome/components/lvgl/hello_world.py +64 -0
  94. esphome/components/lvgl/lv_validation.py +159 -3
  95. esphome/components/lvgl/lvgl_esphome.cpp +0 -43
  96. esphome/components/lvgl/lvgl_esphome.h +0 -4
  97. esphome/components/lvgl/styles.py +3 -2
  98. esphome/components/lvgl/text/__init__.py +3 -3
  99. esphome/components/lvgl/widgets/__init__.py +2 -0
  100. esphome/components/lvgl/widgets/animimg.py +3 -4
  101. esphome/components/lvgl/widgets/dropdown.py +5 -1
  102. esphome/components/lvgl/widgets/meter.py +16 -11
  103. esphome/components/md5/__init__.py +6 -0
  104. esphome/components/md5/md5.cpp +2 -0
  105. esphome/components/md5/md5.h +2 -0
  106. esphome/components/micro_wake_word/__init__.py +7 -0
  107. esphome/components/mics_4514/sensor.py +11 -26
  108. esphome/components/modbus_controller/__init__.py +7 -5
  109. esphome/components/modbus_controller/binary_sensor/__init__.py +6 -6
  110. esphome/components/modbus_controller/number/__init__.py +5 -6
  111. esphome/components/modbus_controller/output/__init__.py +10 -14
  112. esphome/components/modbus_controller/select/__init__.py +1 -1
  113. esphome/components/modbus_controller/sensor/__init__.py +7 -7
  114. esphome/components/modbus_controller/switch/__init__.py +6 -7
  115. esphome/components/modbus_controller/text_sensor/__init__.py +8 -9
  116. esphome/components/mqtt/__init__.py +3 -0
  117. esphome/components/mqtt/mqtt_client.cpp +2 -0
  118. esphome/components/mqtt/mqtt_client.h +2 -0
  119. esphome/components/nau7802/__init__.py +0 -0
  120. esphome/components/nau7802/nau7802.cpp +323 -0
  121. esphome/components/nau7802/nau7802.h +121 -0
  122. esphome/components/nau7802/sensor.py +134 -0
  123. esphome/components/nextion/base_component.py +1 -0
  124. esphome/components/nextion/display.py +4 -0
  125. esphome/components/nextion/nextion.cpp +19 -4
  126. esphome/components/nextion/nextion.h +16 -0
  127. esphome/components/npi19/__init__.py +0 -0
  128. esphome/components/npi19/npi19.cpp +111 -0
  129. esphome/components/npi19/npi19.h +30 -0
  130. esphome/components/npi19/sensor.py +52 -0
  131. esphome/components/number/__init__.py +3 -5
  132. esphome/components/online_image/__init__.py +1 -1
  133. esphome/components/online_image/online_image.h +1 -2
  134. esphome/components/opentherm/__init__.py +57 -0
  135. esphome/components/opentherm/hub.cpp +277 -0
  136. esphome/components/opentherm/hub.h +110 -0
  137. esphome/components/opentherm/opentherm.cpp +568 -0
  138. esphome/components/opentherm/opentherm.h +347 -0
  139. esphome/components/pulse_counter/pulse_counter_sensor.cpp +8 -1
  140. esphome/components/pulse_counter/pulse_counter_sensor.h +1 -0
  141. esphome/components/radon_eye_ble/radon_eye_listener.cpp +10 -3
  142. esphome/components/remote_transmitter/__init__.py +18 -2
  143. esphome/components/remote_transmitter/remote_transmitter.h +6 -0
  144. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +2 -0
  145. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
  146. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
  147. esphome/components/select/__init__.py +3 -4
  148. esphome/components/sensor/__init__.py +3 -4
  149. esphome/components/st7701s/st7701s.cpp +21 -8
  150. esphome/components/st7701s/st7701s.h +2 -0
  151. esphome/components/switch/__init__.py +3 -4
  152. esphome/components/tca9555/__init__.py +72 -0
  153. esphome/components/tca9555/tca9555.cpp +140 -0
  154. esphome/components/tca9555/tca9555.h +64 -0
  155. esphome/components/tcs34725/tcs34725.cpp +62 -64
  156. esphome/components/tem3200/__init__.py +0 -0
  157. esphome/components/tem3200/sensor.py +55 -0
  158. esphome/components/tem3200/tem3200.cpp +151 -0
  159. esphome/components/tem3200/tem3200.h +30 -0
  160. esphome/components/template/binary_sensor/__init__.py +19 -6
  161. esphome/components/text/__init__.py +3 -4
  162. esphome/components/text_sensor/__init__.py +3 -4
  163. esphome/components/thermostat/climate.py +11 -9
  164. esphome/components/thermostat/thermostat_climate.cpp +21 -15
  165. esphome/components/tm1638/binary_sensor/__init__.py +3 -2
  166. esphome/components/tm1638/display.py +5 -5
  167. esphome/components/tm1638/output/__init__.py +3 -2
  168. esphome/components/tm1638/switch/__init__.py +3 -2
  169. esphome/components/update/__init__.py +3 -4
  170. esphome/components/valve/__init__.py +3 -4
  171. esphome/components/web_server/__init__.py +78 -22
  172. esphome/components/web_server/server_index_v3.h +3989 -3979
  173. esphome/components/web_server/web_server.cpp +212 -33
  174. esphome/components/web_server/web_server.h +10 -1
  175. esphome/components/wifi/wifi_component_esp_idf.cpp +4 -5
  176. esphome/config_validation.py +1 -0
  177. esphome/const.py +12 -2
  178. esphome/core/defines.h +4 -2
  179. esphome/core/helpers.cpp +46 -10
  180. esphome/core/helpers.h +8 -0
  181. esphome/core/ring_buffer.cpp +12 -2
  182. esphome/core/ring_buffer.h +3 -0
  183. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/METADATA +5 -3
  184. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/RECORD +188 -139
  185. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/LICENSE +0 -0
  186. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/WHEEL +0 -0
  187. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/entry_points.txt +0 -0
  188. {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,91 @@
1
+ import esphome.codegen as cg
2
+ import esphome.config_validation as cv
3
+ import esphome.final_validate as fv
4
+ from esphome.components import switch
5
+ from esphome.const import (
6
+ CONF_BEEPER,
7
+ CONF_DISPLAY,
8
+ ENTITY_CATEGORY_CONFIG,
9
+ )
10
+ from ..climate import (
11
+ CONF_HAIER_ID,
12
+ CONF_PROTOCOL,
13
+ HaierClimateBase,
14
+ haier_ns,
15
+ PROTOCOL_HON,
16
+ )
17
+
18
+ CODEOWNERS = ["@paveldn"]
19
+ BeeperSwitch = haier_ns.class_("BeeperSwitch", switch.Switch)
20
+ HealthModeSwitch = haier_ns.class_("HealthModeSwitch", switch.Switch)
21
+ DisplaySwitch = haier_ns.class_("DisplaySwitch", switch.Switch)
22
+ QuietModeSwitch = haier_ns.class_("QuietModeSwitch", switch.Switch)
23
+
24
+ # Haier switches
25
+ CONF_HEALTH_MODE = "health_mode"
26
+ CONF_QUIET_MODE = "quiet_mode"
27
+
28
+ # Additional icons
29
+ ICON_LEAF = "mdi:leaf"
30
+ ICON_LED_ON = "mdi:led-on"
31
+ ICON_VOLUME_HIGH = "mdi:volume-high"
32
+ ICON_VOLUME_OFF = "mdi:volume-off"
33
+
34
+ CONFIG_SCHEMA = cv.Schema(
35
+ {
36
+ cv.GenerateID(CONF_HAIER_ID): cv.use_id(HaierClimateBase),
37
+ cv.Optional(CONF_DISPLAY): switch.switch_schema(
38
+ DisplaySwitch,
39
+ icon=ICON_LED_ON,
40
+ entity_category=ENTITY_CATEGORY_CONFIG,
41
+ default_restore_mode="DISABLED",
42
+ ),
43
+ cv.Optional(CONF_HEALTH_MODE): switch.switch_schema(
44
+ HealthModeSwitch,
45
+ icon=ICON_LEAF,
46
+ default_restore_mode="DISABLED",
47
+ ),
48
+ # Beeper switch is only supported for HonClimate
49
+ cv.Optional(CONF_BEEPER): switch.switch_schema(
50
+ BeeperSwitch,
51
+ icon=ICON_VOLUME_HIGH,
52
+ entity_category=ENTITY_CATEGORY_CONFIG,
53
+ default_restore_mode="DISABLED",
54
+ ),
55
+ # Quiet mode is only supported for HonClimate
56
+ cv.Optional(CONF_QUIET_MODE): switch.switch_schema(
57
+ QuietModeSwitch,
58
+ icon=ICON_VOLUME_OFF,
59
+ entity_category=ENTITY_CATEGORY_CONFIG,
60
+ default_restore_mode="DISABLED",
61
+ ),
62
+ }
63
+ )
64
+
65
+
66
+ def _final_validate(config):
67
+ full_config = fv.full_config.get()
68
+ for switch_type in [CONF_BEEPER, CONF_QUIET_MODE]:
69
+ # Check switches that are only supported for HonClimate
70
+ if config.get(switch_type):
71
+ climate_path = full_config.get_path_for_id(config[CONF_HAIER_ID])[:-1]
72
+ climate_conf = full_config.get_config_for_path(climate_path)
73
+ protocol_type = climate_conf.get(CONF_PROTOCOL)
74
+ if protocol_type.casefold() != PROTOCOL_HON.casefold():
75
+ raise cv.Invalid(
76
+ f"{switch_type} switch is only supported for hon climate"
77
+ )
78
+ return config
79
+
80
+
81
+ FINAL_VALIDATE_SCHEMA = _final_validate
82
+
83
+
84
+ async def to_code(config):
85
+ parent = await cg.get_variable(config[CONF_HAIER_ID])
86
+
87
+ for switch_type in [CONF_DISPLAY, CONF_HEALTH_MODE, CONF_BEEPER, CONF_QUIET_MODE]:
88
+ if conf := config.get(switch_type):
89
+ sw_var = await switch.new_switch(conf)
90
+ await cg.register_parented(sw_var, parent)
91
+ cg.add(getattr(parent, f"set_{switch_type}_switch")(sw_var))
@@ -0,0 +1,14 @@
1
+ #include "beeper.h"
2
+
3
+ namespace esphome {
4
+ namespace haier {
5
+
6
+ void BeeperSwitch::write_state(bool state) {
7
+ if (this->parent_->get_beeper_state() != state) {
8
+ this->parent_->set_beeper_state(state);
9
+ }
10
+ this->publish_state(state);
11
+ }
12
+
13
+ } // namespace haier
14
+ } // namespace esphome
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/switch/switch.h"
4
+ #include "../hon_climate.h"
5
+
6
+ namespace esphome {
7
+ namespace haier {
8
+
9
+ class BeeperSwitch : public switch_::Switch, public Parented<HonClimate> {
10
+ public:
11
+ BeeperSwitch() = default;
12
+
13
+ protected:
14
+ void write_state(bool state) override;
15
+ };
16
+
17
+ } // namespace haier
18
+ } // namespace esphome
@@ -0,0 +1,14 @@
1
+ #include "display.h"
2
+
3
+ namespace esphome {
4
+ namespace haier {
5
+
6
+ void DisplaySwitch::write_state(bool state) {
7
+ if (this->parent_->get_display_state() != state) {
8
+ this->parent_->set_display_state(state);
9
+ }
10
+ this->publish_state(state);
11
+ }
12
+
13
+ } // namespace haier
14
+ } // namespace esphome
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/switch/switch.h"
4
+ #include "../haier_base.h"
5
+
6
+ namespace esphome {
7
+ namespace haier {
8
+
9
+ class DisplaySwitch : public switch_::Switch, public Parented<HaierClimateBase> {
10
+ public:
11
+ DisplaySwitch() = default;
12
+
13
+ protected:
14
+ void write_state(bool state) override;
15
+ };
16
+
17
+ } // namespace haier
18
+ } // namespace esphome
@@ -0,0 +1,14 @@
1
+ #include "health_mode.h"
2
+
3
+ namespace esphome {
4
+ namespace haier {
5
+
6
+ void HealthModeSwitch::write_state(bool state) {
7
+ if (this->parent_->get_health_mode() != state) {
8
+ this->parent_->set_health_mode(state);
9
+ }
10
+ this->publish_state(state);
11
+ }
12
+
13
+ } // namespace haier
14
+ } // namespace esphome
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/switch/switch.h"
4
+ #include "../haier_base.h"
5
+
6
+ namespace esphome {
7
+ namespace haier {
8
+
9
+ class HealthModeSwitch : public switch_::Switch, public Parented<HaierClimateBase> {
10
+ public:
11
+ HealthModeSwitch() = default;
12
+
13
+ protected:
14
+ void write_state(bool state) override;
15
+ };
16
+
17
+ } // namespace haier
18
+ } // namespace esphome
@@ -0,0 +1,14 @@
1
+ #include "quiet_mode.h"
2
+
3
+ namespace esphome {
4
+ namespace haier {
5
+
6
+ void QuietModeSwitch::write_state(bool state) {
7
+ if (this->parent_->get_quiet_mode_state() != state) {
8
+ this->parent_->set_quiet_mode_state(state);
9
+ }
10
+ this->publish_state(state);
11
+ }
12
+
13
+ } // namespace haier
14
+ } // namespace esphome
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/switch/switch.h"
4
+ #include "../hon_climate.h"
5
+
6
+ namespace esphome {
7
+ namespace haier {
8
+
9
+ class QuietModeSwitch : public switch_::Switch, public Parented<HonClimate> {
10
+ public:
11
+ QuietModeSwitch() = default;
12
+
13
+ protected:
14
+ void write_state(bool state) override;
15
+ };
16
+
17
+ } // namespace haier
18
+ } // namespace esphome
@@ -1,6 +1,7 @@
1
1
  #include <cstdio>
2
2
  #include <cstring>
3
3
  #include "hmac_md5.h"
4
+ #ifdef USE_MD5
4
5
  #include "esphome/core/helpers.h"
5
6
 
6
7
  namespace esphome {
@@ -54,3 +55,4 @@ bool HmacMD5::equals_hex(const char *expected) { return this->ohash_.equals_hex(
54
55
 
55
56
  } // namespace hmac_md5
56
57
  } // namespace esphome
58
+ #endif
@@ -1,8 +1,8 @@
1
1
  #pragma once
2
2
 
3
3
  #include "esphome/core/defines.h"
4
+ #ifdef USE_MD5
4
5
  #include "esphome/components/md5/md5.h"
5
-
6
6
  #include <string>
7
7
 
8
8
  namespace esphome {
@@ -46,3 +46,4 @@ class HmacMD5 {
46
46
 
47
47
  } // namespace hmac_md5
48
48
  } // namespace esphome
49
+ #endif
@@ -25,6 +25,7 @@ I2SAudioSpeaker = i2s_audio_ns.class_(
25
25
 
26
26
 
27
27
  CONF_DAC_TYPE = "dac_type"
28
+ CONF_I2S_COMM_FMT = "i2s_comm_fmt"
28
29
 
29
30
  i2s_dac_mode_t = cg.global_ns.enum("i2s_dac_mode_t")
30
31
  INTERNAL_DAC_OPTIONS = {
@@ -33,6 +34,20 @@ INTERNAL_DAC_OPTIONS = {
33
34
  CONF_STEREO: i2s_dac_mode_t.I2S_DAC_CHANNEL_BOTH_EN,
34
35
  }
35
36
 
37
+ i2s_comm_format_t = cg.global_ns.enum("i2s_comm_format_t")
38
+ I2C_COMM_FMT_OPTIONS = {
39
+ "stand_i2s": i2s_comm_format_t.I2S_COMM_FORMAT_STAND_I2S,
40
+ "stand_msb": i2s_comm_format_t.I2S_COMM_FORMAT_STAND_MSB,
41
+ "stand_pcm_short": i2s_comm_format_t.I2S_COMM_FORMAT_STAND_PCM_SHORT,
42
+ "stand_pcm_long": i2s_comm_format_t.I2S_COMM_FORMAT_STAND_PCM_LONG,
43
+ "stand_max": i2s_comm_format_t.I2S_COMM_FORMAT_STAND_MAX,
44
+ "i2s_msb": i2s_comm_format_t.I2S_COMM_FORMAT_I2S_MSB,
45
+ "i2s_lsb": i2s_comm_format_t.I2S_COMM_FORMAT_I2S_LSB,
46
+ "pcm": i2s_comm_format_t.I2S_COMM_FORMAT_PCM,
47
+ "pcm_short": i2s_comm_format_t.I2S_COMM_FORMAT_PCM_SHORT,
48
+ "pcm_long": i2s_comm_format_t.I2S_COMM_FORMAT_PCM_LONG,
49
+ }
50
+
36
51
  NO_INTERNAL_DAC_VARIANTS = [esp32.const.VARIANT_ESP32S2]
37
52
 
38
53
 
@@ -77,6 +92,9 @@ CONFIG_SCHEMA = cv.All(
77
92
  cv.Required(
78
93
  CONF_I2S_DOUT_PIN
79
94
  ): pins.internal_gpio_output_pin_number,
95
+ cv.Optional(CONF_I2S_COMM_FMT, default="stand_i2s"): cv.enum(
96
+ I2C_COMM_FMT_OPTIONS, lower=True
97
+ ),
80
98
  }
81
99
  ),
82
100
  },
@@ -96,4 +114,5 @@ async def to_code(config):
96
114
  cg.add(var.set_internal_dac_mode(config[CONF_CHANNEL]))
97
115
  else:
98
116
  cg.add(var.set_dout_pin(config[CONF_I2S_DOUT_PIN]))
117
+ cg.add(var.set_i2s_comm_fmt(config[CONF_I2S_COMM_FMT]))
99
118
  cg.add(var.set_timeout(config[CONF_TIMEOUT]))
@@ -83,7 +83,7 @@ void I2SAudioSpeaker::player_task(void *params) {
83
83
  .sample_rate = this_speaker->sample_rate_,
84
84
  .bits_per_sample = this_speaker->bits_per_sample_,
85
85
  .channel_format = this_speaker->channel_,
86
- .communication_format = I2S_COMM_FORMAT_STAND_I2S,
86
+ .communication_format = this_speaker->i2s_comm_fmt_,
87
87
  .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
88
88
  .dma_buf_count = 8,
89
89
  .dma_buf_len = 256,
@@ -49,6 +49,7 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp
49
49
  #if SOC_I2S_SUPPORTS_DAC
50
50
  void set_internal_dac_mode(i2s_dac_mode_t mode) { this->internal_dac_mode_ = mode; }
51
51
  #endif
52
+ void set_i2s_comm_fmt(i2s_comm_format_t mode) { this->i2s_comm_fmt_ = mode; }
52
53
 
53
54
  void start() override;
54
55
  void stop() override;
@@ -76,6 +77,7 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp
76
77
  #if SOC_I2S_SUPPORTS_DAC
77
78
  i2s_dac_mode_t internal_dac_mode_{I2S_DAC_CHANNEL_DISABLE};
78
79
  #endif
80
+ i2s_comm_format_t i2s_comm_fmt_;
79
81
  };
80
82
 
81
83
  } // namespace i2s_audio
@@ -89,6 +89,7 @@ class ILI9XXXDisplay : public display::DisplayBuffer,
89
89
 
90
90
  void dump_config() override;
91
91
  void setup() override;
92
+ void on_shutdown() override { this->command(ILI9XXX_SLPIN); }
92
93
 
93
94
  display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; }
94
95
  void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order,
@@ -1,18 +1,17 @@
1
1
  from __future__ import annotations
2
2
 
3
- import logging
4
-
5
3
  import hashlib
6
4
  import io
5
+ import logging
7
6
  from pathlib import Path
8
7
  import re
9
- from magic import Magic
10
8
 
11
- from esphome import core
9
+ import puremagic
10
+
11
+ from esphome import core, external_files
12
+ import esphome.codegen as cg
12
13
  from esphome.components import font
13
- from esphome import external_files
14
14
  import esphome.config_validation as cv
15
- import esphome.codegen as cg
16
15
  from esphome.const import (
17
16
  CONF_DITHER,
18
17
  CONF_FILE,
@@ -238,13 +237,12 @@ CONFIG_SCHEMA = cv.All(font.validate_pillow_installed, IMAGE_SCHEMA)
238
237
 
239
238
 
240
239
  def load_svg_image(file: bytes, resize: tuple[int, int]):
241
- # Local import only to allow "validate_pillow_installed" to run *before* importing it
242
- from PIL import Image
243
-
244
- # This import is only needed in case of SVG images; adding it
240
+ # Local imports only to allow "validate_pillow_installed" to run *before* importing it
241
+ # cairosvg is only needed in case of SVG images; adding it
245
242
  # to the top would force configurations not using SVG to also have it
246
243
  # installed for no reason.
247
244
  from cairosvg import svg2png
245
+ from PIL import Image
248
246
 
249
247
  if resize:
250
248
  req_width, req_height = resize
@@ -274,14 +272,16 @@ async def to_code(config):
274
272
  elif conf_file[CONF_SOURCE] == SOURCE_WEB:
275
273
  path = compute_local_image_path(conf_file).as_posix()
276
274
 
275
+ else:
276
+ raise core.EsphomeError(f"Unknown image source: {conf_file[CONF_SOURCE]}")
277
+
277
278
  try:
278
279
  with open(path, "rb") as f:
279
280
  file_contents = f.read()
280
281
  except Exception as e:
281
282
  raise core.EsphomeError(f"Could not load image file {path}: {e}")
282
283
 
283
- mime = Magic(mime=True)
284
- file_type = mime.from_buffer(file_contents)
284
+ file_type = puremagic.from_string(file_contents, mime=True)
285
285
 
286
286
  resize = config.get(CONF_RESIZE)
287
287
  if "svg" in file_type:
@@ -79,6 +79,50 @@ Color Image::get_pixel(int x, int y, Color color_on, Color color_off) const {
79
79
  return color_off;
80
80
  }
81
81
  }
82
+ #ifdef USE_LVGL
83
+ lv_img_dsc_t *Image::get_lv_img_dsc() {
84
+ // lazily construct lvgl image_dsc.
85
+ if (this->dsc_.data != this->data_start_) {
86
+ this->dsc_.data = this->data_start_;
87
+ this->dsc_.header.always_zero = 0;
88
+ this->dsc_.header.reserved = 0;
89
+ this->dsc_.header.w = this->width_;
90
+ this->dsc_.header.h = this->height_;
91
+ this->dsc_.data_size = image_type_to_width_stride(this->dsc_.header.w * this->dsc_.header.h, this->get_type());
92
+ switch (this->get_type()) {
93
+ case IMAGE_TYPE_BINARY:
94
+ this->dsc_.header.cf = LV_IMG_CF_ALPHA_1BIT;
95
+ break;
96
+
97
+ case IMAGE_TYPE_GRAYSCALE:
98
+ this->dsc_.header.cf = LV_IMG_CF_ALPHA_8BIT;
99
+ break;
100
+
101
+ case IMAGE_TYPE_RGB24:
102
+ this->dsc_.header.cf = LV_IMG_CF_RGB888;
103
+ break;
104
+
105
+ case IMAGE_TYPE_RGB565:
106
+ #if LV_COLOR_DEPTH == 16
107
+ this->dsc_.header.cf = this->has_transparency() ? LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED : LV_IMG_CF_TRUE_COLOR;
108
+ #else
109
+ this->dsc_.header.cf = LV_IMG_CF_RGB565;
110
+ #endif
111
+ break;
112
+
113
+ case image::IMAGE_TYPE_RGBA:
114
+ #if LV_COLOR_DEPTH == 32
115
+ this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR;
116
+ #else
117
+ this->dsc_.header.cf = LV_IMG_CF_RGBA8888;
118
+ #endif
119
+ break;
120
+ }
121
+ }
122
+ return &this->dsc_;
123
+ }
124
+ #endif // USE_LVGL
125
+
82
126
  bool Image::get_binary_pixel_(int x, int y) const {
83
127
  const uint32_t width_8 = ((this->width_ + 7u) / 8u) * 8u;
84
128
  const uint32_t pos = x + y * width_8;
@@ -1,6 +1,15 @@
1
1
  #pragma once
2
2
  #include "esphome/core/color.h"
3
- #include "esphome/components/display/display_buffer.h"
3
+ #include "esphome/components/display/display.h"
4
+
5
+ #ifdef USE_LVGL
6
+ // required for clang-tidy
7
+ #ifndef LV_CONF_H
8
+ #define LV_CONF_SKIP 1 // NOLINT
9
+ #endif // LV_CONF_H
10
+
11
+ #include <lvgl.h>
12
+ #endif // USE_LVGL
4
13
 
5
14
  namespace esphome {
6
15
  namespace image {
@@ -37,7 +46,7 @@ class Image : public display::BaseImage {
37
46
  Color get_pixel(int x, int y, Color color_on = display::COLOR_ON, Color color_off = display::COLOR_OFF) const;
38
47
  int get_width() const override;
39
48
  int get_height() const override;
40
- const uint8_t *get_data_start() { return this->data_start_; }
49
+ const uint8_t *get_data_start() const { return this->data_start_; }
41
50
  ImageType get_type() const;
42
51
 
43
52
  void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override;
@@ -45,6 +54,9 @@ class Image : public display::BaseImage {
45
54
  void set_transparency(bool transparent) { transparent_ = transparent; }
46
55
  bool has_transparency() const { return transparent_; }
47
56
 
57
+ #ifdef USE_LVGL
58
+ lv_img_dsc_t *get_lv_img_dsc();
59
+ #endif
48
60
  protected:
49
61
  bool get_binary_pixel_(int x, int y) const;
50
62
  Color get_rgb24_pixel_(int x, int y) const;
@@ -57,6 +69,9 @@ class Image : public display::BaseImage {
57
69
  ImageType type_;
58
70
  const uint8_t *data_start_;
59
71
  bool transparent_;
72
+ #ifdef USE_LVGL
73
+ lv_img_dsc_t dsc_{};
74
+ #endif
60
75
  };
61
76
 
62
77
  } // namespace image
@@ -53,6 +53,8 @@ MODELS = {
53
53
  "inkplate_10": InkplateModel.INKPLATE_10,
54
54
  "inkplate_6_plus": InkplateModel.INKPLATE_6_PLUS,
55
55
  "inkplate_6_v2": InkplateModel.INKPLATE_6_V2,
56
+ "inkplate_5": InkplateModel.INKPLATE_5,
57
+ "inkplate_5_v2": InkplateModel.INKPLATE_5_V2,
56
58
  }
57
59
 
58
60
  CONFIG_SCHEMA = cv.All(
@@ -15,6 +15,8 @@ enum InkplateModel : uint8_t {
15
15
  INKPLATE_10 = 1,
16
16
  INKPLATE_6_PLUS = 2,
17
17
  INKPLATE_6_V2 = 3,
18
+ INKPLATE_5 = 4,
19
+ INKPLATE_5_V2 = 5,
18
20
  };
19
21
 
20
22
  class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice {
@@ -29,7 +31,7 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice {
29
31
  const uint8_t pixelMaskLUT[8] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
30
32
  const uint8_t pixelMaskGLUT[2] = {0x0F, 0xF0};
31
33
 
32
- const uint8_t waveform3BitAll[4][8][9] = {// INKPLATE_6
34
+ const uint8_t waveform3BitAll[6][8][9] = {// INKPLATE_6
33
35
  {{0, 1, 1, 0, 0, 1, 1, 0, 0},
34
36
  {0, 1, 2, 1, 1, 2, 1, 0, 0},
35
37
  {1, 1, 1, 2, 2, 1, 0, 0, 0},
@@ -64,7 +66,25 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice {
64
66
  {1, 1, 1, 1, 2, 2, 1, 0, 0},
65
67
  {0, 1, 1, 1, 2, 2, 1, 0, 0},
66
68
  {0, 0, 0, 0, 1, 1, 2, 0, 0},
67
- {0, 0, 0, 0, 0, 1, 2, 0, 0}}};
69
+ {0, 0, 0, 0, 0, 1, 2, 0, 0}},
70
+ // INKPLATE_5
71
+ {{0, 0, 1, 1, 0, 1, 1, 1, 0},
72
+ {0, 1, 1, 1, 1, 2, 0, 1, 0},
73
+ {1, 2, 2, 0, 2, 1, 1, 1, 0},
74
+ {1, 1, 1, 2, 0, 1, 1, 2, 0},
75
+ {0, 1, 1, 1, 2, 0, 1, 2, 0},
76
+ {0, 0, 0, 1, 1, 2, 1, 2, 0},
77
+ {1, 1, 1, 2, 0, 2, 1, 2, 0},
78
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}},
79
+ // INKPLATE_5_V2
80
+ {{0, 0, 1, 1, 2, 1, 1, 1, 0},
81
+ {1, 1, 2, 2, 1, 2, 1, 1, 0},
82
+ {0, 1, 2, 2, 1, 1, 2, 1, 0},
83
+ {0, 0, 1, 1, 1, 1, 1, 2, 0},
84
+ {1, 2, 1, 2, 1, 1, 1, 2, 0},
85
+ {0, 1, 1, 1, 2, 0, 1, 2, 0},
86
+ {1, 1, 1, 2, 2, 2, 1, 2, 0},
87
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}}};
68
88
 
69
89
  void set_greyscale(bool greyscale) {
70
90
  this->greyscale_ = greyscale;
@@ -146,6 +166,10 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice {
146
166
  return 800;
147
167
  } else if (this->model_ == INKPLATE_10) {
148
168
  return 1200;
169
+ } else if (this->model_ == INKPLATE_5) {
170
+ return 960;
171
+ } else if (this->model_ == INKPLATE_5_V2) {
172
+ return 1280;
149
173
  } else if (this->model_ == INKPLATE_6_PLUS) {
150
174
  return 1024;
151
175
  }
@@ -155,6 +179,10 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice {
155
179
  int get_height_internal() override {
156
180
  if (this->model_ == INKPLATE_6 || this->model_ == INKPLATE_6_V2) {
157
181
  return 600;
182
+ } else if (this->model_ == INKPLATE_5) {
183
+ return 540;
184
+ } else if (this->model_ == INKPLATE_5_V2) {
185
+ return 720;
158
186
  } else if (this->model_ == INKPLATE_10) {
159
187
  return 825;
160
188
  } else if (this->model_ == INKPLATE_6_PLUS) {
@@ -18,7 +18,7 @@ from esphome.const import (
18
18
  CONF_RESTORE_MODE,
19
19
  CONF_TRIGGER_ID,
20
20
  CONF_WARM_WHITE_COLOR_TEMPERATURE,
21
- CONF_WEB_SERVER_ID,
21
+ CONF_WEB_SERVER,
22
22
  )
23
23
  from esphome.core import coroutine_with_priority
24
24
  from esphome.cpp_helpers import setup_entity
@@ -181,9 +181,8 @@ async def setup_light_core_(light_var, output_var, config):
181
181
  mqtt_ = cg.new_Pvariable(mqtt_id, light_var)
182
182
  await mqtt.register_mqtt_component(mqtt_, config)
183
183
 
184
- if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None:
185
- web_server_ = await cg.get_variable(webserver_id)
186
- web_server.add_entity_to_sorting_list(web_server_, light_var, config)
184
+ if web_server_config := config.get(CONF_WEB_SERVER):
185
+ await web_server.add_entity_config(light_var, web_server_config)
187
186
 
188
187
 
189
188
  async def register_light(output_var, config):
@@ -9,7 +9,7 @@ from esphome.const import (
9
9
  CONF_ON_LOCK,
10
10
  CONF_ON_UNLOCK,
11
11
  CONF_TRIGGER_ID,
12
- CONF_WEB_SERVER_ID,
12
+ CONF_WEB_SERVER,
13
13
  )
14
14
  from esphome.core import CORE, coroutine_with_priority
15
15
  from esphome.cpp_helpers import setup_entity
@@ -66,9 +66,8 @@ async def setup_lock_core_(var, config):
66
66
  mqtt_ = cg.new_Pvariable(mqtt_id, var)
67
67
  await mqtt.register_mqtt_component(mqtt_, config)
68
68
 
69
- if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None:
70
- web_server_ = await cg.get_variable(webserver_id)
71
- web_server.add_entity_to_sorting_list(web_server_, var, config)
69
+ if web_server_config := config.get(CONF_WEB_SERVER):
70
+ await web_server.add_entity_config(var, web_server_config)
72
71
 
73
72
 
74
73
  async def register_lock(var, config):