esphome 2024.6.6__py3-none-any.whl → 2024.7.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 (102) hide show
  1. esphome/components/aht10/aht10.cpp +4 -2
  2. esphome/components/climate/climate.cpp +10 -6
  3. esphome/components/climate/climate_traits.h +3 -3
  4. esphome/components/cover/cover.h +2 -2
  5. esphome/components/esp32_camera/__init__.py +6 -3
  6. esphome/components/esp32_can/canbus.py +3 -0
  7. esphome/components/ethernet/ethernet_component.cpp +8 -3
  8. esphome/components/font/__init__.py +2 -28
  9. esphome/components/gree/climate.py +1 -0
  10. esphome/components/gree/gree.cpp +11 -3
  11. esphome/components/gree/gree.h +5 -1
  12. esphome/components/haier/binary_sensor/__init__.py +4 -4
  13. esphome/components/haier/button/__init__.py +1 -1
  14. esphome/components/haier/climate.py +43 -9
  15. esphome/components/haier/haier_base.cpp +4 -0
  16. esphome/components/haier/haier_base.h +11 -1
  17. esphome/components/haier/hon_climate.cpp +109 -55
  18. esphome/components/haier/hon_climate.h +7 -1
  19. esphome/components/haier/hon_packet.h +5 -0
  20. esphome/components/haier/sensor/__init__.py +5 -5
  21. esphome/components/haier/smartair2_climate.cpp +1 -0
  22. esphome/components/haier/text_sensor/__init__.py +4 -4
  23. esphome/components/heatpumpir/climate.py +12 -5
  24. esphome/components/heatpumpir/heatpumpir.cpp +11 -0
  25. esphome/components/heatpumpir/heatpumpir.h +11 -0
  26. esphome/components/http_request/http_request_arduino.cpp +7 -2
  27. esphome/components/http_request/update/http_request_update.cpp +6 -7
  28. esphome/components/http_request/update/http_request_update.h +0 -3
  29. esphome/components/i2s_audio/__init__.py +10 -0
  30. esphome/components/i2s_audio/microphone/__init__.py +7 -0
  31. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +2 -3
  32. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +3 -0
  33. esphome/components/image/__init__.py +2 -29
  34. esphome/components/improv_serial/improv_serial_component.cpp +9 -8
  35. esphome/components/ltr390/ltr390.cpp +44 -29
  36. esphome/components/ltr390/ltr390.h +9 -5
  37. esphome/components/ltr390/sensor.py +35 -5
  38. esphome/components/mdns/__init__.py +3 -3
  39. esphome/components/mdns/mdns_component.cpp +3 -1
  40. esphome/components/mdns/mdns_component.h +3 -1
  41. esphome/components/mdns/mdns_esp32.cpp +2 -1
  42. esphome/components/mdns/mdns_esp8266.cpp +2 -1
  43. esphome/components/mdns/mdns_host.cpp +2 -1
  44. esphome/components/mdns/mdns_libretiny.cpp +2 -1
  45. esphome/components/mdns/mdns_rp2040.cpp +2 -1
  46. esphome/components/micro_wake_word/__init__.py +205 -56
  47. esphome/components/micro_wake_word/micro_wake_word.cpp +225 -275
  48. esphome/components/micro_wake_word/micro_wake_word.h +77 -107
  49. esphome/components/micro_wake_word/preprocessor_settings.h +20 -0
  50. esphome/components/micro_wake_word/streaming_model.cpp +189 -0
  51. esphome/components/micro_wake_word/streaming_model.h +84 -0
  52. esphome/components/mitsubishi/mitsubishi.cpp +1 -0
  53. esphome/components/modbus_controller/text_sensor/__init__.py +2 -1
  54. esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp +4 -1
  55. esphome/components/modbus_controller/text_sensor/modbus_textsensor.h +1 -1
  56. esphome/components/number/__init__.py +2 -0
  57. esphome/components/ota/ota_backend_arduino_esp32.cpp +22 -7
  58. esphome/components/ota/ota_backend_arduino_esp8266.cpp +23 -8
  59. esphome/components/ota/ota_backend_arduino_libretiny.cpp +22 -7
  60. esphome/components/ota/ota_backend_arduino_rp2040.cpp +22 -7
  61. esphome/components/pmsa003i/pmsa003i.cpp +9 -0
  62. esphome/components/qspi_amoled/display.py +16 -4
  63. esphome/components/qspi_amoled/qspi_amoled.cpp +16 -0
  64. esphome/components/qspi_amoled/qspi_amoled.h +0 -3
  65. esphome/components/remote_base/dooya_protocol.cpp +4 -4
  66. esphome/components/remote_base/rc_switch_protocol.cpp +1 -1
  67. esphome/components/restart/button/__init__.py +2 -0
  68. esphome/components/script/__init__.py +1 -1
  69. esphome/components/sensor/__init__.py +2 -0
  70. esphome/components/tuya/tuya.cpp +8 -2
  71. esphome/components/tuya/tuya.h +3 -1
  72. esphome/components/uart/__init__.py +72 -9
  73. esphome/components/uart/uart_component_esp32_arduino.cpp +18 -4
  74. esphome/components/uart/uart_component_esp_idf.cpp +22 -2
  75. esphome/components/uart/uart_component_host.cpp +295 -0
  76. esphome/components/uart/uart_component_host.h +38 -0
  77. esphome/components/uptime/sensor.py +44 -11
  78. esphome/components/uptime/{uptime_sensor.cpp → uptime_seconds_sensor.cpp} +11 -7
  79. esphome/components/uptime/{uptime_sensor.h → uptime_seconds_sensor.h} +2 -2
  80. esphome/components/uptime/uptime_timestamp_sensor.cpp +39 -0
  81. esphome/components/uptime/uptime_timestamp_sensor.h +30 -0
  82. esphome/components/veml7700/veml7700.cpp +1 -1
  83. esphome/components/veml7700/veml7700.h +5 -5
  84. esphome/components/voice_assistant/voice_assistant.cpp +4 -2
  85. esphome/components/web_server/server_index_v2.h +42 -41
  86. esphome/components/web_server/server_index_v3.h +368 -367
  87. esphome/components/wifi/wifi_component_esp_idf.cpp +1 -1
  88. esphome/components/wifi/wifi_component_pico_w.cpp +18 -2
  89. esphome/components/wireguard/__init__.py +1 -1
  90. esphome/components/x9c/output.py +7 -1
  91. esphome/const.py +2 -1
  92. esphome/core/defines.h +1 -0
  93. esphome/core/helpers.cpp +2 -2
  94. esphome/core/helpers.h +1 -1
  95. esphome/external_files.py +26 -0
  96. {esphome-2024.6.6.dist-info → esphome-2024.7.0.dist-info}/METADATA +1 -1
  97. {esphome-2024.6.6.dist-info → esphome-2024.7.0.dist-info}/RECORD +101 -95
  98. esphome/components/micro_wake_word/audio_preprocessor_int8_model_data.h +0 -493
  99. {esphome-2024.6.6.dist-info → esphome-2024.7.0.dist-info}/LICENSE +0 -0
  100. {esphome-2024.6.6.dist-info → esphome-2024.7.0.dist-info}/WHEEL +0 -0
  101. {esphome-2024.6.6.dist-info → esphome-2024.7.0.dist-info}/entry_points.txt +0 -0
  102. {esphome-2024.6.6.dist-info → esphome-2024.7.0.dist-info}/top_level.txt +0 -0
@@ -1,14 +1,17 @@
1
1
  #ifdef USE_ESP32_FRAMEWORK_ARDUINO
2
2
  #include "esphome/core/defines.h"
3
+ #include "esphome/core/log.h"
3
4
 
4
- #include "ota_backend_arduino_esp32.h"
5
5
  #include "ota_backend.h"
6
+ #include "ota_backend_arduino_esp32.h"
6
7
 
7
8
  #include <Update.h>
8
9
 
9
10
  namespace esphome {
10
11
  namespace ota {
11
12
 
13
+ static const char *const TAG = "ota.arduino_esp32";
14
+
12
15
  std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoESP32OTABackend>(); }
13
16
 
14
17
  OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) {
@@ -20,6 +23,9 @@ OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) {
20
23
  uint8_t error = Update.getError();
21
24
  if (error == UPDATE_ERROR_SIZE)
22
25
  return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE;
26
+
27
+ ESP_LOGE(TAG, "Begin error: %d", error);
28
+
23
29
  return OTA_RESPONSE_ERROR_UNKNOWN;
24
30
  }
25
31
 
@@ -27,16 +33,25 @@ void ArduinoESP32OTABackend::set_update_md5(const char *md5) { Update.setMD5(md5
27
33
 
28
34
  OTAResponseTypes ArduinoESP32OTABackend::write(uint8_t *data, size_t len) {
29
35
  size_t written = Update.write(data, len);
30
- if (written != len) {
31
- return OTA_RESPONSE_ERROR_WRITING_FLASH;
36
+ if (written == len) {
37
+ return OTA_RESPONSE_OK;
32
38
  }
33
- return OTA_RESPONSE_OK;
39
+
40
+ uint8_t error = Update.getError();
41
+ ESP_LOGE(TAG, "Write error: %d", error);
42
+
43
+ return OTA_RESPONSE_ERROR_WRITING_FLASH;
34
44
  }
35
45
 
36
46
  OTAResponseTypes ArduinoESP32OTABackend::end() {
37
- if (!Update.end())
38
- return OTA_RESPONSE_ERROR_UPDATE_END;
39
- return OTA_RESPONSE_OK;
47
+ if (Update.end()) {
48
+ return OTA_RESPONSE_OK;
49
+ }
50
+
51
+ uint8_t error = Update.getError();
52
+ ESP_LOGE(TAG, "End error: %d", error);
53
+
54
+ return OTA_RESPONSE_ERROR_UPDATE_END;
40
55
  }
41
56
 
42
57
  void ArduinoESP32OTABackend::abort() { Update.abort(); }
@@ -1,16 +1,19 @@
1
1
  #ifdef USE_ARDUINO
2
2
  #ifdef USE_ESP8266
3
- #include "ota_backend.h"
4
3
  #include "ota_backend_arduino_esp8266.h"
4
+ #include "ota_backend.h"
5
5
 
6
- #include "esphome/core/defines.h"
7
6
  #include "esphome/components/esp8266/preferences.h"
7
+ #include "esphome/core/defines.h"
8
+ #include "esphome/core/log.h"
8
9
 
9
10
  #include <Updater.h>
10
11
 
11
12
  namespace esphome {
12
13
  namespace ota {
13
14
 
15
+ static const char *const TAG = "ota.arduino_esp8266";
16
+
14
17
  std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoESP8266OTABackend>(); }
15
18
 
16
19
  OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) {
@@ -29,6 +32,9 @@ OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) {
29
32
  return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG;
30
33
  if (error == UPDATE_ERROR_SPACE)
31
34
  return OTA_RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE;
35
+
36
+ ESP_LOGE(TAG, "Begin error: %d", error);
37
+
32
38
  return OTA_RESPONSE_ERROR_UNKNOWN;
33
39
  }
34
40
 
@@ -36,16 +42,25 @@ void ArduinoESP8266OTABackend::set_update_md5(const char *md5) { Update.setMD5(m
36
42
 
37
43
  OTAResponseTypes ArduinoESP8266OTABackend::write(uint8_t *data, size_t len) {
38
44
  size_t written = Update.write(data, len);
39
- if (written != len) {
40
- return OTA_RESPONSE_ERROR_WRITING_FLASH;
45
+ if (written == len) {
46
+ return OTA_RESPONSE_OK;
41
47
  }
42
- return OTA_RESPONSE_OK;
48
+
49
+ uint8_t error = Update.getError();
50
+ ESP_LOGE(TAG, "Write error: %d", error);
51
+
52
+ return OTA_RESPONSE_ERROR_WRITING_FLASH;
43
53
  }
44
54
 
45
55
  OTAResponseTypes ArduinoESP8266OTABackend::end() {
46
- if (!Update.end())
47
- return OTA_RESPONSE_ERROR_UPDATE_END;
48
- return OTA_RESPONSE_OK;
56
+ if (Update.end()) {
57
+ return OTA_RESPONSE_OK;
58
+ }
59
+
60
+ uint8_t error = Update.getError();
61
+ ESP_LOGE(TAG, "End error: %d", error);
62
+
63
+ return OTA_RESPONSE_ERROR_UPDATE_END;
49
64
  }
50
65
 
51
66
  void ArduinoESP8266OTABackend::abort() {
@@ -1,14 +1,17 @@
1
1
  #ifdef USE_LIBRETINY
2
- #include "ota_backend.h"
3
2
  #include "ota_backend_arduino_libretiny.h"
3
+ #include "ota_backend.h"
4
4
 
5
5
  #include "esphome/core/defines.h"
6
+ #include "esphome/core/log.h"
6
7
 
7
8
  #include <Update.h>
8
9
 
9
10
  namespace esphome {
10
11
  namespace ota {
11
12
 
13
+ static const char *const TAG = "ota.arduino_libretiny";
14
+
12
15
  std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoLibreTinyOTABackend>(); }
13
16
 
14
17
  OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) {
@@ -20,6 +23,9 @@ OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) {
20
23
  uint8_t error = Update.getError();
21
24
  if (error == UPDATE_ERROR_SIZE)
22
25
  return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE;
26
+
27
+ ESP_LOGE(TAG, "Begin error: %d", error);
28
+
23
29
  return OTA_RESPONSE_ERROR_UNKNOWN;
24
30
  }
25
31
 
@@ -27,16 +33,25 @@ void ArduinoLibreTinyOTABackend::set_update_md5(const char *md5) { Update.setMD5
27
33
 
28
34
  OTAResponseTypes ArduinoLibreTinyOTABackend::write(uint8_t *data, size_t len) {
29
35
  size_t written = Update.write(data, len);
30
- if (written != len) {
31
- return OTA_RESPONSE_ERROR_WRITING_FLASH;
36
+ if (written == len) {
37
+ return OTA_RESPONSE_OK;
32
38
  }
33
- return OTA_RESPONSE_OK;
39
+
40
+ uint8_t error = Update.getError();
41
+ ESP_LOGE(TAG, "Write error: %d", error);
42
+
43
+ return OTA_RESPONSE_ERROR_WRITING_FLASH;
34
44
  }
35
45
 
36
46
  OTAResponseTypes ArduinoLibreTinyOTABackend::end() {
37
- if (!Update.end())
38
- return OTA_RESPONSE_ERROR_UPDATE_END;
39
- return OTA_RESPONSE_OK;
47
+ if (Update.end()) {
48
+ return OTA_RESPONSE_OK;
49
+ }
50
+
51
+ uint8_t error = Update.getError();
52
+ ESP_LOGE(TAG, "End error: %d", error);
53
+
54
+ return OTA_RESPONSE_ERROR_UPDATE_END;
40
55
  }
41
56
 
42
57
  void ArduinoLibreTinyOTABackend::abort() { Update.abort(); }
@@ -1,16 +1,19 @@
1
1
  #ifdef USE_ARDUINO
2
2
  #ifdef USE_RP2040
3
- #include "ota_backend.h"
4
3
  #include "ota_backend_arduino_rp2040.h"
4
+ #include "ota_backend.h"
5
5
 
6
6
  #include "esphome/components/rp2040/preferences.h"
7
7
  #include "esphome/core/defines.h"
8
+ #include "esphome/core/log.h"
8
9
 
9
10
  #include <Updater.h>
10
11
 
11
12
  namespace esphome {
12
13
  namespace ota {
13
14
 
15
+ static const char *const TAG = "ota.arduino_rp2040";
16
+
14
17
  std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoRP2040OTABackend>(); }
15
18
 
16
19
  OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) {
@@ -29,6 +32,9 @@ OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) {
29
32
  return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG;
30
33
  if (error == UPDATE_ERROR_SPACE)
31
34
  return OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE;
35
+
36
+ ESP_LOGE(TAG, "Begin error: %d", error);
37
+
32
38
  return OTA_RESPONSE_ERROR_UNKNOWN;
33
39
  }
34
40
 
@@ -36,16 +42,25 @@ void ArduinoRP2040OTABackend::set_update_md5(const char *md5) { Update.setMD5(md
36
42
 
37
43
  OTAResponseTypes ArduinoRP2040OTABackend::write(uint8_t *data, size_t len) {
38
44
  size_t written = Update.write(data, len);
39
- if (written != len) {
40
- return OTA_RESPONSE_ERROR_WRITING_FLASH;
45
+ if (written == len) {
46
+ return OTA_RESPONSE_OK;
41
47
  }
42
- return OTA_RESPONSE_OK;
48
+
49
+ uint8_t error = Update.getError();
50
+ ESP_LOGE(TAG, "Write error: %d", error);
51
+
52
+ return OTA_RESPONSE_ERROR_WRITING_FLASH;
43
53
  }
44
54
 
45
55
  OTAResponseTypes ArduinoRP2040OTABackend::end() {
46
- if (!Update.end())
47
- return OTA_RESPONSE_ERROR_UPDATE_END;
48
- return OTA_RESPONSE_OK;
56
+ if (Update.end()) {
57
+ return OTA_RESPONSE_OK;
58
+ }
59
+
60
+ uint8_t error = Update.getError();
61
+ ESP_LOGE(TAG, "End error: %d", error);
62
+
63
+ return OTA_RESPONSE_ERROR_UPDATE_END;
49
64
  }
50
65
 
51
66
  void ArduinoRP2040OTABackend::abort() {
@@ -13,6 +13,15 @@ void PMSA003IComponent::setup() {
13
13
  PM25AQIData data;
14
14
  bool successful_read = this->read_data_(&data);
15
15
 
16
+ if (!successful_read) {
17
+ for (int i = 0; i < 3; i++) {
18
+ successful_read = this->read_data_(&data);
19
+ if (successful_read) {
20
+ break;
21
+ }
22
+ }
23
+ }
24
+
16
25
  if (!successful_read) {
17
26
  this->mark_failed();
18
27
  return;
@@ -42,6 +42,14 @@ COLOR_ORDERS = {
42
42
  }
43
43
  DATA_PIN_SCHEMA = pins.internal_gpio_output_pin_schema
44
44
 
45
+
46
+ def validate_dimension(value):
47
+ value = cv.positive_int(value)
48
+ if value % 2 != 0:
49
+ raise cv.Invalid("Width/height/offset must be divisible by 2")
50
+ return value
51
+
52
+
45
53
  CONFIG_SCHEMA = cv.All(
46
54
  display.FULL_DISPLAY_SCHEMA.extend(
47
55
  cv.Schema(
@@ -52,10 +60,14 @@ CONFIG_SCHEMA = cv.All(
52
60
  cv.dimensions,
53
61
  cv.Schema(
54
62
  {
55
- cv.Required(CONF_WIDTH): cv.int_,
56
- cv.Required(CONF_HEIGHT): cv.int_,
57
- cv.Optional(CONF_OFFSET_HEIGHT, default=0): cv.int_,
58
- cv.Optional(CONF_OFFSET_WIDTH, default=0): cv.int_,
63
+ cv.Required(CONF_WIDTH): validate_dimension,
64
+ cv.Required(CONF_HEIGHT): validate_dimension,
65
+ cv.Optional(
66
+ CONF_OFFSET_HEIGHT, default=0
67
+ ): validate_dimension,
68
+ cv.Optional(
69
+ CONF_OFFSET_WIDTH, default=0
70
+ ): validate_dimension,
59
71
  }
60
72
  ),
61
73
  ),
@@ -25,7 +25,23 @@ void QspiAmoLed::setup() {
25
25
  }
26
26
 
27
27
  void QspiAmoLed::update() {
28
+ if (!this->setup_complete_) {
29
+ return;
30
+ }
28
31
  this->do_update_();
32
+ // Start addresses and widths/heights must be divisible by 2 (CASET/RASET restriction in datasheet)
33
+ if (this->x_low_ % 2 == 1) {
34
+ this->x_low_--;
35
+ }
36
+ if (this->x_high_ % 2 == 0) {
37
+ this->x_high_++;
38
+ }
39
+ if (this->y_low_ % 2 == 1) {
40
+ this->y_low_--;
41
+ }
42
+ if (this->y_high_ % 2 == 0) {
43
+ this->y_high_++;
44
+ }
29
45
  int w = this->x_high_ - this->x_low_ + 1;
30
46
  int h = this->y_high_ - this->y_low_ + 1;
31
47
  this->draw_pixels_at(this->x_low_, this->y_low_, w, h, this->buffer_, this->color_mode_, display::COLOR_BITNESS_565,
@@ -65,13 +65,10 @@ class QspiAmoLed : public display::DisplayBuffer,
65
65
 
66
66
  void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; }
67
67
  void set_enable_pin(GPIOPin *enable_pin) { this->enable_pin_ = enable_pin; }
68
- void set_width(uint16_t width) { this->width_ = width; }
69
68
  void set_dimensions(uint16_t width, uint16_t height) {
70
69
  this->width_ = width;
71
70
  this->height_ = height;
72
71
  }
73
- int get_width() override { return this->width_; }
74
- int get_height() override { return this->height_; }
75
72
  void set_invert_colors(bool invert_colors) {
76
73
  this->invert_colors_ = invert_colors;
77
74
  this->reset_params_();
@@ -8,10 +8,10 @@ static const char *const TAG = "remote.dooya";
8
8
 
9
9
  static const uint32_t HEADER_HIGH_US = 5000;
10
10
  static const uint32_t HEADER_LOW_US = 1500;
11
- static const uint32_t BIT_ZERO_HIGH_US = 750;
12
- static const uint32_t BIT_ZERO_LOW_US = 350;
13
- static const uint32_t BIT_ONE_HIGH_US = 350;
14
- static const uint32_t BIT_ONE_LOW_US = 750;
11
+ static const uint32_t BIT_ZERO_HIGH_US = 350;
12
+ static const uint32_t BIT_ZERO_LOW_US = 750;
13
+ static const uint32_t BIT_ONE_HIGH_US = 750;
14
+ static const uint32_t BIT_ONE_LOW_US = 350;
15
15
 
16
16
  void DooyaProtocol::encode(RemoteTransmitData *dst, const DooyaData &data) {
17
17
  dst->set_carrier_frequency(0);
@@ -54,7 +54,7 @@ void RCSwitchBase::sync(RemoteTransmitData *dst) const {
54
54
  }
55
55
  }
56
56
  void RCSwitchBase::transmit(RemoteTransmitData *dst, uint64_t code, uint8_t len) const {
57
- dst->set_carrier_frequency(0);
57
+ dst->set_carrier_frequency(38000);
58
58
  this->sync(dst);
59
59
  for (int16_t i = len - 1; i >= 0; i--) {
60
60
  if (code & ((uint64_t) 1 << i)) {
@@ -5,6 +5,7 @@ from esphome.const import (
5
5
  CONF_ID,
6
6
  DEVICE_CLASS_RESTART,
7
7
  ENTITY_CATEGORY_CONFIG,
8
+ ICON_RESTART,
8
9
  )
9
10
 
10
11
  restart_ns = cg.esphome_ns.namespace("restart")
@@ -12,6 +13,7 @@ RestartButton = restart_ns.class_("RestartButton", button.Button, cg.Component)
12
13
 
13
14
  CONFIG_SCHEMA = button.button_schema(
14
15
  RestartButton,
16
+ icon=ICON_RESTART,
15
17
  device_class=DEVICE_CLASS_RESTART,
16
18
  entity_category=ENTITY_CATEGORY_CONFIG,
17
19
  ).extend(cv.COMPONENT_SCHEMA)
@@ -88,7 +88,7 @@ def validate_parameter_name(value):
88
88
  raise cv.Invalid(f"Script's parameter name cannot be {CONF_ID}")
89
89
 
90
90
 
91
- ALLOWED_PARAM_TYPE_CHARSET = set("abcdefghijklmnopqrstuvwxyz0123456789_:*&[]")
91
+ ALLOWED_PARAM_TYPE_CHARSET = set("abcdefghijklmnopqrstuvwxyz0123456789_:*&[]<>")
92
92
 
93
93
 
94
94
  def validate_parameter_type(value):
@@ -43,6 +43,7 @@ from esphome.const import (
43
43
  DEVICE_CLASS_BATTERY,
44
44
  DEVICE_CLASS_CARBON_DIOXIDE,
45
45
  DEVICE_CLASS_CARBON_MONOXIDE,
46
+ DEVICE_CLASS_CONDUCTIVITY,
46
47
  DEVICE_CLASS_CURRENT,
47
48
  DEVICE_CLASS_DATA_RATE,
48
49
  DEVICE_CLASS_DATA_SIZE,
@@ -103,6 +104,7 @@ DEVICE_CLASSES = [
103
104
  DEVICE_CLASS_BATTERY,
104
105
  DEVICE_CLASS_CARBON_DIOXIDE,
105
106
  DEVICE_CLASS_CARBON_MONOXIDE,
107
+ DEVICE_CLASS_CONDUCTIVITY,
106
108
  DEVICE_CLASS_CURRENT,
107
109
  DEVICE_CLASS_DATA_RATE,
108
110
  DEVICE_CLASS_DATA_SIZE,
@@ -223,13 +223,19 @@ void Tuya::handle_command_(uint8_t command, uint8_t version, const uint8_t *buff
223
223
  break;
224
224
  case TuyaCommandType::DATAPOINT_DELIVER:
225
225
  break;
226
- case TuyaCommandType::DATAPOINT_REPORT:
226
+ case TuyaCommandType::DATAPOINT_REPORT_ASYNC:
227
+ case TuyaCommandType::DATAPOINT_REPORT_SYNC:
227
228
  if (this->init_state_ == TuyaInitState::INIT_DATAPOINT) {
228
229
  this->init_state_ = TuyaInitState::INIT_DONE;
229
230
  this->set_timeout("datapoint_dump", 1000, [this] { this->dump_config(); });
230
231
  this->initialized_callback_.call();
231
232
  }
232
233
  this->handle_datapoints_(buffer, len);
234
+
235
+ if (command_type == TuyaCommandType::DATAPOINT_REPORT_SYNC) {
236
+ this->send_command_(
237
+ TuyaCommand{.cmd = TuyaCommandType::DATAPOINT_REPORT_ACK, .payload = std::vector<uint8_t>{0x01}});
238
+ }
233
239
  break;
234
240
  case TuyaCommandType::DATAPOINT_QUERY:
235
241
  break;
@@ -423,7 +429,7 @@ void Tuya::send_raw_command_(TuyaCommand command) {
423
429
  break;
424
430
  case TuyaCommandType::DATAPOINT_DELIVER:
425
431
  case TuyaCommandType::DATAPOINT_QUERY:
426
- this->expected_response_ = TuyaCommandType::DATAPOINT_REPORT;
432
+ this->expected_response_ = TuyaCommandType::DATAPOINT_REPORT_ASYNC;
427
433
  break;
428
434
  default:
429
435
  break;
@@ -53,10 +53,12 @@ enum class TuyaCommandType : uint8_t {
53
53
  WIFI_RESET = 0x04,
54
54
  WIFI_SELECT = 0x05,
55
55
  DATAPOINT_DELIVER = 0x06,
56
- DATAPOINT_REPORT = 0x07,
56
+ DATAPOINT_REPORT_ASYNC = 0x07,
57
57
  DATAPOINT_QUERY = 0x08,
58
58
  WIFI_TEST = 0x0E,
59
59
  LOCAL_TIME_QUERY = 0x1C,
60
+ DATAPOINT_REPORT_SYNC = 0x22,
61
+ DATAPOINT_REPORT_ACK = 0x23,
60
62
  WIFI_RSSI = 0x24,
61
63
  VACUUM_MAP_UPLOAD = 0x28,
62
64
  GET_NETWORK_STATUS = 0x2B,
@@ -1,5 +1,5 @@
1
1
  from typing import Optional
2
-
2
+ import re
3
3
  import esphome.codegen as cg
4
4
  import esphome.config_validation as cv
5
5
  import esphome.final_validate as fv
@@ -11,6 +11,7 @@ from esphome.const import (
11
11
  CONF_NUMBER,
12
12
  CONF_RX_PIN,
13
13
  CONF_TX_PIN,
14
+ CONF_PORT,
14
15
  CONF_UART_ID,
15
16
  CONF_DATA,
16
17
  CONF_RX_BUFFER_SIZE,
@@ -27,6 +28,7 @@ from esphome.const import (
27
28
  CONF_DUMMY_RECEIVER,
28
29
  CONF_DUMMY_RECEIVER_ID,
29
30
  CONF_LAMBDA,
31
+ PLATFORM_HOST,
30
32
  )
31
33
  from esphome.core import CORE
32
34
 
@@ -45,6 +47,7 @@ RP2040UartComponent = uart_ns.class_("RP2040UartComponent", UARTComponent, cg.Co
45
47
  LibreTinyUARTComponent = uart_ns.class_(
46
48
  "LibreTinyUARTComponent", UARTComponent, cg.Component
47
49
  )
50
+ HostUartComponent = uart_ns.class_("HostUartComponent", UARTComponent, cg.Component)
48
51
 
49
52
  NATIVE_UART_CLASSES = (
50
53
  str(IDFUARTComponent),
@@ -54,6 +57,39 @@ NATIVE_UART_CLASSES = (
54
57
  str(LibreTinyUARTComponent),
55
58
  )
56
59
 
60
+ HOST_BAUD_RATES = [
61
+ 50,
62
+ 75,
63
+ 110,
64
+ 134,
65
+ 150,
66
+ 200,
67
+ 300,
68
+ 600,
69
+ 1200,
70
+ 1800,
71
+ 2400,
72
+ 4800,
73
+ 9600,
74
+ 19200,
75
+ 38400,
76
+ 57600,
77
+ 115200,
78
+ 230400,
79
+ 460800,
80
+ 500000,
81
+ 576000,
82
+ 921600,
83
+ 1000000,
84
+ 1152000,
85
+ 1500000,
86
+ 2000000,
87
+ 2500000,
88
+ 3000000,
89
+ 3500000,
90
+ 4000000,
91
+ ]
92
+
57
93
  UARTDevice = uart_ns.class_("UARTDevice")
58
94
  UARTWriteAction = uart_ns.class_("UARTWriteAction", automation.Action)
59
95
  UARTDebugger = uart_ns.class_("UARTDebugger", cg.Component, automation.Action)
@@ -95,6 +131,20 @@ def validate_invert_esp32(config):
95
131
  return config
96
132
 
97
133
 
134
+ def validate_host_config(config):
135
+ if CORE.is_host:
136
+ if CONF_TX_PIN in config or CONF_RX_PIN in config:
137
+ raise cv.Invalid(
138
+ "TX and RX pins are not supported for UART on host platform."
139
+ )
140
+ if config[CONF_BAUD_RATE] not in HOST_BAUD_RATES:
141
+ raise cv.Invalid(
142
+ f"Host platform doesn't support baud rate {config[CONF_BAUD_RATE]}",
143
+ path=[CONF_BAUD_RATE],
144
+ )
145
+ return config
146
+
147
+
98
148
  def _uart_declare_type(value):
99
149
  if CORE.is_esp8266:
100
150
  return cv.declare_id(ESP8266UartComponent)(value)
@@ -107,6 +157,8 @@ def _uart_declare_type(value):
107
157
  return cv.declare_id(RP2040UartComponent)(value)
108
158
  if CORE.is_libretiny:
109
159
  return cv.declare_id(LibreTinyUARTComponent)(value)
160
+ if CORE.is_host:
161
+ return cv.declare_id(HostUartComponent)(value)
110
162
  raise NotImplementedError
111
163
 
112
164
 
@@ -149,6 +201,12 @@ def maybe_empty_debug(value):
149
201
  return DEBUG_SCHEMA(value)
150
202
 
151
203
 
204
+ def validate_port(value):
205
+ if not re.match(r"^/(?:[^/]+/)[^/]+$", value):
206
+ raise cv.Invalid("Port must be a valid device path")
207
+ return value
208
+
209
+
152
210
  DEBUG_SCHEMA = cv.Schema(
153
211
  {
154
212
  cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UARTDebugger),
@@ -181,6 +239,7 @@ CONFIG_SCHEMA = cv.All(
181
239
  cv.Required(CONF_BAUD_RATE): cv.int_range(min=1),
182
240
  cv.Optional(CONF_TX_PIN): pins.internal_gpio_output_pin_schema,
183
241
  cv.Optional(CONF_RX_PIN): validate_rx_pin,
242
+ cv.Optional(CONF_PORT): cv.All(validate_port, cv.only_on(PLATFORM_HOST)),
184
243
  cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes,
185
244
  cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True),
186
245
  cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8),
@@ -193,8 +252,9 @@ CONFIG_SCHEMA = cv.All(
193
252
  cv.Optional(CONF_DEBUG): maybe_empty_debug,
194
253
  }
195
254
  ).extend(cv.COMPONENT_SCHEMA),
196
- cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN),
255
+ cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN, CONF_PORT),
197
256
  validate_invert_esp32,
257
+ validate_host_config,
198
258
  )
199
259
 
200
260
 
@@ -236,6 +296,8 @@ async def to_code(config):
236
296
  if CONF_RX_PIN in config:
237
297
  rx_pin = await cg.gpio_pin_expression(config[CONF_RX_PIN])
238
298
  cg.add(var.set_rx_pin(rx_pin))
299
+ if CONF_PORT in config:
300
+ cg.add(var.set_name(config[CONF_PORT]))
239
301
  cg.add(var.set_rx_buffer_size(config[CONF_RX_BUFFER_SIZE]))
240
302
  cg.add(var.set_stop_bits(config[CONF_STOP_BITS]))
241
303
  cg.add(var.set_data_bits(config[CONF_DATA_BITS]))
@@ -258,6 +320,7 @@ KEY_UART_DEVICES = "uart_devices"
258
320
  def final_validate_device_schema(
259
321
  name: str,
260
322
  *,
323
+ uart_bus: str = CONF_UART_ID,
261
324
  baud_rate: Optional[int] = None,
262
325
  require_tx: bool = False,
263
326
  require_rx: bool = False,
@@ -268,7 +331,7 @@ def final_validate_device_schema(
268
331
  def validate_baud_rate(value):
269
332
  if value != baud_rate:
270
333
  raise cv.Invalid(
271
- f"Component {name} requires baud rate {baud_rate} for the uart bus"
334
+ f"Component {name} requires baud rate {baud_rate} for the uart referenced by {uart_bus}"
272
335
  )
273
336
  return value
274
337
 
@@ -287,21 +350,21 @@ def final_validate_device_schema(
287
350
  def validate_data_bits(value):
288
351
  if value != data_bits:
289
352
  raise cv.Invalid(
290
- f"Component {name} requires {data_bits} data bits for the uart bus"
353
+ f"Component {name} requires {data_bits} data bits for the uart referenced by {uart_bus}"
291
354
  )
292
355
  return value
293
356
 
294
357
  def validate_parity(value):
295
358
  if value != parity:
296
359
  raise cv.Invalid(
297
- f"Component {name} requires parity {parity} for the uart bus"
360
+ f"Component {name} requires parity {parity} for the uart referenced by {uart_bus}"
298
361
  )
299
362
  return value
300
363
 
301
364
  def validate_stop_bits(value):
302
365
  if value != stop_bits:
303
366
  raise cv.Invalid(
304
- f"Component {name} requires {stop_bits} stop bits for the uart bus"
367
+ f"Component {name} requires {stop_bits} stop bits for the uart referenced by {uart_bus}"
305
368
  )
306
369
  return value
307
370
 
@@ -316,14 +379,14 @@ def final_validate_device_schema(
316
379
  hub_schema[
317
380
  cv.Required(
318
381
  CONF_TX_PIN,
319
- msg=f"Component {name} requires this uart bus to declare a tx_pin",
382
+ msg=f"Component {name} requires uart referenced by {uart_bus} to declare a tx_pin",
320
383
  )
321
384
  ] = validate_pin(CONF_TX_PIN, device)
322
385
  if require_rx and uart_id_type_str in NATIVE_UART_CLASSES:
323
386
  hub_schema[
324
387
  cv.Required(
325
388
  CONF_RX_PIN,
326
- msg=f"Component {name} requires this uart bus to declare a rx_pin",
389
+ msg=f"Component {name} requires uart referenced by {uart_bus} to declare a rx_pin",
327
390
  )
328
391
  ] = validate_pin(CONF_RX_PIN, device)
329
392
  if baud_rate is not None:
@@ -337,7 +400,7 @@ def final_validate_device_schema(
337
400
  return cv.Schema(hub_schema, extra=cv.ALLOW_EXTRA)(hub_config)
338
401
 
339
402
  return cv.Schema(
340
- {cv.Required(CONF_UART_ID): fv.id_declaration_match_schema(validate_hub)},
403
+ {cv.Required(uart_bus): fv.id_declaration_match_schema(validate_hub)},
341
404
  extra=cv.ALLOW_EXTRA,
342
405
  )
343
406