mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 06:33:51 +00:00 
			
		
		
		
	| @@ -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; } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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: | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| """Constants used by esphome.""" | ||||
|  | ||||
| __version__ = "2024.3.0b4" | ||||
| __version__ = "2024.3.0b5" | ||||
|  | ||||
| ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" | ||||
| VALID_SUBSTITUTIONS_CHARACTERS = ( | ||||
|   | ||||
| @@ -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(); }); | ||||
|   | ||||
| @@ -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(); | ||||
|  | ||||
|   | ||||
| @@ -23,6 +23,9 @@ logger: | ||||
| api: | ||||
|   reboot_timeout: 10min | ||||
|  | ||||
| web_server: | ||||
|   version: 3 | ||||
|  | ||||
| time: | ||||
|   - platform: sntp | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user