1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-02 08:01:50 +00:00

Compare commits

...

14 Commits

Author SHA1 Message Date
Jesse Hills
ce5a323f91 Merge pull request #6408 from esphome/bump-2024.3.0
2024.3.0
2024-03-20 18:30:49 +13:00
Jesse Hills
9541df9d88 Bump version to 2024.3.0 2024-03-20 17:15:19 +13:00
Jesse Hills
be15122e8b Merge pull request #6407 from esphome/bump-2024.3.0b5
2024.3.0b5
2024-03-20 17:11:24 +13:00
Jesse Hills
6f7273d9cb Bump version to 2024.3.0b5 2024-03-20 16:38:15 +13:00
RFDarter
ccca545862 web_server support for v3 (#6203) 2024-03-20 16:38:15 +13:00
Clyde Stubbs
e27e342927 Show component warnings and errors in the log; (#6400) 2024-03-20 16:38:15 +13:00
Clyde Stubbs
507568db64 AHT10: Use state machine to avoid blocking delay (#6401) 2024-03-20 16:38:15 +13:00
Jesse Hills
156d2c04f9 Merge pull request #6397 from esphome/bump-2024.3.0b4
2024.3.0b4
2024-03-19 15:37:30 +13:00
Jesse Hills
855b1fd706 Bump version to 2024.3.0b4 2024-03-19 14:22:28 +13:00
Jesse Hills
c56c40cb82 Require xsrf/csrf when using a password (#6396) 2024-03-19 14:22:28 +13:00
Mike La Spina
a3bd8ad025 ld2420: Firmware v1.5.4+ bug workaround (#6168) 2024-03-19 14:22:28 +13:00
Stefan Rado
db1b187e80 Fix wrong initialization of vectors in ade7953_i2c (#6393) 2024-03-19 14:22:28 +13:00
Stefan Rado
9442f7a271 Fix sending packets to uponor_smatrix devices (#6392) 2024-03-19 14:22:28 +13:00
swoboda1337
b3aa950c60 Fix bug in remote_base conditional (#6281)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda>
2024-03-19 14:22:28 +13:00
15 changed files with 138 additions and 96 deletions

View File

@@ -13,29 +13,29 @@ void AdE7953I2c::dump_config() {
ade7953_base::ADE7953::dump_config();
}
bool AdE7953I2c::ade_write_8(uint16_t reg, uint8_t value) {
std::vector<uint8_t> data(3);
data.push_back(reg >> 8);
data.push_back(reg >> 0);
data.push_back(value);
return this->write(data.data(), data.size()) != i2c::ERROR_OK;
uint8_t data[3];
data[0] = reg >> 8;
data[1] = reg >> 0;
data[2] = value;
return this->write(data, 3) != i2c::ERROR_OK;
}
bool AdE7953I2c::ade_write_16(uint16_t reg, uint16_t value) {
std::vector<uint8_t> data(4);
data.push_back(reg >> 8);
data.push_back(reg >> 0);
data.push_back(value >> 8);
data.push_back(value >> 0);
return this->write(data.data(), data.size()) != i2c::ERROR_OK;
uint8_t data[4];
data[0] = reg >> 8;
data[1] = reg >> 0;
data[2] = value >> 8;
data[3] = value >> 0;
return this->write(data, 4) != i2c::ERROR_OK;
}
bool AdE7953I2c::ade_write_32(uint16_t reg, uint32_t value) {
std::vector<uint8_t> data(6);
data.push_back(reg >> 8);
data.push_back(reg >> 0);
data.push_back(value >> 24);
data.push_back(value >> 16);
data.push_back(value >> 8);
data.push_back(value >> 0);
return this->write(data.data(), data.size()) != i2c::ERROR_OK;
uint8_t data[6];
data[0] = reg >> 8;
data[1] = reg >> 0;
data[2] = value >> 24;
data[3] = value >> 16;
data[4] = value >> 8;
data[5] = value >> 0;
return this->write(data, 6) != i2c::ERROR_OK;
}
bool AdE7953I2c::ade_read_8(uint16_t reg, uint8_t *value) {
uint8_t reg_data[2];

View File

@@ -36,6 +36,7 @@ static const uint8_t AHT10_INIT_ATTEMPTS = 10;
static const uint8_t AHT10_STATUS_BUSY = 0x80;
void AHT10Component::setup() {
this->read_delay_ = this->humidity_sensor_ != nullptr ? AHT10_HUMIDITY_DELAY : AHT10_DEFAULT_DELAY;
if (this->write(AHT10_SOFTRESET_CMD, sizeof(AHT10_SOFTRESET_CMD)) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Reset AHT10 failed!");
}
@@ -83,74 +84,78 @@ void AHT10Component::setup() {
ESP_LOGV(TAG, "AHT10 initialization");
}
void AHT10Component::update() {
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Communication with AHT10 failed!");
this->status_set_warning();
return;
}
uint8_t data[6];
uint8_t delay_ms = AHT10_DEFAULT_DELAY;
if (this->humidity_sensor_ != nullptr)
delay_ms = AHT10_HUMIDITY_DELAY;
bool success = false;
for (int i = 0; i < AHT10_ATTEMPTS; ++i) {
ESP_LOGVV(TAG, "Attempt %d at %6" PRIu32, i, millis());
delay(delay_ms);
if (this->read(data, 6) != i2c::ERROR_OK) {
ESP_LOGD(TAG, "Communication with AHT10 failed, waiting...");
continue;
}
if ((data[0] & 0x80) == 0x80) { // Bit[7] = 0b1, device is busy
ESP_LOGD(TAG, "AHT10 is busy, waiting...");
} else if (data[1] == 0x0 && data[2] == 0x0 && (data[3] >> 4) == 0x0) {
// Unrealistic humidity (0x0)
if (this->humidity_sensor_ == nullptr) {
ESP_LOGVV(TAG, "ATH10 Unrealistic humidity (0x0), but humidity is not required");
break;
} else {
ESP_LOGD(TAG, "ATH10 Unrealistic humidity (0x0), retrying...");
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Communication with AHT10 failed!");
this->status_set_warning();
return;
}
}
} else {
// data is valid, we can break the loop
ESP_LOGVV(TAG, "Answer at %6" PRIu32, millis());
success = true;
break;
}
}
if (!success || (data[0] & 0x80) == 0x80) {
void AHT10Component::restart_read_() {
if (this->read_count_ == AHT10_ATTEMPTS) {
this->read_count_ = 0;
ESP_LOGE(TAG, "Measurements reading timed-out!");
this->status_set_warning();
this->status_set_error();
return;
}
this->read_count_++;
this->set_timeout(this->read_delay_, [this]() { this->read_data_(); });
}
void AHT10Component::read_data_() {
uint8_t data[6];
ESP_LOGD(TAG, "Read attempt %d at %ums", this->read_count_, (unsigned) (millis() - this->start_time_));
if (this->read(data, 6) != i2c::ERROR_OK) {
ESP_LOGD(TAG, "Communication with AHT10 failed, waiting...");
this->restart_read_();
return;
}
if ((data[0] & 0x80) == 0x80) { // Bit[7] = 0b1, device is busy
ESP_LOGD(TAG, "AHT10 is busy, waiting...");
this->restart_read_();
return;
}
if (data[1] == 0x0 && data[2] == 0x0 && (data[3] >> 4) == 0x0) {
// Unrealistic humidity (0x0)
if (this->humidity_sensor_ == nullptr) {
ESP_LOGV(TAG, "ATH10 Unrealistic humidity (0x0), but humidity is not required");
} else {
ESP_LOGD(TAG, "ATH10 Unrealistic humidity (0x0), retrying...");
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Communication with AHT10 failed!");
this->status_set_warning();
}
this->restart_read_();
return;
}
}
ESP_LOGD(TAG, "Success at %ums", (unsigned) (millis() - this->start_time_));
uint32_t raw_temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5];
uint32_t raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4;
float temperature = ((200.0f * (float) raw_temperature) / 1048576.0f) - 50.0f;
float humidity;
if (raw_humidity == 0) { // unrealistic value
humidity = NAN;
} else {
humidity = (float) raw_humidity * 100.0f / 1048576.0f;
}
if (this->temperature_sensor_ != nullptr) {
float temperature = ((200.0f * (float) raw_temperature) / 1048576.0f) - 50.0f;
this->temperature_sensor_->publish_state(temperature);
}
if (this->humidity_sensor_ != nullptr) {
float humidity;
if (raw_humidity == 0) { // unrealistic value
humidity = NAN;
} else {
humidity = (float) raw_humidity * 100.0f / 1048576.0f;
}
if (std::isnan(humidity)) {
ESP_LOGW(TAG, "Invalid humidity! Sensor reported 0%% Hum");
}
this->humidity_sensor_->publish_state(humidity);
}
this->status_clear_warning();
this->read_count_ = 0;
}
void AHT10Component::update() {
if (this->read_count_ != 0)
return;
this->start_time_ = millis();
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Communication with AHT10 failed!");
this->status_set_warning();
return;
}
this->restart_read_();
}
float AHT10Component::get_setup_priority() const { return setup_priority::DATA; }

View File

@@ -26,6 +26,11 @@ class AHT10Component : public PollingComponent, public i2c::I2CDevice {
sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *humidity_sensor_{nullptr};
AHT10Variant variant_{};
unsigned read_count_{};
unsigned read_delay_{};
void read_data_();
void restart_read_();
uint32_t start_time_{};
};
} // namespace aht10

View File

@@ -211,10 +211,11 @@ void LD2420Component::factory_reset_action() {
void LD2420Component::restart_module_action() {
ESP_LOGCONFIG(TAG, "Restarting LD2420 module...");
this->send_module_restart();
delay_microseconds_safe(45000);
this->set_config_mode(true);
this->set_system_mode(system_mode_);
this->set_config_mode(false);
this->set_timeout(250, [this]() {
this->set_config_mode(true);
this->set_system_mode(system_mode_);
this->set_config_mode(false);
});
ESP_LOGCONFIG(TAG, "LD2420 Restarted.");
}
@@ -527,18 +528,16 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
this->write_byte(cmd_buffer[index]);
}
delay_microseconds_safe(500); // give the module a moment to process it
error = 0;
if (frame.command == CMD_RESTART) {
delay_microseconds_safe(25000); // Wait for the restart
return 0; // restart does not reply exit now
return 0; // restart does not reply exit now
}
while (!this->cmd_reply_.ack) {
while (available()) {
this->readline_(read(), ack_buffer, sizeof(ack_buffer));
}
delay_microseconds_safe(250);
delay_microseconds_safe(1450);
if (loop_count <= 0) {
error = LD2420_ERROR_TIMEOUT;
retry--;

View File

@@ -16,7 +16,7 @@ RemoteRMTChannel::RemoteRMTChannel(uint8_t mem_block_num) : mem_block_num_(mem_b
}
void RemoteRMTChannel::config_rmt(rmt_config_t &rmt) {
if (rmt_channel_t(int(this->channel_) + this->mem_block_num_) >= RMT_CHANNEL_MAX) {
if (rmt_channel_t(int(this->channel_) + this->mem_block_num_) > RMT_CHANNEL_MAX) {
this->mem_block_num_ = int(RMT_CHANNEL_MAX) - int(this->channel_);
ESP_LOGW(TAG, "Not enough RMT memory blocks available, reduced to %i blocks.", this->mem_block_num_);
}

View File

@@ -173,7 +173,9 @@ bool UponorSmatrixComponent::send(uint16_t device_address, const UponorSmatrixDa
return false;
// Assemble packet for send queue. All fields are big-endian except for the little-endian checksum.
std::vector<uint8_t> packet(6 + 3 * data_len);
std::vector<uint8_t> packet;
packet.reserve(6 + 3 * data_len);
packet.push_back(this->address_ >> 8);
packet.push_back(this->address_ >> 0);
packet.push_back(device_address >> 8);

View File

@@ -44,6 +44,11 @@ def default_url(config):
config[CONF_CSS_URL] = ""
if not (CONF_JS_URL in config):
config[CONF_JS_URL] = "https://oi.esphome.io/v2/www.js"
if config[CONF_VERSION] == 3:
if not (CONF_CSS_URL in config):
config[CONF_CSS_URL] = ""
if not (CONF_JS_URL in config):
config[CONF_JS_URL] = "https://oi.esphome.io/v3/www.js"
return config
@@ -64,7 +69,7 @@ CONFIG_SCHEMA = cv.All(
{
cv.GenerateID(): cv.declare_id(WebServer),
cv.Optional(CONF_PORT, default=80): cv.port,
cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, int=True),
cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, 3, int=True),
cv.Optional(CONF_CSS_URL): cv.string,
cv.Optional(CONF_CSS_INCLUDE): cv.file_,
cv.Optional(CONF_JS_URL): cv.string,
@@ -152,7 +157,7 @@ async def to_code(config):
cg.add_define("USE_WEBSERVER")
cg.add_define("USE_WEBSERVER_PORT", config[CONF_PORT])
cg.add_define("USE_WEBSERVER_VERSION", version)
if version == 2:
if version >= 2:
# Don't compress the index HTML as the data sizes are almost the same.
add_resource_as_progmem("INDEX_HTML", build_index_html(config), compress=False)
else:

View File

@@ -358,7 +358,7 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) {
stream->print(F("</article></body></html>"));
request->send(stream);
}
#elif USE_WEBSERVER_VERSION == 2
#elif USE_WEBSERVER_VERSION >= 2
void WebServer::handle_index_request(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response =
request->beginResponse_P(200, "text/html", ESPHOME_WEBSERVER_INDEX_HTML, ESPHOME_WEBSERVER_INDEX_HTML_SIZE);

View File

@@ -13,7 +13,7 @@
#include <freertos/semphr.h>
#endif
#if USE_WEBSERVER_VERSION == 2
#if USE_WEBSERVER_VERSION >= 2
extern const uint8_t ESPHOME_WEBSERVER_INDEX_HTML[] PROGMEM;
extern const size_t ESPHOME_WEBSERVER_INDEX_HTML_SIZE;
#endif

View File

@@ -1,6 +1,6 @@
"""Constants used by esphome."""
__version__ = "2024.3.0b3"
__version__ = "2024.3.0"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
VALID_SUBSTITUTIONS_CHARACTERS = (

View File

@@ -141,18 +141,35 @@ bool Component::is_ready() {
(this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_SETUP;
}
bool Component::can_proceed() { return true; }
bool Component::status_has_warning() { return this->component_state_ & STATUS_LED_WARNING; }
bool Component::status_has_error() { return this->component_state_ & STATUS_LED_ERROR; }
void Component::status_set_warning() {
bool Component::status_has_warning() const { return this->component_state_ & STATUS_LED_WARNING; }
bool Component::status_has_error() const { return this->component_state_ & STATUS_LED_ERROR; }
void Component::status_set_warning(const char *message) {
// Don't spam the log. This risks missing different warning messages though.
if ((this->component_state_ & STATUS_LED_WARNING) != 0)
return;
this->component_state_ |= STATUS_LED_WARNING;
App.app_state_ |= STATUS_LED_WARNING;
ESP_LOGW(this->get_component_source(), "Warning set: %s", message);
}
void Component::status_set_error() {
void Component::status_set_error(const char *message) {
if ((this->component_state_ & STATUS_LED_ERROR) != 0)
return;
this->component_state_ |= STATUS_LED_ERROR;
App.app_state_ |= STATUS_LED_ERROR;
ESP_LOGE(this->get_component_source(), "Error set: %s", message);
}
void Component::status_clear_warning() {
if ((this->component_state_ & STATUS_LED_WARNING) == 0)
return;
this->component_state_ &= ~STATUS_LED_WARNING;
ESP_LOGW(this->get_component_source(), "Warning cleared");
}
void Component::status_clear_error() {
if ((this->component_state_ & STATUS_LED_ERROR) == 0)
return;
this->component_state_ &= ~STATUS_LED_ERROR;
ESP_LOGE(this->get_component_source(), "Error cleared");
}
void Component::status_clear_warning() { this->component_state_ &= ~STATUS_LED_WARNING; }
void Component::status_clear_error() { this->component_state_ &= ~STATUS_LED_ERROR; }
void Component::status_momentary_warning(const std::string &name, uint32_t length) {
this->status_set_warning();
this->set_timeout(name, length, [this]() { this->status_clear_warning(); });

View File

@@ -124,13 +124,13 @@ class Component {
virtual bool can_proceed();
bool status_has_warning();
bool status_has_warning() const;
bool status_has_error();
bool status_has_error() const;
void status_set_warning();
void status_set_warning(const char *message = "unspecified");
void status_set_error();
void status_set_error(const char *message = "unspecified");
void status_clear_warning();

View File

@@ -688,6 +688,11 @@ class MainRequestHandler(BaseHandler):
@authenticated
def get(self) -> None:
begin = bool(self.get_argument("begin", False))
if settings.using_password:
# Simply accessing the xsrf_token sets the cookie for us
self.xsrf_token # pylint: disable=pointless-statement
else:
self.clear_cookie("_xsrf")
self.render(
"index.template.html",
@@ -1102,6 +1107,7 @@ def make_app(debug=get_bool_env(ENV_DEV)) -> tornado.web.Application:
"log_function": log_function,
"websocket_ping_interval": 30.0,
"template_path": get_base_frontend_path(),
"xsrf_cookies": settings.using_password,
}
rel = settings.relative_url
return tornado.web.Application(

View File

@@ -12,7 +12,7 @@ pyserial==3.5
platformio==6.1.13 # When updating platformio, also update Dockerfile
esptool==4.7.0
click==8.1.7
esphome-dashboard==20231107.0
esphome-dashboard==20240319.0
aioesphomeapi==23.1.1
zeroconf==0.131.0
python-magic==0.4.27

View File

@@ -23,6 +23,9 @@ logger:
api:
reboot_timeout: 10min
web_server:
version: 3
time:
- platform: sntp