mirror of
				https://github.com/esphome/esphome.git
				synced 2025-11-04 00:51:49 +00:00 
			
		
		
		
	Compare commits
	
		
			18 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					01ec414873 | ||
| 
						 | 
					150c9b5fa3 | ||
| 
						 | 
					55df88d7ae | ||
| 
						 | 
					619787e6d2 | ||
| 
						 | 
					3f8bad3ed1 | ||
| 
						 | 
					c146712b16 | ||
| 
						 | 
					2cabe59c22 | ||
| 
						 | 
					a67b92a04c | ||
| 
						 | 
					9fb8e9edef | ||
| 
						 | 
					d2bccbe8ac | ||
| 
						 | 
					e44a60e814 | ||
| 
						 | 
					02a71cb6a7 | ||
| 
						 | 
					e600784ebf | ||
| 
						 | 
					5e19a3b892 | ||
| 
						 | 
					8bf112669f | ||
| 
						 | 
					4278664208 | ||
| 
						 | 
					0789657fd5 | ||
| 
						 | 
					b566c78f00 | 
@@ -28,14 +28,14 @@ RUN \
 | 
			
		||||
        git=1:2.30.2-1+deb11u2 \
 | 
			
		||||
        curl=7.74.0-1.3+deb11u7 \
 | 
			
		||||
        openssh-client=1:8.4p1-5+deb11u1 \
 | 
			
		||||
        python3-cffi=1.14.5-1; \
 | 
			
		||||
        python3-cffi=1.14.5-1 \
 | 
			
		||||
        libcairo2=1.16.0-5; \
 | 
			
		||||
    if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
 | 
			
		||||
        apt-get install -y --no-install-recommends \
 | 
			
		||||
          build-essential=12.9 \
 | 
			
		||||
          python3-dev=3.9.2-3 \
 | 
			
		||||
          zlib1g-dev=1:1.2.11.dfsg-2+deb11u2 \
 | 
			
		||||
          libjpeg-dev=1:2.0.6-4 \
 | 
			
		||||
          libcairo2=1.16.0-5 \
 | 
			
		||||
          libfreetype-dev=2.10.4+dfsg-1+deb11u1; \
 | 
			
		||||
    fi; \
 | 
			
		||||
    rm -rf \
 | 
			
		||||
 
 | 
			
		||||
@@ -371,7 +371,7 @@ def command_config(args, config):
 | 
			
		||||
    # add the console decoration so the front-end can hide the secrets
 | 
			
		||||
    if not args.show_secrets:
 | 
			
		||||
        output = re.sub(
 | 
			
		||||
            r"(password|key|psk|ssid)\:\s(.*)", r"\1: \\033[5m\2\\033[6m", output
 | 
			
		||||
            r"(password|key|psk|ssid)\: (.+)", r"\1: \\033[5m\2\\033[6m", output
 | 
			
		||||
        )
 | 
			
		||||
    safe_print(output)
 | 
			
		||||
    _LOGGER.info("Configuration is valid!")
 | 
			
		||||
 
 | 
			
		||||
@@ -89,7 +89,7 @@ SUPPORTED_SWING_MODES_OPTIONS = {
 | 
			
		||||
 | 
			
		||||
SUPPORTED_CLIMATE_MODES_OPTIONS = {
 | 
			
		||||
    "OFF": ClimateMode.CLIMATE_MODE_OFF,  # always available
 | 
			
		||||
    "AUTO": ClimateMode.CLIMATE_MODE_AUTO,  # always available
 | 
			
		||||
    "HEAT_COOL": ClimateMode.CLIMATE_MODE_HEAT_COOL,  # always available
 | 
			
		||||
    "COOL": ClimateMode.CLIMATE_MODE_COOL,
 | 
			
		||||
    "HEAT": ClimateMode.CLIMATE_MODE_HEAT,
 | 
			
		||||
    "DRY": ClimateMode.CLIMATE_MODE_DRY,
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ HaierClimateBase::HaierClimateBase()
 | 
			
		||||
  this->traits_ = climate::ClimateTraits();
 | 
			
		||||
  this->traits_.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_COOL, climate::CLIMATE_MODE_HEAT,
 | 
			
		||||
                                     climate::CLIMATE_MODE_FAN_ONLY, climate::CLIMATE_MODE_DRY,
 | 
			
		||||
                                     climate::CLIMATE_MODE_AUTO});
 | 
			
		||||
                                     climate::CLIMATE_MODE_HEAT_COOL});
 | 
			
		||||
  this->traits_.set_supported_fan_modes(
 | 
			
		||||
      {climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH});
 | 
			
		||||
  this->traits_.set_supported_swing_modes({climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_BOTH,
 | 
			
		||||
@@ -171,8 +171,8 @@ void HaierClimateBase::set_answer_timeout(uint32_t timeout) {
 | 
			
		||||
 | 
			
		||||
void HaierClimateBase::set_supported_modes(const std::set<climate::ClimateMode> &modes) {
 | 
			
		||||
  this->traits_.set_supported_modes(modes);
 | 
			
		||||
  this->traits_.add_supported_mode(climate::CLIMATE_MODE_OFF);   // Always available
 | 
			
		||||
  this->traits_.add_supported_mode(climate::CLIMATE_MODE_AUTO);  // Always available
 | 
			
		||||
  this->traits_.add_supported_mode(climate::CLIMATE_MODE_OFF);        // Always available
 | 
			
		||||
  this->traits_.add_supported_mode(climate::CLIMATE_MODE_HEAT_COOL);  // Always available
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HaierClimateBase::set_supported_presets(const std::set<climate::ClimatePreset> &presets) {
 | 
			
		||||
 
 | 
			
		||||
@@ -458,7 +458,7 @@ haier_protocol::HaierMessage HonClimate::get_control_message() {
 | 
			
		||||
        case CLIMATE_MODE_OFF:
 | 
			
		||||
          out_data->ac_power = 0;
 | 
			
		||||
          break;
 | 
			
		||||
        case CLIMATE_MODE_AUTO:
 | 
			
		||||
        case CLIMATE_MODE_HEAT_COOL:
 | 
			
		||||
          out_data->ac_power = 1;
 | 
			
		||||
          out_data->ac_mode = (uint8_t) hon_protocol::ConditioningMode::AUTO;
 | 
			
		||||
          out_data->fan_mode = this->other_modes_fan_speed_;
 | 
			
		||||
@@ -758,7 +758,7 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *
 | 
			
		||||
          this->mode = CLIMATE_MODE_FAN_ONLY;
 | 
			
		||||
          break;
 | 
			
		||||
        case (uint8_t) hon_protocol::ConditioningMode::AUTO:
 | 
			
		||||
          this->mode = CLIMATE_MODE_AUTO;
 | 
			
		||||
          this->mode = CLIMATE_MODE_HEAT_COOL;
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -270,7 +270,7 @@ haier_protocol::HaierMessage Smartair2Climate::get_control_message() {
 | 
			
		||||
          out_data->ac_power = 0;
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case CLIMATE_MODE_AUTO:
 | 
			
		||||
        case CLIMATE_MODE_HEAT_COOL:
 | 
			
		||||
          out_data->ac_power = 1;
 | 
			
		||||
          out_data->ac_mode = (uint8_t) smartair2_protocol::ConditioningMode::AUTO;
 | 
			
		||||
          out_data->fan_mode = this->other_modes_fan_speed_;
 | 
			
		||||
@@ -487,7 +487,7 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin
 | 
			
		||||
          this->mode = CLIMATE_MODE_FAN_ONLY;
 | 
			
		||||
          break;
 | 
			
		||||
        case (uint8_t) smartair2_protocol::ConditioningMode::AUTO:
 | 
			
		||||
          this->mode = CLIMATE_MODE_AUTO;
 | 
			
		||||
          this->mode = CLIMATE_MODE_HEAT_COOL;
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -23,13 +23,13 @@ CONFIG_SCHEMA = (
 | 
			
		||||
    cv.Schema(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(HTU21DComponent),
 | 
			
		||||
            cv.Required(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Required(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
            cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
 
 | 
			
		||||
@@ -66,25 +66,28 @@ void MQTTClientComponent::setup() {
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  this->subscribe(
 | 
			
		||||
      "esphome/discover", [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); },
 | 
			
		||||
      2);
 | 
			
		||||
  if (this->is_discovery_enabled()) {
 | 
			
		||||
    this->subscribe(
 | 
			
		||||
        "esphome/discover", [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); },
 | 
			
		||||
        2);
 | 
			
		||||
 | 
			
		||||
  std::string topic = "esphome/ping/";
 | 
			
		||||
  topic.append(App.get_name());
 | 
			
		||||
  this->subscribe(
 | 
			
		||||
      topic, [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2);
 | 
			
		||||
    std::string topic = "esphome/ping/";
 | 
			
		||||
    topic.append(App.get_name());
 | 
			
		||||
    this->subscribe(
 | 
			
		||||
        topic, [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this->last_connected_ = millis();
 | 
			
		||||
  this->start_dnslookup_();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MQTTClientComponent::send_device_info_() {
 | 
			
		||||
  if (!this->is_connected()) {
 | 
			
		||||
  if (!this->is_connected() or !this->is_discovery_enabled()) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  std::string topic = "esphome/discover/";
 | 
			
		||||
  topic.append(App.get_name());
 | 
			
		||||
 | 
			
		||||
  this->publish_json(
 | 
			
		||||
      topic,
 | 
			
		||||
      [](JsonObject root) {
 | 
			
		||||
 
 | 
			
		||||
@@ -769,7 +769,7 @@ uint8_t Pipsolar::check_incoming_length_(uint8_t length) {
 | 
			
		||||
 | 
			
		||||
uint8_t Pipsolar::check_incoming_crc_() {
 | 
			
		||||
  uint16_t crc16;
 | 
			
		||||
  crc16 = crc16be(read_buffer_, read_pos_ - 3);
 | 
			
		||||
  crc16 = this->pipsolar_crc_(read_buffer_, read_pos_ - 3);
 | 
			
		||||
  ESP_LOGD(TAG, "checking crc on incoming message");
 | 
			
		||||
  if (((uint8_t) ((crc16) >> 8)) == read_buffer_[read_pos_ - 3] &&
 | 
			
		||||
      ((uint8_t) ((crc16) &0xff)) == read_buffer_[read_pos_ - 2]) {
 | 
			
		||||
@@ -798,7 +798,7 @@ uint8_t Pipsolar::send_next_command_() {
 | 
			
		||||
    this->command_start_millis_ = millis();
 | 
			
		||||
    this->empty_uart_buffer_();
 | 
			
		||||
    this->read_pos_ = 0;
 | 
			
		||||
    crc16 = crc16be(byte_command, length);
 | 
			
		||||
    crc16 = this->pipsolar_crc_(byte_command, length);
 | 
			
		||||
    this->write_str(command);
 | 
			
		||||
    // checksum
 | 
			
		||||
    this->write(((uint8_t) ((crc16) >> 8)));   // highbyte
 | 
			
		||||
@@ -825,8 +825,8 @@ void Pipsolar::send_next_poll_() {
 | 
			
		||||
  this->command_start_millis_ = millis();
 | 
			
		||||
  this->empty_uart_buffer_();
 | 
			
		||||
  this->read_pos_ = 0;
 | 
			
		||||
  crc16 = crc16be(this->used_polling_commands_[this->last_polling_command_].command,
 | 
			
		||||
                  this->used_polling_commands_[this->last_polling_command_].length);
 | 
			
		||||
  crc16 = this->pipsolar_crc_(this->used_polling_commands_[this->last_polling_command_].command,
 | 
			
		||||
                              this->used_polling_commands_[this->last_polling_command_].length);
 | 
			
		||||
  this->write_array(this->used_polling_commands_[this->last_polling_command_].command,
 | 
			
		||||
                    this->used_polling_commands_[this->last_polling_command_].length);
 | 
			
		||||
  // checksum
 | 
			
		||||
@@ -893,5 +893,17 @@ void Pipsolar::add_polling_command_(const char *command, ENUMPollingCommand poll
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t Pipsolar::pipsolar_crc_(uint8_t *msg, uint8_t len) {
 | 
			
		||||
  uint16_t crc = crc16be(msg, len);
 | 
			
		||||
  uint8_t crc_low = crc & 0xff;
 | 
			
		||||
  uint8_t crc_high = crc >> 8;
 | 
			
		||||
  if (crc_low == 0x28 || crc_low == 0x0d || crc_low == 0x0a)
 | 
			
		||||
    crc_low++;
 | 
			
		||||
  if (crc_high == 0x28 || crc_high == 0x0d || crc_high == 0x0a)
 | 
			
		||||
    crc_high++;
 | 
			
		||||
  crc = (crc_high << 8) | crc_low;
 | 
			
		||||
  return crc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace pipsolar
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 
 | 
			
		||||
@@ -193,7 +193,7 @@ class Pipsolar : public uart::UARTDevice, public PollingComponent {
 | 
			
		||||
  void empty_uart_buffer_();
 | 
			
		||||
  uint8_t check_incoming_crc_();
 | 
			
		||||
  uint8_t check_incoming_length_(uint8_t length);
 | 
			
		||||
  uint16_t cal_crc_half_(uint8_t *msg, uint8_t len);
 | 
			
		||||
  uint16_t pipsolar_crc_(uint8_t *msg, uint8_t len);
 | 
			
		||||
  uint8_t send_next_command_();
 | 
			
		||||
  void send_next_poll_();
 | 
			
		||||
  void queue_command_(const char *command, uint8_t length);
 | 
			
		||||
 
 | 
			
		||||
@@ -100,14 +100,14 @@ bool check_sml_data(const bytes &buffer) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint16_t crc_received = (buffer.at(buffer.size() - 2) << 8) | buffer.at(buffer.size() - 1);
 | 
			
		||||
  uint16_t crc_calculated = crc16(buffer.data(), buffer.size(), 0x6e23, 0x8408, true, true);
 | 
			
		||||
  uint16_t crc_calculated = crc16(buffer.data(), buffer.size() - 2, 0x6e23, 0x8408, true, true);
 | 
			
		||||
  crc_calculated = (crc_calculated >> 8) | (crc_calculated << 8);
 | 
			
		||||
  if (crc_received == crc_calculated) {
 | 
			
		||||
    ESP_LOGV(TAG, "Checksum verification successful with CRC16/X25.");
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  crc_calculated = crc16(buffer.data(), buffer.size(), 0xed50, 0x8408);
 | 
			
		||||
  crc_calculated = crc16(buffer.data(), buffer.size() - 2, 0xed50, 0x8408);
 | 
			
		||||
  if (crc_received == crc_calculated) {
 | 
			
		||||
    ESP_LOGV(TAG, "Checksum verification successful with CRC16/KERMIT.");
 | 
			
		||||
    return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,9 @@ SPI_DATA_RATE_OPTIONS = {
 | 
			
		||||
    40e6: SPIDataRate.DATA_RATE_40MHZ,
 | 
			
		||||
    20e6: SPIDataRate.DATA_RATE_20MHZ,
 | 
			
		||||
    10e6: SPIDataRate.DATA_RATE_10MHZ,
 | 
			
		||||
    8e6: SPIDataRate.DATA_RATE_8MHZ,
 | 
			
		||||
    5e6: SPIDataRate.DATA_RATE_5MHZ,
 | 
			
		||||
    4e6: SPIDataRate.DATA_RATE_4MHZ,
 | 
			
		||||
    2e6: SPIDataRate.DATA_RATE_2MHZ,
 | 
			
		||||
    1e6: SPIDataRate.DATA_RATE_1MHZ,
 | 
			
		||||
    2e5: SPIDataRate.DATA_RATE_200KHZ,
 | 
			
		||||
 
 | 
			
		||||
@@ -63,6 +63,7 @@ enum SPIDataRate : uint32_t {
 | 
			
		||||
  DATA_RATE_1MHZ = 1000000,
 | 
			
		||||
  DATA_RATE_2MHZ = 2000000,
 | 
			
		||||
  DATA_RATE_4MHZ = 4000000,
 | 
			
		||||
  DATA_RATE_5MHZ = 5000000,
 | 
			
		||||
  DATA_RATE_8MHZ = 8000000,
 | 
			
		||||
  DATA_RATE_10MHZ = 10000000,
 | 
			
		||||
  DATA_RATE_20MHZ = 20000000,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,23 +7,27 @@ namespace tca9548a {
 | 
			
		||||
static const char *const TAG = "tca9548a";
 | 
			
		||||
 | 
			
		||||
i2c::ErrorCode TCA9548AChannel::readv(uint8_t address, i2c::ReadBuffer *buffers, size_t cnt) {
 | 
			
		||||
  auto err = parent_->switch_to_channel(channel_);
 | 
			
		||||
  auto err = this->parent_->switch_to_channel(channel_);
 | 
			
		||||
  if (err != i2c::ERROR_OK)
 | 
			
		||||
    return err;
 | 
			
		||||
  return parent_->bus_->readv(address, buffers, cnt);
 | 
			
		||||
  err = this->parent_->bus_->readv(address, buffers, cnt);
 | 
			
		||||
  this->parent_->disable_all_channels();
 | 
			
		||||
  return err;
 | 
			
		||||
}
 | 
			
		||||
i2c::ErrorCode TCA9548AChannel::writev(uint8_t address, i2c::WriteBuffer *buffers, size_t cnt, bool stop) {
 | 
			
		||||
  auto err = parent_->switch_to_channel(channel_);
 | 
			
		||||
  auto err = this->parent_->switch_to_channel(channel_);
 | 
			
		||||
  if (err != i2c::ERROR_OK)
 | 
			
		||||
    return err;
 | 
			
		||||
  return parent_->bus_->writev(address, buffers, cnt, stop);
 | 
			
		||||
  err = this->parent_->bus_->writev(address, buffers, cnt, stop);
 | 
			
		||||
  this->parent_->disable_all_channels();
 | 
			
		||||
  return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TCA9548AComponent::setup() {
 | 
			
		||||
  ESP_LOGCONFIG(TAG, "Setting up TCA9548A...");
 | 
			
		||||
  uint8_t status = 0;
 | 
			
		||||
  if (this->read(&status, 1) != i2c::ERROR_OK) {
 | 
			
		||||
    ESP_LOGI(TAG, "TCA9548A failed");
 | 
			
		||||
    ESP_LOGE(TAG, "TCA9548A failed");
 | 
			
		||||
    this->mark_failed();
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
@@ -37,15 +41,16 @@ void TCA9548AComponent::dump_config() {
 | 
			
		||||
i2c::ErrorCode TCA9548AComponent::switch_to_channel(uint8_t channel) {
 | 
			
		||||
  if (this->is_failed())
 | 
			
		||||
    return i2c::ERROR_NOT_INITIALIZED;
 | 
			
		||||
  if (current_channel_ == channel)
 | 
			
		||||
    return i2c::ERROR_OK;
 | 
			
		||||
 | 
			
		||||
  uint8_t channel_val = 1 << channel;
 | 
			
		||||
  auto err = this->write(&channel_val, 1);
 | 
			
		||||
  if (err == i2c::ERROR_OK) {
 | 
			
		||||
    current_channel_ = channel;
 | 
			
		||||
  return this->write(&channel_val, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TCA9548AComponent::disable_all_channels() {
 | 
			
		||||
  if (this->write(&TCA9548A_DISABLE_CHANNELS_COMMAND, 1) != i2c::ERROR_OK) {
 | 
			
		||||
    ESP_LOGE(TAG, "Failed to disable all channels.");
 | 
			
		||||
    this->status_set_error();  // couldn't disable channels, set error status
 | 
			
		||||
  }
 | 
			
		||||
  return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace tca9548a
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,8 @@
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace tca9548a {
 | 
			
		||||
 | 
			
		||||
static const uint8_t TCA9548A_DISABLE_CHANNELS_COMMAND = 0x00;
 | 
			
		||||
 | 
			
		||||
class TCA9548AComponent;
 | 
			
		||||
class TCA9548AChannel : public i2c::I2CBus {
 | 
			
		||||
 public:
 | 
			
		||||
@@ -28,10 +30,10 @@ class TCA9548AComponent : public Component, public i2c::I2CDevice {
 | 
			
		||||
  void update();
 | 
			
		||||
 | 
			
		||||
  i2c::ErrorCode switch_to_channel(uint8_t channel);
 | 
			
		||||
  void disable_all_channels();
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  friend class TCA9548AChannel;
 | 
			
		||||
  uint8_t current_channel_ = 255;
 | 
			
		||||
};
 | 
			
		||||
}  // namespace tca9548a
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 
 | 
			
		||||
@@ -591,11 +591,11 @@ CONFIG_SCHEMA = cv.All(
 | 
			
		||||
            cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature,
 | 
			
		||||
            cv.Optional(
 | 
			
		||||
                CONF_SET_POINT_MINIMUM_DIFFERENTIAL, default=0.5
 | 
			
		||||
            ): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_COOL_DEADBAND, default=0.5): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_COOL_OVERRUN, default=0.5): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_HEAT_DEADBAND, default=0.5): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_HEAT_OVERRUN, default=0.5): cv.temperature,
 | 
			
		||||
            ): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_COOL_DEADBAND, default=0.5): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_COOL_OVERRUN, default=0.5): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_HEAT_DEADBAND, default=0.5): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_HEAT_OVERRUN, default=0.5): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_MAX_COOLING_RUN_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
            cv.Optional(CONF_MAX_HEATING_RUN_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
            cv.Optional(CONF_MIN_COOLING_OFF_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
@@ -608,8 +608,8 @@ CONFIG_SCHEMA = cv.All(
 | 
			
		||||
            cv.Optional(CONF_MIN_HEATING_OFF_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
            cv.Optional(CONF_MIN_HEATING_RUN_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
            cv.Required(CONF_MIN_IDLE_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
            cv.Optional(CONF_SUPPLEMENTAL_COOLING_DELTA): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_SUPPLEMENTAL_HEATING_DELTA): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_SUPPLEMENTAL_COOLING_DELTA): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_SUPPLEMENTAL_HEATING_DELTA): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(
 | 
			
		||||
                CONF_FAN_ONLY_ACTION_USES_FAN_MODE_TIMER, default=False
 | 
			
		||||
            ): cv.boolean,
 | 
			
		||||
 
 | 
			
		||||
@@ -125,6 +125,7 @@ RESERVED_IDS = [
 | 
			
		||||
    "char16_t",
 | 
			
		||||
    "char32_t",
 | 
			
		||||
    "class",
 | 
			
		||||
    "clock",
 | 
			
		||||
    "compl",
 | 
			
		||||
    "concept",
 | 
			
		||||
    "const",
 | 
			
		||||
@@ -928,6 +929,27 @@ def temperature(value):
 | 
			
		||||
    raise err
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def temperature_delta(value):
 | 
			
		||||
    err = None
 | 
			
		||||
    try:
 | 
			
		||||
        return _temperature_c(value)
 | 
			
		||||
    except Invalid as orig_err:
 | 
			
		||||
        err = orig_err
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        return _temperature_k(value)
 | 
			
		||||
    except Invalid:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        fahrenheit = _temperature_f(value)
 | 
			
		||||
        return fahrenheit * (5 / 9)
 | 
			
		||||
    except Invalid:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    raise err
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
_color_temperature_mireds = float_with_unit("Color Temperature", r"(mireds|Mireds)")
 | 
			
		||||
_color_temperature_kelvin = float_with_unit("Color Temperature", r"(K|Kelvin)")
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
"""Constants used by esphome."""
 | 
			
		||||
 | 
			
		||||
__version__ = "2023.8.0"
 | 
			
		||||
__version__ = "2023.8.3"
 | 
			
		||||
 | 
			
		||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
 | 
			
		||||
VALID_SUBSTITUTIONS_CHARACTERS = (
 | 
			
		||||
 
 | 
			
		||||
@@ -868,9 +868,6 @@ class PingStatusThread(threading.Thread):
 | 
			
		||||
                entries = _list_dashboard_entries()
 | 
			
		||||
                queue = collections.deque()
 | 
			
		||||
                for entry in entries:
 | 
			
		||||
                    if entry.no_mdns is True:
 | 
			
		||||
                        continue
 | 
			
		||||
 | 
			
		||||
                    if entry.address is None:
 | 
			
		||||
                        PING_RESULT[entry.filename] = None
 | 
			
		||||
                        continue
 | 
			
		||||
 
 | 
			
		||||
@@ -957,7 +957,7 @@ climate:
 | 
			
		||||
      temperature_step: 1 °C
 | 
			
		||||
    supported_modes:
 | 
			
		||||
    - 'OFF'
 | 
			
		||||
    - AUTO
 | 
			
		||||
    - HEAT_COOL
 | 
			
		||||
    - COOL
 | 
			
		||||
    - HEAT
 | 
			
		||||
    - DRY
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user