1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-04 04:12:23 +01: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:
Felix Kaechele
2025-08-31 17:02:56 -04:00
committed by GitHub
parent e29f0ee7f8
commit da21174c6d
2 changed files with 43 additions and 9 deletions

View File

@@ -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

View File

@@ -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