esphome 2024.9.1__py3-none-any.whl → 2024.10.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 (196) 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/bl0906/sensor.py +3 -2
  27. esphome/components/button/__init__.py +3 -4
  28. esphome/components/ch422g/__init__.py +26 -17
  29. esphome/components/ch422g/ch422g.cpp +66 -49
  30. esphome/components/ch422g/ch422g.h +17 -19
  31. esphome/components/climate/__init__.py +3 -4
  32. esphome/components/cover/__init__.py +4 -5
  33. esphome/components/cse7766/cse7766.cpp +12 -1
  34. esphome/components/cse7766/cse7766.h +4 -0
  35. esphome/components/cse7766/sensor.py +13 -1
  36. esphome/components/cst816/touchscreen/__init__.py +7 -4
  37. esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +20 -19
  38. esphome/components/cst816/touchscreen/cst816_touchscreen.h +2 -0
  39. esphome/components/datetime/__init__.py +21 -14
  40. esphome/components/datetime/datetime_base.h +8 -1
  41. esphome/components/datetime/datetime_entity.cpp +2 -0
  42. esphome/components/datetime/datetime_entity.h +2 -0
  43. esphome/components/datetime/time_entity.cpp +2 -0
  44. esphome/components/datetime/time_entity.h +2 -0
  45. esphome/components/esp32/__init__.py +20 -4
  46. esphome/components/esp32_improv/__init__.py +82 -1
  47. esphome/components/esp32_improv/automation.h +72 -0
  48. esphome/components/esp32_improv/esp32_improv_component.cpp +13 -5
  49. esphome/components/esp32_improv/esp32_improv_component.h +15 -0
  50. esphome/components/ethernet/__init__.py +5 -0
  51. esphome/components/ethernet/ethernet_component.cpp +13 -0
  52. esphome/components/ethernet/ethernet_component.h +1 -0
  53. esphome/components/event/__init__.py +20 -12
  54. esphome/components/fan/__init__.py +3 -4
  55. esphome/components/gp2y1010au0f/__init__.py +0 -0
  56. esphome/components/gp2y1010au0f/gp2y1010au0f.cpp +67 -0
  57. esphome/components/gp2y1010au0f/gp2y1010au0f.h +52 -0
  58. esphome/components/gp2y1010au0f/sensor.py +61 -0
  59. esphome/components/gpio_expander/__init__.py +0 -0
  60. esphome/components/gpio_expander/cached_gpio.h +38 -0
  61. esphome/components/grove_gas_mc_v2/__init__.py +0 -0
  62. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +88 -0
  63. esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +39 -0
  64. esphome/components/grove_gas_mc_v2/sensor.py +77 -0
  65. esphome/components/haier/climate.py +4 -3
  66. esphome/components/haier/haier_base.cpp +63 -8
  67. esphome/components/haier/haier_base.h +29 -3
  68. esphome/components/haier/hon_climate.cpp +122 -65
  69. esphome/components/haier/hon_climate.h +18 -2
  70. esphome/components/haier/smartair2_climate.cpp +21 -21
  71. esphome/components/haier/switch/__init__.py +91 -0
  72. esphome/components/haier/switch/beeper.cpp +14 -0
  73. esphome/components/haier/switch/beeper.h +18 -0
  74. esphome/components/haier/switch/display.cpp +14 -0
  75. esphome/components/haier/switch/display.h +18 -0
  76. esphome/components/haier/switch/health_mode.cpp +14 -0
  77. esphome/components/haier/switch/health_mode.h +18 -0
  78. esphome/components/haier/switch/quiet_mode.cpp +14 -0
  79. esphome/components/haier/switch/quiet_mode.h +18 -0
  80. esphome/components/hmac_md5/hmac_md5.cpp +2 -0
  81. esphome/components/hmac_md5/hmac_md5.h +2 -1
  82. esphome/components/i2s_audio/speaker/__init__.py +19 -0
  83. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  84. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +2 -0
  85. esphome/components/ili9xxx/ili9xxx_display.h +1 -0
  86. esphome/components/image/__init__.py +12 -12
  87. esphome/components/image/image.cpp +44 -0
  88. esphome/components/image/image.h +17 -2
  89. esphome/components/inkplate6/display.py +2 -0
  90. esphome/components/inkplate6/inkplate.h +30 -2
  91. esphome/components/light/__init__.py +3 -4
  92. esphome/components/lock/__init__.py +3 -4
  93. esphome/components/lvgl/__init__.py +16 -5
  94. esphome/components/lvgl/defines.py +1 -0
  95. esphome/components/lvgl/hello_world.py +64 -0
  96. esphome/components/lvgl/lv_validation.py +159 -3
  97. esphome/components/lvgl/lvgl_esphome.cpp +0 -43
  98. esphome/components/lvgl/lvgl_esphome.h +0 -4
  99. esphome/components/lvgl/styles.py +3 -2
  100. esphome/components/lvgl/text/__init__.py +3 -3
  101. esphome/components/lvgl/widgets/__init__.py +2 -0
  102. esphome/components/lvgl/widgets/animimg.py +3 -4
  103. esphome/components/lvgl/widgets/dropdown.py +5 -1
  104. esphome/components/lvgl/widgets/meter.py +16 -11
  105. esphome/components/md5/__init__.py +6 -0
  106. esphome/components/md5/md5.cpp +2 -0
  107. esphome/components/md5/md5.h +2 -0
  108. esphome/components/micro_wake_word/__init__.py +7 -0
  109. esphome/components/mics_4514/sensor.py +11 -26
  110. esphome/components/modbus_controller/__init__.py +7 -5
  111. esphome/components/modbus_controller/binary_sensor/__init__.py +6 -6
  112. esphome/components/modbus_controller/number/__init__.py +5 -6
  113. esphome/components/modbus_controller/output/__init__.py +10 -14
  114. esphome/components/modbus_controller/select/__init__.py +1 -1
  115. esphome/components/modbus_controller/sensor/__init__.py +7 -7
  116. esphome/components/modbus_controller/switch/__init__.py +6 -7
  117. esphome/components/modbus_controller/text_sensor/__init__.py +8 -9
  118. esphome/components/mqtt/__init__.py +3 -0
  119. esphome/components/mqtt/mqtt_client.cpp +2 -0
  120. esphome/components/mqtt/mqtt_client.h +2 -0
  121. esphome/components/nau7802/__init__.py +0 -0
  122. esphome/components/nau7802/nau7802.cpp +323 -0
  123. esphome/components/nau7802/nau7802.h +121 -0
  124. esphome/components/nau7802/sensor.py +134 -0
  125. esphome/components/nextion/base_component.py +1 -0
  126. esphome/components/nextion/display.py +4 -0
  127. esphome/components/nextion/nextion.cpp +19 -4
  128. esphome/components/nextion/nextion.h +16 -0
  129. esphome/components/npi19/__init__.py +0 -0
  130. esphome/components/npi19/npi19.cpp +111 -0
  131. esphome/components/npi19/npi19.h +30 -0
  132. esphome/components/npi19/sensor.py +52 -0
  133. esphome/components/number/__init__.py +3 -5
  134. esphome/components/online_image/__init__.py +1 -1
  135. esphome/components/online_image/online_image.h +1 -2
  136. esphome/components/opentherm/__init__.py +57 -0
  137. esphome/components/opentherm/hub.cpp +277 -0
  138. esphome/components/opentherm/hub.h +110 -0
  139. esphome/components/opentherm/opentherm.cpp +568 -0
  140. esphome/components/opentherm/opentherm.h +347 -0
  141. esphome/components/pulse_counter/pulse_counter_sensor.cpp +8 -1
  142. esphome/components/pulse_counter/pulse_counter_sensor.h +1 -0
  143. esphome/components/radon_eye_ble/radon_eye_listener.cpp +10 -3
  144. esphome/components/remote_transmitter/__init__.py +18 -2
  145. esphome/components/remote_transmitter/remote_transmitter.h +6 -0
  146. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +2 -0
  147. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
  148. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
  149. esphome/components/rp2040/__init__.py +13 -14
  150. esphome/components/select/__init__.py +3 -4
  151. esphome/components/sensor/__init__.py +3 -4
  152. esphome/components/shelly_dimmer/shelly_dimmer.cpp +32 -32
  153. esphome/components/shelly_dimmer/shelly_dimmer.h +2 -0
  154. esphome/components/st7701s/st7701s.cpp +21 -8
  155. esphome/components/st7701s/st7701s.h +2 -0
  156. esphome/components/switch/__init__.py +3 -4
  157. esphome/components/tca9555/__init__.py +72 -0
  158. esphome/components/tca9555/tca9555.cpp +140 -0
  159. esphome/components/tca9555/tca9555.h +64 -0
  160. esphome/components/tcs34725/tcs34725.cpp +62 -64
  161. esphome/components/tem3200/__init__.py +0 -0
  162. esphome/components/tem3200/sensor.py +55 -0
  163. esphome/components/tem3200/tem3200.cpp +151 -0
  164. esphome/components/tem3200/tem3200.h +30 -0
  165. esphome/components/template/binary_sensor/__init__.py +19 -6
  166. esphome/components/text/__init__.py +3 -4
  167. esphome/components/text_sensor/__init__.py +3 -4
  168. esphome/components/thermostat/climate.py +11 -9
  169. esphome/components/thermostat/thermostat_climate.cpp +21 -15
  170. esphome/components/tm1638/binary_sensor/__init__.py +3 -2
  171. esphome/components/tm1638/display.py +5 -5
  172. esphome/components/tm1638/output/__init__.py +3 -2
  173. esphome/components/tm1638/switch/__init__.py +3 -2
  174. esphome/components/touchscreen/touchscreen.cpp +2 -2
  175. esphome/components/update/__init__.py +3 -4
  176. esphome/components/valve/__init__.py +3 -4
  177. esphome/components/web_server/__init__.py +78 -22
  178. esphome/components/web_server/server_index_v3.h +3989 -3979
  179. esphome/components/web_server/web_server.cpp +219 -34
  180. esphome/components/web_server/web_server.h +10 -1
  181. esphome/components/wifi/wifi_component_esp_idf.cpp +4 -5
  182. esphome/config_validation.py +1 -0
  183. esphome/const.py +12 -2
  184. esphome/core/defines.h +4 -2
  185. esphome/core/helpers.cpp +46 -10
  186. esphome/core/helpers.h +8 -0
  187. esphome/core/ring_buffer.cpp +12 -2
  188. esphome/core/ring_buffer.h +3 -0
  189. esphome/voluptuous_schema.py +3 -1
  190. esphome/wizard.py +0 -3
  191. {esphome-2024.9.1.dist-info → esphome-2024.10.0.dist-info}/METADATA +5 -3
  192. {esphome-2024.9.1.dist-info → esphome-2024.10.0.dist-info}/RECORD +196 -147
  193. {esphome-2024.9.1.dist-info → esphome-2024.10.0.dist-info}/LICENSE +0 -0
  194. {esphome-2024.9.1.dist-info → esphome-2024.10.0.dist-info}/WHEEL +0 -0
  195. {esphome-2024.9.1.dist-info → esphome-2024.10.0.dist-info}/entry_points.txt +0 -0
  196. {esphome-2024.9.1.dist-info → esphome-2024.10.0.dist-info}/top_level.txt +0 -0
@@ -8,18 +8,21 @@ from esphome.const import (
8
8
  CONF_ID,
9
9
  CONF_POWER,
10
10
  CONF_POWER_FACTOR,
11
+ CONF_REACTIVE_POWER,
11
12
  CONF_VOLTAGE,
12
13
  DEVICE_CLASS_APPARENT_POWER,
13
14
  DEVICE_CLASS_CURRENT,
14
15
  DEVICE_CLASS_ENERGY,
15
16
  DEVICE_CLASS_POWER,
16
17
  DEVICE_CLASS_POWER_FACTOR,
18
+ DEVICE_CLASS_REACTIVE_POWER,
17
19
  DEVICE_CLASS_VOLTAGE,
18
20
  STATE_CLASS_MEASUREMENT,
19
21
  STATE_CLASS_TOTAL_INCREASING,
20
22
  UNIT_AMPERE,
21
23
  UNIT_VOLT,
22
24
  UNIT_VOLT_AMPS,
25
+ UNIT_VOLT_AMPS_REACTIVE,
23
26
  UNIT_WATT,
24
27
  UNIT_WATT_HOURS,
25
28
  )
@@ -62,6 +65,12 @@ CONFIG_SCHEMA = cv.Schema(
62
65
  device_class=DEVICE_CLASS_APPARENT_POWER,
63
66
  state_class=STATE_CLASS_MEASUREMENT,
64
67
  ),
68
+ cv.Optional(CONF_REACTIVE_POWER): sensor.sensor_schema(
69
+ unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE,
70
+ accuracy_decimals=1,
71
+ device_class=DEVICE_CLASS_REACTIVE_POWER,
72
+ state_class=STATE_CLASS_MEASUREMENT,
73
+ ),
65
74
  cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema(
66
75
  accuracy_decimals=2,
67
76
  device_class=DEVICE_CLASS_POWER_FACTOR,
@@ -70,7 +79,7 @@ CONFIG_SCHEMA = cv.Schema(
70
79
  }
71
80
  ).extend(uart.UART_DEVICE_SCHEMA)
72
81
  FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
73
- "cse7766", baud_rate=4800, require_rx=True
82
+ "cse7766", baud_rate=4800, parity="EVEN", require_rx=True
74
83
  )
75
84
 
76
85
 
@@ -94,6 +103,9 @@ async def to_code(config):
94
103
  if apparent_power_config := config.get(CONF_APPARENT_POWER):
95
104
  sens = await sensor.new_sensor(apparent_power_config)
96
105
  cg.add(var.set_apparent_power_sensor(sens))
106
+ if reactive_power_config := config.get(CONF_REACTIVE_POWER):
107
+ sens = await sensor.new_sensor(reactive_power_config)
108
+ cg.add(var.set_reactive_power_sensor(sens))
97
109
  if power_factor_config := config.get(CONF_POWER_FACTOR):
98
110
  sens = await sensor.new_sensor(power_factor_config)
99
111
  cg.add(var.set_power_factor_sensor(sens))
@@ -1,12 +1,11 @@
1
+ from esphome import pins
1
2
  import esphome.codegen as cg
3
+ from esphome.components import i2c, touchscreen
2
4
  import esphome.config_validation as cv
5
+ from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_RESET_PIN
3
6
 
4
- from esphome import pins
5
- from esphome.components import i2c, touchscreen
6
- from esphome.const import CONF_INTERRUPT_PIN, CONF_ID, CONF_RESET_PIN
7
7
  from .. import cst816_ns
8
8
 
9
-
10
9
  CST816Touchscreen = cst816_ns.class_(
11
10
  "CST816Touchscreen",
12
11
  touchscreen.Touchscreen,
@@ -14,11 +13,14 @@ CST816Touchscreen = cst816_ns.class_(
14
13
  )
15
14
 
16
15
  CST816ButtonListener = cst816_ns.class_("CST816ButtonListener")
16
+
17
+ CONF_SKIP_PROBE = "skip_probe"
17
18
  CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend(
18
19
  {
19
20
  cv.GenerateID(): cv.declare_id(CST816Touchscreen),
20
21
  cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema,
21
22
  cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
23
+ cv.Optional(CONF_SKIP_PROBE, default=False): cv.boolean,
22
24
  }
23
25
  ).extend(i2c.i2c_device_schema(0x15))
24
26
 
@@ -28,6 +30,7 @@ async def to_code(config):
28
30
  await touchscreen.register_touchscreen(var, config)
29
31
  await i2c.register_i2c_device(var, config)
30
32
 
33
+ cg.add(var.set_skip_probe(config[CONF_SKIP_PROBE]))
31
34
  if interrupt_pin := config.get(CONF_INTERRUPT_PIN):
32
35
  cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin)))
33
36
  if reset_pin := config.get(CONF_RESET_PIN):
@@ -8,32 +8,33 @@ void CST816Touchscreen::continue_setup_() {
8
8
  this->interrupt_pin_->setup();
9
9
  this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE);
10
10
  }
11
- if (!this->read_byte(REG_CHIP_ID, &this->chip_id_)) {
11
+ if (this->read_byte(REG_CHIP_ID, &this->chip_id_)) {
12
+ switch (this->chip_id_) {
13
+ case CST820_CHIP_ID:
14
+ case CST826_CHIP_ID:
15
+ case CST716_CHIP_ID:
16
+ case CST816S_CHIP_ID:
17
+ case CST816D_CHIP_ID:
18
+ case CST816T_CHIP_ID:
19
+ break;
20
+ default:
21
+ this->mark_failed();
22
+ this->status_set_error(str_sprintf("Unknown chip ID 0x%02X", this->chip_id_).c_str());
23
+ return;
24
+ }
25
+ this->write_byte(REG_IRQ_CTL, IRQ_EN_MOTION);
26
+ } else if (!this->skip_probe_) {
27
+ this->status_set_error("Failed to read chip id");
12
28
  this->mark_failed();
13
- esph_log_e(TAG, "Failed to read chip id");
14
29
  return;
15
30
  }
16
- switch (this->chip_id_) {
17
- case CST820_CHIP_ID:
18
- case CST826_CHIP_ID:
19
- case CST716_CHIP_ID:
20
- case CST816S_CHIP_ID:
21
- case CST816D_CHIP_ID:
22
- case CST816T_CHIP_ID:
23
- break;
24
- default:
25
- this->mark_failed();
26
- esph_log_e(TAG, "Unknown chip ID 0x%02X", this->chip_id_);
27
- return;
28
- }
29
- this->write_byte(REG_IRQ_CTL, IRQ_EN_MOTION);
30
31
  if (this->x_raw_max_ == this->x_raw_min_) {
31
32
  this->x_raw_max_ = this->display_->get_native_width();
32
33
  }
33
34
  if (this->y_raw_max_ == this->y_raw_min_) {
34
35
  this->y_raw_max_ = this->display_->get_native_height();
35
36
  }
36
- esph_log_config(TAG, "CST816 Touchscreen setup complete");
37
+ ESP_LOGCONFIG(TAG, "CST816 Touchscreen setup complete");
37
38
  }
38
39
 
39
40
  void CST816Touchscreen::update_button_state_(bool state) {
@@ -45,7 +46,7 @@ void CST816Touchscreen::update_button_state_(bool state) {
45
46
  }
46
47
 
47
48
  void CST816Touchscreen::setup() {
48
- esph_log_config(TAG, "Setting up CST816 Touchscreen...");
49
+ ESP_LOGCONFIG(TAG, "Setting up CST816 Touchscreen...");
49
50
  if (this->reset_pin_ != nullptr) {
50
51
  this->reset_pin_->setup();
51
52
  this->reset_pin_->digital_write(true);
@@ -73,7 +74,7 @@ void CST816Touchscreen::update_touches() {
73
74
 
74
75
  uint16_t x = encode_uint16(data[REG_XPOS_HIGH] & 0xF, data[REG_XPOS_LOW]);
75
76
  uint16_t y = encode_uint16(data[REG_YPOS_HIGH] & 0xF, data[REG_YPOS_LOW]);
76
- esph_log_v(TAG, "Read touch %d/%d", x, y);
77
+ ESP_LOGV(TAG, "Read touch %d/%d", x, y);
77
78
  if (x >= this->x_raw_max_) {
78
79
  this->update_button_state_(true);
79
80
  } else {
@@ -45,6 +45,7 @@ class CST816Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice
45
45
 
46
46
  void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; }
47
47
  void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; }
48
+ void set_skip_probe(bool skip_probe) { this->skip_probe_ = skip_probe; }
48
49
 
49
50
  protected:
50
51
  void continue_setup_();
@@ -53,6 +54,7 @@ class CST816Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice
53
54
  InternalGPIOPin *interrupt_pin_{};
54
55
  GPIOPin *reset_pin_{};
55
56
  uint8_t chip_id_{};
57
+ bool skip_probe_{}; // if set, do not expect to be able to probe the controller on the i2c bus.
56
58
  std::vector<CST816ButtonListener *> button_listeners_;
57
59
  bool button_touched_{};
58
60
  };
@@ -18,7 +18,7 @@ from esphome.const import (
18
18
  CONF_TIME_ID,
19
19
  CONF_TRIGGER_ID,
20
20
  CONF_TYPE,
21
- CONF_WEB_SERVER_ID,
21
+ CONF_WEB_SERVER,
22
22
  CONF_YEAR,
23
23
  )
24
24
  from esphome.core import CORE, coroutine_with_priority
@@ -26,7 +26,6 @@ from esphome.cpp_generator import MockObjClass
26
26
  from esphome.cpp_helpers import setup_entity
27
27
 
28
28
  CODEOWNERS = ["@rfdarter", "@jesserockz"]
29
- DEPENDENCIES = ["time"]
30
29
 
31
30
  IS_PLATFORM_COMPONENT = True
32
31
 
@@ -62,20 +61,28 @@ DATETIME_MODES = [
62
61
  ]
63
62
 
64
63
 
65
- _DATETIME_SCHEMA = (
66
- cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
67
- .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)
68
- .extend(
64
+ def _validate_time_present(config):
65
+ config = config.copy()
66
+ if CONF_ON_TIME in config and CONF_TIME_ID not in config:
67
+ time_id = cv.use_id(time.RealTimeClock)(None)
68
+ config[CONF_TIME_ID] = time_id
69
+ return config
70
+
71
+
72
+ _DATETIME_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
73
+ web_server.WEBSERVER_SORTING_SCHEMA,
74
+ cv.MQTT_COMMAND_COMPONENT_SCHEMA,
75
+ cv.Schema(
69
76
  {
70
77
  cv.Optional(CONF_ON_VALUE): automation.validate_automation(
71
78
  {
72
79
  cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DateTimeStateTrigger),
73
80
  }
74
81
  ),
75
- cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock),
82
+ cv.Optional(CONF_TIME_ID): cv.use_id(time.RealTimeClock),
76
83
  }
77
- )
78
- )
84
+ ),
85
+ ).add_extra(_validate_time_present)
79
86
 
80
87
 
81
88
  def date_schema(class_: MockObjClass) -> cv.Schema:
@@ -131,15 +138,15 @@ async def setup_datetime_core_(var, config):
131
138
  if (mqtt_id := config.get(CONF_MQTT_ID)) is not None:
132
139
  mqtt_ = cg.new_Pvariable(mqtt_id, var)
133
140
  await mqtt.register_mqtt_component(mqtt_, config)
134
- if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None:
135
- web_server_ = await cg.get_variable(webserver_id)
136
- web_server.add_entity_to_sorting_list(web_server_, var, config)
141
+ if web_server_config := config.get(CONF_WEB_SERVER):
142
+ await web_server.add_entity_config(var, web_server_config)
137
143
  for conf in config.get(CONF_ON_VALUE, []):
138
144
  trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
139
145
  await automation.build_automation(trigger, [(cg.ESPTime, "x")], conf)
140
146
 
141
- rtc = await cg.get_variable(config[CONF_TIME_ID])
142
- cg.add(var.set_rtc(rtc))
147
+ if CONF_TIME_ID in config:
148
+ rtc = await cg.get_variable(config[CONF_TIME_ID])
149
+ cg.add(var.set_rtc(rtc))
143
150
 
144
151
  for conf in config.get(CONF_ON_TIME, []):
145
152
  trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID])
@@ -4,8 +4,9 @@
4
4
  #include "esphome/core/component.h"
5
5
  #include "esphome/core/entity_base.h"
6
6
  #include "esphome/core/time.h"
7
-
7
+ #ifdef USE_TIME
8
8
  #include "esphome/components/time/real_time_clock.h"
9
+ #endif
9
10
 
10
11
  namespace esphome {
11
12
  namespace datetime {
@@ -19,23 +20,29 @@ class DateTimeBase : public EntityBase {
19
20
 
20
21
  void add_on_state_callback(std::function<void()> &&callback) { this->state_callback_.add(std::move(callback)); }
21
22
 
23
+ #ifdef USE_TIME
22
24
  void set_rtc(time::RealTimeClock *rtc) { this->rtc_ = rtc; }
23
25
  time::RealTimeClock *get_rtc() const { return this->rtc_; }
26
+ #endif
24
27
 
25
28
  protected:
26
29
  CallbackManager<void()> state_callback_;
27
30
 
31
+ #ifdef USE_TIME
28
32
  time::RealTimeClock *rtc_;
33
+ #endif
29
34
 
30
35
  bool has_state_{false};
31
36
  };
32
37
 
38
+ #ifdef USE_TIME
33
39
  class DateTimeStateTrigger : public Trigger<ESPTime> {
34
40
  public:
35
41
  explicit DateTimeStateTrigger(DateTimeBase *parent) {
36
42
  parent->add_on_state_callback([this, parent]() { this->trigger(parent->state_as_esptime()); });
37
43
  }
38
44
  };
45
+ #endif
39
46
 
40
47
  } // namespace datetime
41
48
  } // namespace esphome
@@ -192,6 +192,7 @@ void DateTimeEntityRestoreState::apply(DateTimeEntity *time) {
192
192
  time->publish_state();
193
193
  }
194
194
 
195
+ #ifdef USE_TIME
195
196
  static const int MAX_TIMESTAMP_DRIFT = 900; // how far can the clock drift before we consider
196
197
  // there has been a drastic time synchronization
197
198
 
@@ -245,6 +246,7 @@ bool OnDateTimeTrigger::matches_(const ESPTime &time) const {
245
246
  time.day_of_month == this->parent_->day && time.hour == this->parent_->hour &&
246
247
  time.minute == this->parent_->minute && time.second == this->parent_->second;
247
248
  }
249
+ #endif
248
250
 
249
251
  } // namespace datetime
250
252
  } // namespace esphome
@@ -134,6 +134,7 @@ template<typename... Ts> class DateTimeSetAction : public Action<Ts...>, public
134
134
  }
135
135
  };
136
136
 
137
+ #ifdef USE_TIME
137
138
  class OnDateTimeTrigger : public Trigger<>, public Component, public Parented<DateTimeEntity> {
138
139
  public:
139
140
  void loop() override;
@@ -143,6 +144,7 @@ class OnDateTimeTrigger : public Trigger<>, public Component, public Parented<Da
143
144
 
144
145
  optional<ESPTime> last_check_;
145
146
  };
147
+ #endif
146
148
 
147
149
  } // namespace datetime
148
150
  } // namespace esphome
@@ -94,6 +94,7 @@ void TimeEntityRestoreState::apply(TimeEntity *time) {
94
94
  time->publish_state();
95
95
  }
96
96
 
97
+ #ifdef USE_TIME
97
98
  static const int MAX_TIMESTAMP_DRIFT = 900; // how far can the clock drift before we consider
98
99
  // there has been a drastic time synchronization
99
100
 
@@ -145,6 +146,7 @@ bool OnTimeTrigger::matches_(const ESPTime &time) const {
145
146
  return time.is_valid() && time.hour == this->parent_->hour && time.minute == this->parent_->minute &&
146
147
  time.second == this->parent_->second;
147
148
  }
149
+ #endif
148
150
 
149
151
  } // namespace datetime
150
152
  } // namespace esphome
@@ -113,6 +113,7 @@ template<typename... Ts> class TimeSetAction : public Action<Ts...>, public Pare
113
113
  }
114
114
  };
115
115
 
116
+ #ifdef USE_TIME
116
117
  class OnTimeTrigger : public Trigger<>, public Component, public Parented<TimeEntity> {
117
118
  public:
118
119
  void loop() override;
@@ -122,6 +123,7 @@ class OnTimeTrigger : public Trigger<>, public Component, public Parented<TimeEn
122
123
 
123
124
  optional<ESPTime> last_check_;
124
125
  };
126
+ #endif
125
127
 
126
128
  } // namespace datetime
127
129
  } // namespace esphome
@@ -13,6 +13,7 @@ from esphome.const import (
13
13
  CONF_COMPONENTS,
14
14
  CONF_ESPHOME,
15
15
  CONF_FRAMEWORK,
16
+ CONF_IGNORE_EFUSE_CUSTOM_MAC,
16
17
  CONF_IGNORE_EFUSE_MAC_CRC,
17
18
  CONF_NAME,
18
19
  CONF_PATH,
@@ -52,6 +53,7 @@ from .const import ( # noqa
52
53
  KEY_SDKCONFIG_OPTIONS,
53
54
  KEY_SUBMODULES,
54
55
  KEY_VARIANT,
56
+ VARIANT_ESP32,
55
57
  VARIANT_FRIENDLY,
56
58
  VARIANTS,
57
59
  )
@@ -239,7 +241,7 @@ ARDUINO_PLATFORM_VERSION = cv.Version(5, 4, 0)
239
241
  # The default/recommended esp-idf framework version
240
242
  # - https://github.com/espressif/esp-idf/releases
241
243
  # - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf
242
- RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 7)
244
+ RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 8)
243
245
  # The platformio/espressif32 version to use for esp-idf frameworks
244
246
  # - https://github.com/platformio/platform-espressif32/releases
245
247
  # - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
@@ -375,6 +377,15 @@ def final_validate(config):
375
377
  f"Please specify {CONF_FLASH_SIZE} within esp32 configuration only"
376
378
  )
377
379
 
380
+ if (
381
+ config[CONF_VARIANT] != VARIANT_ESP32
382
+ and CONF_ADVANCED in (conf_fw := config[CONF_FRAMEWORK])
383
+ and CONF_IGNORE_EFUSE_MAC_CRC in conf_fw[CONF_ADVANCED]
384
+ ):
385
+ raise cv.Invalid(
386
+ f"{CONF_IGNORE_EFUSE_MAC_CRC} is not supported on {config[CONF_VARIANT]}"
387
+ )
388
+
378
389
  return config
379
390
 
380
391
 
@@ -401,7 +412,10 @@ ESP_IDF_FRAMEWORK_SCHEMA = cv.All(
401
412
  },
402
413
  cv.Optional(CONF_ADVANCED, default={}): cv.Schema(
403
414
  {
404
- cv.Optional(CONF_IGNORE_EFUSE_MAC_CRC, default=False): cv.boolean,
415
+ cv.Optional(
416
+ CONF_IGNORE_EFUSE_CUSTOM_MAC, default=False
417
+ ): cv.boolean,
418
+ cv.Optional(CONF_IGNORE_EFUSE_MAC_CRC): cv.boolean,
405
419
  }
406
420
  ),
407
421
  cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list(
@@ -526,8 +540,10 @@ async def to_code(config):
526
540
  for name, value in conf[CONF_SDKCONFIG_OPTIONS].items():
527
541
  add_idf_sdkconfig_option(name, RawSdkconfigValue(value))
528
542
 
529
- if conf[CONF_ADVANCED][CONF_IGNORE_EFUSE_MAC_CRC]:
530
- cg.add_define("USE_ESP32_IGNORE_EFUSE_MAC_CRC")
543
+ if conf[CONF_ADVANCED][CONF_IGNORE_EFUSE_CUSTOM_MAC]:
544
+ cg.add_define("USE_ESP32_IGNORE_EFUSE_CUSTOM_MAC")
545
+ if conf[CONF_ADVANCED].get(CONF_IGNORE_EFUSE_MAC_CRC):
546
+ add_idf_sdkconfig_option("CONFIG_ESP_MAC_IGNORE_MAC_CRC_ERROR", True)
531
547
  if (framework_ver.major, framework_ver.minor) >= (4, 4):
532
548
  add_idf_sdkconfig_option(
533
549
  "CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False
@@ -1,7 +1,8 @@
1
+ from esphome import automation
1
2
  import esphome.codegen as cg
2
3
  from esphome.components import binary_sensor, esp32_ble_server, output
3
4
  import esphome.config_validation as cv
4
- from esphome.const import CONF_ID
5
+ from esphome.const import CONF_ID, CONF_ON_STATE, CONF_TRIGGER_ID
5
6
 
6
7
  AUTO_LOAD = ["esp32_ble_server"]
7
8
  CODEOWNERS = ["@jesserockz"]
@@ -11,13 +12,36 @@ CONF_AUTHORIZED_DURATION = "authorized_duration"
11
12
  CONF_AUTHORIZER = "authorizer"
12
13
  CONF_BLE_SERVER_ID = "ble_server_id"
13
14
  CONF_IDENTIFY_DURATION = "identify_duration"
15
+ CONF_ON_PROVISIONED = "on_provisioned"
16
+ CONF_ON_PROVISIONING = "on_provisioning"
17
+ CONF_ON_START = "on_start"
18
+ CONF_ON_STOP = "on_stop"
14
19
  CONF_STATUS_INDICATOR = "status_indicator"
15
20
  CONF_WIFI_TIMEOUT = "wifi_timeout"
16
21
 
22
+ improv_ns = cg.esphome_ns.namespace("improv")
23
+ Error = improv_ns.enum("Error")
24
+ State = improv_ns.enum("State")
25
+
17
26
  esp32_improv_ns = cg.esphome_ns.namespace("esp32_improv")
18
27
  ESP32ImprovComponent = esp32_improv_ns.class_(
19
28
  "ESP32ImprovComponent", cg.Component, esp32_ble_server.BLEServiceComponent
20
29
  )
30
+ ESP32ImprovProvisionedTrigger = esp32_improv_ns.class_(
31
+ "ESP32ImprovProvisionedTrigger", automation.Trigger.template()
32
+ )
33
+ ESP32ImprovProvisioningTrigger = esp32_improv_ns.class_(
34
+ "ESP32ImprovProvisioningTrigger", automation.Trigger.template()
35
+ )
36
+ ESP32ImprovStartTrigger = esp32_improv_ns.class_(
37
+ "ESP32ImprovStartTrigger", automation.Trigger.template()
38
+ )
39
+ ESP32ImprovStateTrigger = esp32_improv_ns.class_(
40
+ "ESP32ImprovStateTrigger", automation.Trigger.template()
41
+ )
42
+ ESP32ImprovStoppedTrigger = esp32_improv_ns.class_(
43
+ "ESP32ImprovStoppedTrigger", automation.Trigger.template()
44
+ )
21
45
 
22
46
 
23
47
  CONFIG_SCHEMA = cv.Schema(
@@ -37,6 +61,37 @@ CONFIG_SCHEMA = cv.Schema(
37
61
  cv.Optional(
38
62
  CONF_WIFI_TIMEOUT, default="1min"
39
63
  ): cv.positive_time_period_milliseconds,
64
+ cv.Optional(CONF_ON_PROVISIONED): automation.validate_automation(
65
+ {
66
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
67
+ ESP32ImprovProvisionedTrigger
68
+ ),
69
+ }
70
+ ),
71
+ cv.Optional(CONF_ON_PROVISIONING): automation.validate_automation(
72
+ {
73
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
74
+ ESP32ImprovProvisioningTrigger
75
+ ),
76
+ }
77
+ ),
78
+ cv.Optional(CONF_ON_START): automation.validate_automation(
79
+ {
80
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESP32ImprovStartTrigger),
81
+ }
82
+ ),
83
+ cv.Optional(CONF_ON_STATE): automation.validate_automation(
84
+ {
85
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESP32ImprovStateTrigger),
86
+ }
87
+ ),
88
+ cv.Optional(CONF_ON_STOP): automation.validate_automation(
89
+ {
90
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
91
+ ESP32ImprovStoppedTrigger
92
+ ),
93
+ }
94
+ ),
40
95
  }
41
96
  ).extend(cv.COMPONENT_SCHEMA)
42
97
 
@@ -63,3 +118,29 @@ async def to_code(config):
63
118
  if CONF_STATUS_INDICATOR in config:
64
119
  status_indicator = await cg.get_variable(config[CONF_STATUS_INDICATOR])
65
120
  cg.add(var.set_status_indicator(status_indicator))
121
+
122
+ use_state_callback = False
123
+ for conf in config.get(CONF_ON_PROVISIONED, []):
124
+ trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
125
+ await automation.build_automation(trigger, [], conf)
126
+ use_state_callback = True
127
+ for conf in config.get(CONF_ON_PROVISIONING, []):
128
+ trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
129
+ await automation.build_automation(trigger, [], conf)
130
+ use_state_callback = True
131
+ for conf in config.get(CONF_ON_START, []):
132
+ trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
133
+ await automation.build_automation(trigger, [], conf)
134
+ use_state_callback = True
135
+ for conf in config.get(CONF_ON_STATE, []):
136
+ trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
137
+ await automation.build_automation(
138
+ trigger, [(State, "state"), (Error, "error")], conf
139
+ )
140
+ use_state_callback = True
141
+ for conf in config.get(CONF_ON_STOP, []):
142
+ trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
143
+ await automation.build_automation(trigger, [], conf)
144
+ use_state_callback = True
145
+ if use_state_callback:
146
+ cg.add_define("USE_ESP32_IMPROV_STATE_CALLBACK")
@@ -0,0 +1,72 @@
1
+ #pragma once
2
+ #ifdef USE_ESP32
3
+ #ifdef USE_ESP32_IMPROV_STATE_CALLBACK
4
+ #include "esp32_improv_component.h"
5
+
6
+ #include "esphome/core/automation.h"
7
+
8
+ #include <improv.h>
9
+
10
+ namespace esphome {
11
+ namespace esp32_improv {
12
+
13
+ class ESP32ImprovProvisionedTrigger : public Trigger<> {
14
+ public:
15
+ explicit ESP32ImprovProvisionedTrigger(ESP32ImprovComponent *parent) {
16
+ parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) {
17
+ if (state == improv::STATE_PROVISIONED && !parent->is_failed()) {
18
+ trigger();
19
+ }
20
+ });
21
+ }
22
+ };
23
+
24
+ class ESP32ImprovProvisioningTrigger : public Trigger<> {
25
+ public:
26
+ explicit ESP32ImprovProvisioningTrigger(ESP32ImprovComponent *parent) {
27
+ parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) {
28
+ if (state == improv::STATE_PROVISIONING && !parent->is_failed()) {
29
+ trigger();
30
+ }
31
+ });
32
+ }
33
+ };
34
+
35
+ class ESP32ImprovStartTrigger : public Trigger<> {
36
+ public:
37
+ explicit ESP32ImprovStartTrigger(ESP32ImprovComponent *parent) {
38
+ parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) {
39
+ if ((state == improv::STATE_AUTHORIZED || state == improv::STATE_AWAITING_AUTHORIZATION) &&
40
+ !parent->is_failed()) {
41
+ trigger();
42
+ }
43
+ });
44
+ }
45
+ };
46
+
47
+ class ESP32ImprovStateTrigger : public Trigger<improv::State, improv::Error> {
48
+ public:
49
+ explicit ESP32ImprovStateTrigger(ESP32ImprovComponent *parent) {
50
+ parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) {
51
+ if (!parent->is_failed()) {
52
+ trigger(state, error);
53
+ }
54
+ });
55
+ }
56
+ };
57
+
58
+ class ESP32ImprovStoppedTrigger : public Trigger<> {
59
+ public:
60
+ explicit ESP32ImprovStoppedTrigger(ESP32ImprovComponent *parent) {
61
+ parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) {
62
+ if (state == improv::STATE_STOPPED && !parent->is_failed()) {
63
+ trigger();
64
+ }
65
+ });
66
+ }
67
+ };
68
+
69
+ } // namespace esp32_improv
70
+ } // namespace esphome
71
+ #endif
72
+ #endif
@@ -68,7 +68,12 @@ void ESP32ImprovComponent::setup_characteristics() {
68
68
 
69
69
  void ESP32ImprovComponent::loop() {
70
70
  if (!global_ble_server->is_running()) {
71
- this->state_ = improv::STATE_STOPPED;
71
+ if (this->state_ != improv::STATE_STOPPED) {
72
+ this->state_ = improv::STATE_STOPPED;
73
+ #ifdef USE_ESP32_IMPROV_STATE_CALLBACK
74
+ this->state_callback_.call(this->state_, this->error_state_);
75
+ #endif
76
+ }
72
77
  this->incoming_data_.clear();
73
78
  return;
74
79
  }
@@ -217,6 +222,9 @@ void ESP32ImprovComponent::set_state_(improv::State state) {
217
222
  service_data[7] = 0x00; // Reserved
218
223
 
219
224
  esp32_ble::global_ble->advertising_set_service_data(service_data);
225
+ #ifdef USE_ESP32_IMPROV_STATE_CALLBACK
226
+ this->state_callback_.call(this->state_, this->error_state_);
227
+ #endif
220
228
  }
221
229
 
222
230
  void ESP32ImprovComponent::set_error_(improv::Error error) {
@@ -270,7 +278,7 @@ void ESP32ImprovComponent::dump_config() {
270
278
  void ESP32ImprovComponent::process_incoming_data_() {
271
279
  uint8_t length = this->incoming_data_[1];
272
280
 
273
- ESP_LOGD(TAG, "Processing bytes - %s", format_hex_pretty(this->incoming_data_).c_str());
281
+ ESP_LOGV(TAG, "Processing bytes - %s", format_hex_pretty(this->incoming_data_).c_str());
274
282
  if (this->incoming_data_.size() - 3 == length) {
275
283
  this->set_error_(improv::ERROR_NONE);
276
284
  improv::ImprovCommand command = improv::parse_improv_data(this->incoming_data_);
@@ -295,7 +303,7 @@ void ESP32ImprovComponent::process_incoming_data_() {
295
303
  wifi::global_wifi_component->set_sta(sta);
296
304
  wifi::global_wifi_component->start_connecting(sta, false);
297
305
  this->set_state_(improv::STATE_PROVISIONING);
298
- ESP_LOGD(TAG, "Received Improv wifi settings ssid=%s, password=" LOG_SECRET("%s"), command.ssid.c_str(),
306
+ ESP_LOGD(TAG, "Received Improv Wi-Fi settings ssid=%s, password=" LOG_SECRET("%s"), command.ssid.c_str(),
299
307
  command.password.c_str());
300
308
 
301
309
  auto f = std::bind(&ESP32ImprovComponent::on_wifi_connect_timeout_, this);
@@ -313,7 +321,7 @@ void ESP32ImprovComponent::process_incoming_data_() {
313
321
  this->incoming_data_.clear();
314
322
  }
315
323
  } else if (this->incoming_data_.size() - 2 > length) {
316
- ESP_LOGV(TAG, "Too much data came in, or malformed resetting buffer...");
324
+ ESP_LOGV(TAG, "Too much data received or data malformed; resetting buffer...");
317
325
  this->incoming_data_.clear();
318
326
  } else {
319
327
  ESP_LOGV(TAG, "Waiting for split data packets...");
@@ -327,7 +335,7 @@ void ESP32ImprovComponent::on_wifi_connect_timeout_() {
327
335
  if (this->authorizer_ != nullptr)
328
336
  this->authorized_start_ = millis();
329
337
  #endif
330
- ESP_LOGW(TAG, "Timed out trying to connect to given WiFi network");
338
+ ESP_LOGW(TAG, "Timed out while connecting to Wi-Fi network");
331
339
  wifi::global_wifi_component->clear_sta();
332
340
  }
333
341