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