mirror of
https://github.com/esphome/esphome.git
synced 2024-11-27 01:08:03 +01:00
commit
35388cf2a2
7 changed files with 75 additions and 36 deletions
|
@ -118,7 +118,9 @@ void APIConnection::loop() {
|
||||||
this->list_entities_iterator_.advance();
|
this->list_entities_iterator_.advance();
|
||||||
this->initial_state_iterator_.advance();
|
this->initial_state_iterator_.advance();
|
||||||
|
|
||||||
const uint32_t keepalive = 60000;
|
static uint32_t keepalive = 60000;
|
||||||
|
static uint8_t max_ping_retries = 60;
|
||||||
|
static uint16_t ping_retry_interval = 1000;
|
||||||
const uint32_t now = millis();
|
const uint32_t now = millis();
|
||||||
if (this->sent_ping_) {
|
if (this->sent_ping_) {
|
||||||
// Disconnect if not responded within 2.5*keepalive
|
// Disconnect if not responded within 2.5*keepalive
|
||||||
|
@ -126,10 +128,24 @@ void APIConnection::loop() {
|
||||||
on_fatal_error();
|
on_fatal_error();
|
||||||
ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_combined_info_.c_str());
|
ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_combined_info_.c_str());
|
||||||
}
|
}
|
||||||
} else if (now - this->last_traffic_ > keepalive) {
|
} else if (now - this->last_traffic_ > keepalive && now > this->next_ping_retry_) {
|
||||||
ESP_LOGVV(TAG, "Sending keepalive PING...");
|
ESP_LOGVV(TAG, "Sending keepalive PING...");
|
||||||
this->sent_ping_ = true;
|
this->sent_ping_ = this->send_ping_request(PingRequest());
|
||||||
this->send_ping_request(PingRequest());
|
if (!this->sent_ping_) {
|
||||||
|
this->next_ping_retry_ = now + ping_retry_interval;
|
||||||
|
this->ping_retries_++;
|
||||||
|
if (this->ping_retries_ >= max_ping_retries) {
|
||||||
|
on_fatal_error();
|
||||||
|
ESP_LOGE(TAG, "%s: Sending keepalive failed %d time(s). Disconnecting...", this->client_combined_info_.c_str(),
|
||||||
|
this->ping_retries_);
|
||||||
|
} else if (this->ping_retries_ >= 10) {
|
||||||
|
ESP_LOGW(TAG, "%s: Sending keepalive failed %d time(s), will retry in %d ms",
|
||||||
|
this->client_combined_info_.c_str(), this->ping_retries_, ping_retry_interval);
|
||||||
|
} else {
|
||||||
|
ESP_LOGD(TAG, "%s: Sending keepalive failed %d time(s), will retry in %d ms",
|
||||||
|
this->client_combined_info_.c_str(), this->ping_retries_, ping_retry_interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_ESP32_CAMERA
|
#ifdef USE_ESP32_CAMERA
|
||||||
|
|
|
@ -140,6 +140,7 @@ class APIConnection : public APIServerConnection {
|
||||||
void on_disconnect_response(const DisconnectResponse &value) override;
|
void on_disconnect_response(const DisconnectResponse &value) override;
|
||||||
void on_ping_response(const PingResponse &value) override {
|
void on_ping_response(const PingResponse &value) override {
|
||||||
// we initiated ping
|
// we initiated ping
|
||||||
|
this->ping_retries_ = 0;
|
||||||
this->sent_ping_ = false;
|
this->sent_ping_ = false;
|
||||||
}
|
}
|
||||||
void on_home_assistant_state_response(const HomeAssistantStateResponse &msg) override;
|
void on_home_assistant_state_response(const HomeAssistantStateResponse &msg) override;
|
||||||
|
@ -217,6 +218,8 @@ class APIConnection : public APIServerConnection {
|
||||||
bool state_subscription_{false};
|
bool state_subscription_{false};
|
||||||
int log_subscription_{ESPHOME_LOG_LEVEL_NONE};
|
int log_subscription_{ESPHOME_LOG_LEVEL_NONE};
|
||||||
uint32_t last_traffic_;
|
uint32_t last_traffic_;
|
||||||
|
uint32_t next_ping_retry_{0};
|
||||||
|
uint8_t ping_retries_{0};
|
||||||
bool sent_ping_{false};
|
bool sent_ping_{false};
|
||||||
bool service_call_subscription_{false};
|
bool service_call_subscription_{false};
|
||||||
bool next_close_ = false;
|
bool next_close_ = false;
|
||||||
|
|
|
@ -3848,6 +3848,7 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const {
|
||||||
sprintf(buffer, "%g", this->visual_max_humidity);
|
sprintf(buffer, "%g", this->visual_max_humidity);
|
||||||
out.append(buffer);
|
out.append(buffer);
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
bool ClimateStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
bool ClimateStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||||
|
@ -4015,6 +4016,7 @@ void ClimateStateResponse::dump_to(std::string &out) const {
|
||||||
sprintf(buffer, "%g", this->target_humidity);
|
sprintf(buffer, "%g", this->target_humidity);
|
||||||
out.append(buffer);
|
out.append(buffer);
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
bool ClimateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
bool ClimateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||||
|
|
|
@ -39,45 +39,54 @@ void HTU21DComponent::dump_config() {
|
||||||
LOG_SENSOR(" ", "Humidity", this->humidity_);
|
LOG_SENSOR(" ", "Humidity", this->humidity_);
|
||||||
}
|
}
|
||||||
void HTU21DComponent::update() {
|
void HTU21DComponent::update() {
|
||||||
uint16_t raw_temperature;
|
|
||||||
if (this->write(&HTU21D_REGISTER_TEMPERATURE, 1) != i2c::ERROR_OK) {
|
if (this->write(&HTU21D_REGISTER_TEMPERATURE, 1) != i2c::ERROR_OK) {
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
delay(50); // NOLINT
|
|
||||||
if (this->read(reinterpret_cast<uint8_t *>(&raw_temperature), 2) != i2c::ERROR_OK) {
|
|
||||||
this->status_set_warning();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
raw_temperature = i2c::i2ctohs(raw_temperature);
|
|
||||||
|
|
||||||
float temperature = (float(raw_temperature & 0xFFFC)) * 175.72f / 65536.0f - 46.85f;
|
// According to the datasheet sht21 temperature readings can take up to 85ms
|
||||||
|
this->set_timeout(85, [this]() {
|
||||||
|
uint16_t raw_temperature;
|
||||||
|
if (this->read(reinterpret_cast<uint8_t *>(&raw_temperature), 2) != i2c::ERROR_OK) {
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
raw_temperature = i2c::i2ctohs(raw_temperature);
|
||||||
|
|
||||||
uint16_t raw_humidity;
|
float temperature = (float(raw_temperature & 0xFFFC)) * 175.72f / 65536.0f - 46.85f;
|
||||||
if (this->write(&HTU21D_REGISTER_HUMIDITY, 1) != i2c::ERROR_OK) {
|
|
||||||
this->status_set_warning();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
delay(50); // NOLINT
|
|
||||||
if (this->read(reinterpret_cast<uint8_t *>(&raw_humidity), 2) != i2c::ERROR_OK) {
|
|
||||||
this->status_set_warning();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
raw_humidity = i2c::i2ctohs(raw_humidity);
|
|
||||||
|
|
||||||
float humidity = (float(raw_humidity & 0xFFFC)) * 125.0f / 65536.0f - 6.0f;
|
ESP_LOGD(TAG, "Got Temperature=%.1f°C", temperature);
|
||||||
|
|
||||||
int8_t heater_level = this->get_heater_level();
|
if (this->temperature_ != nullptr)
|
||||||
|
this->temperature_->publish_state(temperature);
|
||||||
|
this->status_clear_warning();
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Got Temperature=%.1f°C Humidity=%.1f%% Heater Level=%d", temperature, humidity, heater_level);
|
if (this->write(&HTU21D_REGISTER_HUMIDITY, 1) != i2c::ERROR_OK) {
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->temperature_ != nullptr)
|
this->set_timeout(50, [this]() {
|
||||||
this->temperature_->publish_state(temperature);
|
uint16_t raw_humidity;
|
||||||
if (this->humidity_ != nullptr)
|
if (this->read(reinterpret_cast<uint8_t *>(&raw_humidity), 2) != i2c::ERROR_OK) {
|
||||||
this->humidity_->publish_state(humidity);
|
this->status_set_warning();
|
||||||
if (this->heater_ != nullptr)
|
return;
|
||||||
this->heater_->publish_state(heater_level);
|
}
|
||||||
this->status_clear_warning();
|
raw_humidity = i2c::i2ctohs(raw_humidity);
|
||||||
|
|
||||||
|
float humidity = (float(raw_humidity & 0xFFFC)) * 125.0f / 65536.0f - 6.0f;
|
||||||
|
|
||||||
|
int8_t heater_level = this->get_heater_level();
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Got Humidity=%.1f%% Heater Level=%d", humidity, heater_level);
|
||||||
|
|
||||||
|
if (this->humidity_ != nullptr)
|
||||||
|
this->humidity_->publish_state(humidity);
|
||||||
|
if (this->heater_ != nullptr)
|
||||||
|
this->heater_->publish_state(heater_level);
|
||||||
|
this->status_clear_warning();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTU21DComponent::is_heater_enabled() {
|
bool HTU21DComponent::is_heater_enabled() {
|
||||||
|
|
|
@ -315,7 +315,11 @@ class LoadValidationStep(ConfigValidationStep):
|
||||||
return
|
return
|
||||||
result.add_output_path([self.domain], self.domain)
|
result.add_output_path([self.domain], self.domain)
|
||||||
component = get_component(self.domain)
|
component = get_component(self.domain)
|
||||||
if component.multi_conf_no_default and isinstance(self.conf, core.AutoLoad):
|
if (
|
||||||
|
component is not None
|
||||||
|
and component.multi_conf_no_default
|
||||||
|
and isinstance(self.conf, core.AutoLoad)
|
||||||
|
):
|
||||||
self.conf = []
|
self.conf = []
|
||||||
result[self.domain] = self.conf
|
result[self.domain] = self.conf
|
||||||
path = [self.domain]
|
path = [self.domain]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Constants used by esphome."""
|
"""Constants used by esphome."""
|
||||||
|
|
||||||
__version__ = "2023.12.2"
|
__version__ = "2023.12.3"
|
||||||
|
|
||||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||||
VALID_SUBSTITUTIONS_CHARACTERS = (
|
VALID_SUBSTITUTIONS_CHARACTERS = (
|
||||||
|
|
|
@ -301,11 +301,16 @@ class EsphomePortCommandWebSocket(EsphomeCommandWebSocket):
|
||||||
config_file = settings.rel_path(configuration)
|
config_file = settings.rel_path(configuration)
|
||||||
port = json_message["port"]
|
port = json_message["port"]
|
||||||
if (
|
if (
|
||||||
port == "OTA"
|
port == "OTA" # pylint: disable=too-many-boolean-expressions
|
||||||
and (mdns := dashboard.mdns_status)
|
and (mdns := dashboard.mdns_status)
|
||||||
and (entry := entries.get(config_file))
|
and (entry := entries.get(config_file))
|
||||||
|
and entry.loaded_integrations
|
||||||
|
and "api" in entry.loaded_integrations
|
||||||
and (address := await mdns.async_resolve_host(entry.name))
|
and (address := await mdns.async_resolve_host(entry.name))
|
||||||
):
|
):
|
||||||
|
# Use the IP address if available but only
|
||||||
|
# if the API is loaded and the device is online
|
||||||
|
# since MQTT logging will not work otherwise
|
||||||
port = address
|
port = address
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
Loading…
Reference in a new issue