mirror of
https://github.com/esphome/esphome.git
synced 2024-12-18 15:57:58 +01:00
commit
e43dcded62
@ -60,6 +60,7 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
|
||||
auto chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
|
||||
if (chr == nullptr) {
|
||||
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str());
|
||||
break;
|
||||
}
|
||||
this->char_handle_ = chr->handle;
|
||||
|
@ -109,9 +109,9 @@ def _compute_destination_path(key: str) -> Path:
|
||||
return base_dir / h.hexdigest()[:8]
|
||||
|
||||
|
||||
def _run_git_command(cmd):
|
||||
def _run_git_command(cmd, cwd=None):
|
||||
try:
|
||||
ret = subprocess.run(cmd, capture_output=True, check=False)
|
||||
ret = subprocess.run(cmd, cwd=cwd, capture_output=True, check=False)
|
||||
except FileNotFoundError as err:
|
||||
raise cv.Invalid(
|
||||
"git is not installed but required for external_components.\n"
|
||||
@ -151,14 +151,16 @@ def _process_git_config(config: dict, refresh) -> str:
|
||||
_LOGGER.info("Updating %s", key)
|
||||
_LOGGER.debug("Location: %s", repo_dir)
|
||||
# Stash local changes (if any)
|
||||
_run_git_command(["git", "stash", "push", "--include-untracked"])
|
||||
_run_git_command(
|
||||
["git", "stash", "push", "--include-untracked"], str(repo_dir)
|
||||
)
|
||||
# Fetch remote ref
|
||||
cmd = ["git", "fetch", "--", "origin"]
|
||||
if CONF_REF in config:
|
||||
cmd.append(config[CONF_REF])
|
||||
_run_git_command(cmd)
|
||||
_run_git_command(cmd, str(repo_dir))
|
||||
# Hard reset to FETCH_HEAD (short-lived git ref corresponding to most recent fetch)
|
||||
_run_git_command(["git", "reset", "--hard", "FETCH_HEAD"])
|
||||
_run_git_command(["git", "reset", "--hard", "FETCH_HEAD"], str(repo_dir))
|
||||
|
||||
if (repo_dir / "esphome" / "components").is_dir():
|
||||
components_dir = repo_dir / "esphome" / "components"
|
||||
|
@ -100,7 +100,7 @@ bool MideaAC::allow_preset(climate::ClimatePreset preset) const {
|
||||
ESP_LOGD(TAG, "BOOST preset is only available in HEAT or COOL mode");
|
||||
}
|
||||
break;
|
||||
case climate::CLIMATE_PRESET_HOME:
|
||||
case climate::CLIMATE_PRESET_NONE:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
@ -191,7 +191,7 @@ climate::ClimateTraits MideaAC::traits() {
|
||||
if (traits_swing_both_)
|
||||
traits.add_supported_swing_mode(climate::CLIMATE_SWING_BOTH);
|
||||
traits.set_supported_presets({
|
||||
climate::CLIMATE_PRESET_HOME,
|
||||
climate::CLIMATE_PRESET_NONE,
|
||||
});
|
||||
if (traits_preset_eco_)
|
||||
traits.add_supported_preset(climate::CLIMATE_PRESET_ECO);
|
||||
|
@ -86,18 +86,17 @@ void PropertiesFrame::set_mode(climate::ClimateMode mode) {
|
||||
}
|
||||
|
||||
optional<climate::ClimatePreset> PropertiesFrame::get_preset() const {
|
||||
if (this->get_eco_mode()) {
|
||||
if (this->get_eco_mode())
|
||||
return climate::CLIMATE_PRESET_ECO;
|
||||
} else if (this->get_sleep_mode()) {
|
||||
if (this->get_sleep_mode())
|
||||
return climate::CLIMATE_PRESET_SLEEP;
|
||||
} else if (this->get_turbo_mode()) {
|
||||
if (this->get_turbo_mode())
|
||||
return climate::CLIMATE_PRESET_BOOST;
|
||||
} else {
|
||||
return climate::CLIMATE_PRESET_HOME;
|
||||
}
|
||||
return climate::CLIMATE_PRESET_NONE;
|
||||
}
|
||||
|
||||
void PropertiesFrame::set_preset(climate::ClimatePreset preset) {
|
||||
this->clear_presets();
|
||||
switch (preset) {
|
||||
case climate::CLIMATE_PRESET_ECO:
|
||||
this->set_eco_mode(true);
|
||||
@ -113,14 +112,21 @@ void PropertiesFrame::set_preset(climate::ClimatePreset preset) {
|
||||
}
|
||||
}
|
||||
|
||||
void PropertiesFrame::clear_presets() {
|
||||
this->set_eco_mode(false);
|
||||
this->set_sleep_mode(false);
|
||||
this->set_turbo_mode(false);
|
||||
this->set_freeze_protection_mode(false);
|
||||
}
|
||||
|
||||
bool PropertiesFrame::is_custom_preset() const { return this->get_freeze_protection_mode(); }
|
||||
|
||||
const std::string &PropertiesFrame::get_custom_preset() const { return midea_ac::MIDEA_FREEZE_PROTECTION_PRESET; };
|
||||
|
||||
void PropertiesFrame::set_custom_preset(const std::string &preset) {
|
||||
if (preset == MIDEA_FREEZE_PROTECTION_PRESET) {
|
||||
this->clear_presets();
|
||||
if (preset == MIDEA_FREEZE_PROTECTION_PRESET)
|
||||
this->set_freeze_protection_mode(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool PropertiesFrame::is_custom_fan_mode() const {
|
||||
|
@ -115,6 +115,7 @@ class PropertiesFrame : public midea_dongle::BaseFrame {
|
||||
/* PRESET */
|
||||
optional<climate::ClimatePreset> get_preset() const;
|
||||
void set_preset(climate::ClimatePreset preset);
|
||||
void clear_presets();
|
||||
|
||||
bool is_custom_preset() const;
|
||||
const std::string &get_custom_preset() const;
|
||||
|
@ -72,7 +72,7 @@ void MQTTClimateComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryC
|
||||
root["act_t"] = this->get_action_state_topic();
|
||||
}
|
||||
|
||||
if (traits.get_supports_fan_modes()) {
|
||||
if (traits.get_supports_fan_modes() || !traits.get_supported_custom_fan_modes().empty()) {
|
||||
// fan_mode_command_topic
|
||||
root["fan_mode_cmd_t"] = this->get_fan_mode_command_topic();
|
||||
// fan_mode_state_topic
|
||||
|
@ -35,8 +35,8 @@ void PIDClimate::control(const climate::ClimateCall &call) {
|
||||
if (call.get_target_temperature().has_value())
|
||||
this->target_temperature = *call.get_target_temperature();
|
||||
|
||||
// If switching to non-auto mode, set output immediately
|
||||
if (this->mode != climate::CLIMATE_MODE_HEAT_COOL)
|
||||
// If switching to off mode, set output immediately
|
||||
if (this->mode == climate::CLIMATE_MODE_OFF)
|
||||
this->handle_non_auto_mode_();
|
||||
|
||||
this->publish_state();
|
||||
|
@ -8,9 +8,10 @@ namespace tuya {
|
||||
|
||||
static const char *const TAG = "tuya";
|
||||
static const int COMMAND_DELAY = 50;
|
||||
static const int RECEIVE_TIMEOUT = 300;
|
||||
|
||||
void Tuya::setup() {
|
||||
this->set_interval("heartbeat", 10000, [this] { this->send_empty_command_(TuyaCommandType::HEARTBEAT); });
|
||||
this->set_interval("heartbeat", 15000, [this] { this->send_empty_command_(TuyaCommandType::HEARTBEAT); });
|
||||
}
|
||||
|
||||
void Tuya::loop() {
|
||||
@ -117,7 +118,13 @@ void Tuya::handle_char_(uint8_t c) {
|
||||
}
|
||||
|
||||
void Tuya::handle_command_(uint8_t command, uint8_t version, const uint8_t *buffer, size_t len) {
|
||||
switch ((TuyaCommandType) command) {
|
||||
TuyaCommandType command_type = (TuyaCommandType) command;
|
||||
|
||||
if (this->expected_response_.has_value() && this->expected_response_ == command_type) {
|
||||
this->expected_response_.reset();
|
||||
}
|
||||
|
||||
switch (command_type) {
|
||||
case TuyaCommandType::HEARTBEAT:
|
||||
ESP_LOGV(TAG, "MCU Heartbeat (0x%02X)", buffer[0]);
|
||||
this->protocol_version_ = version;
|
||||
@ -316,6 +323,25 @@ void Tuya::send_raw_command_(TuyaCommand command) {
|
||||
uint8_t version = 0;
|
||||
|
||||
this->last_command_timestamp_ = millis();
|
||||
switch (command.cmd) {
|
||||
case TuyaCommandType::HEARTBEAT:
|
||||
this->expected_response_ = TuyaCommandType::HEARTBEAT;
|
||||
break;
|
||||
case TuyaCommandType::PRODUCT_QUERY:
|
||||
this->expected_response_ = TuyaCommandType::PRODUCT_QUERY;
|
||||
break;
|
||||
case TuyaCommandType::CONF_QUERY:
|
||||
this->expected_response_ = TuyaCommandType::CONF_QUERY;
|
||||
break;
|
||||
case TuyaCommandType::DATAPOINT_DELIVER:
|
||||
this->expected_response_ = TuyaCommandType::DATAPOINT_REPORT;
|
||||
break;
|
||||
case TuyaCommandType::DATAPOINT_QUERY:
|
||||
this->expected_response_ = TuyaCommandType::DATAPOINT_REPORT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Sending Tuya: CMD=0x%02X VERSION=%u DATA=[%s] INIT_STATE=%u", static_cast<uint8_t>(command.cmd),
|
||||
version, hexencode(command.payload).c_str(), static_cast<uint8_t>(this->init_state_));
|
||||
@ -332,8 +358,14 @@ void Tuya::send_raw_command_(TuyaCommand command) {
|
||||
|
||||
void Tuya::process_command_queue_() {
|
||||
uint32_t delay = millis() - this->last_command_timestamp_;
|
||||
|
||||
if (this->expected_response_.has_value() && delay > RECEIVE_TIMEOUT) {
|
||||
this->expected_response_.reset();
|
||||
}
|
||||
|
||||
// Left check of delay since last command in case theres ever a command sent by calling send_raw_command_ directly
|
||||
if (delay > COMMAND_DELAY && !this->command_queue_.empty() && this->rx_message_.empty()) {
|
||||
if (delay > COMMAND_DELAY && !this->command_queue_.empty() && this->rx_message_.empty() &&
|
||||
!this->expected_response_.has_value()) {
|
||||
this->send_raw_command_(command_queue_.front());
|
||||
this->command_queue_.erase(command_queue_.begin());
|
||||
}
|
||||
@ -345,7 +377,7 @@ void Tuya::send_command_(const TuyaCommand &command) {
|
||||
}
|
||||
|
||||
void Tuya::send_empty_command_(TuyaCommandType command) {
|
||||
send_command_(TuyaCommand{.cmd = command, .payload = std::vector<uint8_t>{0x04}});
|
||||
send_command_(TuyaCommand{.cmd = command, .payload = std::vector<uint8_t>{}});
|
||||
}
|
||||
|
||||
void Tuya::send_wifi_status_() {
|
||||
|
@ -113,6 +113,7 @@ class Tuya : public Component, public uart::UARTDevice {
|
||||
std::vector<uint8_t> rx_message_;
|
||||
std::vector<uint8_t> ignore_mcu_update_on_datapoints_{};
|
||||
std::vector<TuyaCommand> command_queue_;
|
||||
optional<TuyaCommandType> expected_response_{};
|
||||
uint8_t wifi_status_ = -1;
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Constants used by esphome."""
|
||||
|
||||
__version__ = "1.20.0"
|
||||
__version__ = "1.20.1"
|
||||
|
||||
ESP_PLATFORM_ESP32 = "ESP32"
|
||||
ESP_PLATFORM_ESP8266 = "ESP8266"
|
||||
|
Loading…
Reference in New Issue
Block a user