mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	[sntp] Use callbacks to trigger on_time_sync for ESP32 and ESP8266 (#10390)
				
					
				
			Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -14,8 +14,13 @@ namespace sntp { | |||||||
|  |  | ||||||
| static const char *const TAG = "sntp"; | static const char *const TAG = "sntp"; | ||||||
|  |  | ||||||
|  | #if defined(USE_ESP32) | ||||||
|  | SNTPComponent *SNTPComponent::instance = nullptr;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| void SNTPComponent::setup() { | void SNTPComponent::setup() { | ||||||
| #if defined(USE_ESP32) | #if defined(USE_ESP32) | ||||||
|  |   SNTPComponent::instance = this; | ||||||
|   if (esp_sntp_enabled()) { |   if (esp_sntp_enabled()) { | ||||||
|     esp_sntp_stop(); |     esp_sntp_stop(); | ||||||
|   } |   } | ||||||
| @@ -25,6 +30,11 @@ void SNTPComponent::setup() { | |||||||
|     esp_sntp_setservername(i++, server.c_str()); |     esp_sntp_setservername(i++, server.c_str()); | ||||||
|   } |   } | ||||||
|   esp_sntp_set_sync_interval(this->get_update_interval()); |   esp_sntp_set_sync_interval(this->get_update_interval()); | ||||||
|  |   esp_sntp_set_time_sync_notification_cb([](struct timeval *tv) { | ||||||
|  |     if (SNTPComponent::instance != nullptr) { | ||||||
|  |       SNTPComponent::instance->defer([]() { SNTPComponent::instance->time_synced(); }); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|   esp_sntp_init(); |   esp_sntp_init(); | ||||||
| #else | #else | ||||||
|   sntp_stop(); |   sntp_stop(); | ||||||
| @@ -34,6 +44,14 @@ void SNTPComponent::setup() { | |||||||
|   for (auto &server : this->servers_) { |   for (auto &server : this->servers_) { | ||||||
|     sntp_setservername(i++, server.c_str()); |     sntp_setservername(i++, server.c_str()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | #if defined(USE_ESP8266) | ||||||
|  |   settimeofday_cb([this](bool from_sntp) { | ||||||
|  |     if (from_sntp) | ||||||
|  |       this->time_synced(); | ||||||
|  |   }); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   sntp_init(); |   sntp_init(); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| @@ -46,7 +64,8 @@ void SNTPComponent::dump_config() { | |||||||
| } | } | ||||||
| void SNTPComponent::update() { | void SNTPComponent::update() { | ||||||
| #if !defined(USE_ESP32) | #if !defined(USE_ESP32) | ||||||
|   // force resync |   // Some platforms currently cannot set the sync interval at runtime so we need | ||||||
|  |   // to do the re-sync by hand for now. | ||||||
|   if (sntp_enabled()) { |   if (sntp_enabled()) { | ||||||
|     sntp_stop(); |     sntp_stop(); | ||||||
|     this->has_time_ = false; |     this->has_time_ = false; | ||||||
| @@ -55,23 +74,31 @@ void SNTPComponent::update() { | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
| void SNTPComponent::loop() { | void SNTPComponent::loop() { | ||||||
|  | // The loop is used to infer whether we have valid time on platforms where we | ||||||
|  | // cannot tell whether SNTP has succeeded. | ||||||
|  | // One limitation of this approach is that we cannot tell if it was the SNTP | ||||||
|  | // component that set the time. | ||||||
|  | // ESP-IDF and ESP8266 use callbacks from the SNTP task to trigger the | ||||||
|  | // `on_time_sync` trigger on successful sync events. | ||||||
|  | #if defined(USE_ESP32) || defined(USE_ESP8266) | ||||||
|  |   this->disable_loop(); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   if (this->has_time_) |   if (this->has_time_) | ||||||
|     return; |     return; | ||||||
|  |  | ||||||
|  |   this->time_synced(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SNTPComponent::time_synced() { | ||||||
|   auto time = this->now(); |   auto time = this->now(); | ||||||
|   if (!time.is_valid()) |   this->has_time_ = time.is_valid(); | ||||||
|  |   if (!this->has_time_) | ||||||
|     return; |     return; | ||||||
|  |  | ||||||
|   ESP_LOGD(TAG, "Synchronized time: %04d-%02d-%02d %02d:%02d:%02d", time.year, time.month, time.day_of_month, time.hour, |   ESP_LOGD(TAG, "Synchronized time: %04d-%02d-%02d %02d:%02d:%02d", time.year, time.month, time.day_of_month, time.hour, | ||||||
|            time.minute, time.second); |            time.minute, time.second); | ||||||
|   this->time_sync_callback_.call(); |   this->time_sync_callback_.call(); | ||||||
|   this->has_time_ = true; |  | ||||||
|  |  | ||||||
| #ifdef USE_ESP_IDF |  | ||||||
|   // On ESP-IDF, time sync is permanent and update() doesn't force resync |  | ||||||
|   // Time is now synchronized, no need to check anymore |  | ||||||
|   this->disable_loop(); |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace sntp | }  // namespace sntp | ||||||
|   | |||||||
| @@ -26,9 +26,16 @@ class SNTPComponent : public time::RealTimeClock { | |||||||
|   void update() override; |   void update() override; | ||||||
|   void loop() override; |   void loop() override; | ||||||
|  |  | ||||||
|  |   void time_synced(); | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   std::vector<std::string> servers_; |   std::vector<std::string> servers_; | ||||||
|   bool has_time_{false}; |   bool has_time_{false}; | ||||||
|  |  | ||||||
|  | #if defined(USE_ESP32) | ||||||
|  |  private: | ||||||
|  |   static SNTPComponent *instance; | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace sntp | }  // namespace sntp | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user