mirror of
https://github.com/esphome/esphome.git
synced 2025-01-21 20:06:01 +01:00
SNTP for esp-idf
* report syncronization events * force restart * server list runtime update * server list setup checks * real update interval reported * update interval runtime change
This commit is contained in:
parent
2635c31d7e
commit
12e5d6e7a9
2 changed files with 96 additions and 42 deletions
|
@ -14,15 +14,17 @@
|
|||
#include "lwip/apps/sntp.h"
|
||||
#endif
|
||||
|
||||
// Yes, the server names are leaked, but that's fine.
|
||||
#ifdef CLANG_TIDY
|
||||
#define strdup(x) (const_cast<char *>(x))
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace sntp {
|
||||
|
||||
static const char *const TAG = "sntp";
|
||||
static const std::string FORCE_UPDATE_SCHEDULE = "force_update_schedule";
|
||||
|
||||
const char *server_name_buffer(const auto &server) { return this->server.empty() ? nullptr : this->server.c_str(); }
|
||||
|
||||
#ifdef USE_ESP_IDF
|
||||
static time_t sync_time_to_report_ = 0;
|
||||
#else
|
||||
|
||||
void SNTPComponent::setup() {
|
||||
#ifndef USE_HOST
|
||||
|
@ -37,25 +39,24 @@ void SNTPComponent::setup() {
|
|||
sntp_stop();
|
||||
#endif
|
||||
|
||||
sntp_setservername(0, strdup(this->server_1_.c_str()));
|
||||
if (!this->server_2_.empty()) {
|
||||
sntp_setservername(1, strdup(this->server_2_.c_str()));
|
||||
}
|
||||
if (!this->server_3_.empty()) {
|
||||
sntp_setservername(2, strdup(this->server_3_.c_str()));
|
||||
setup_servers_();
|
||||
this->servers_was_setup_ = true;
|
||||
|
||||
for(uint8_t i = 0; i<3; ++i) {
|
||||
const auto& buff = server_name_buffer(server_[i]);
|
||||
if(buff != nullptr && buff != sntp_getservername()) {
|
||||
ESP_LOGCONFIG(TAG, "Can't set server %d", i+1);
|
||||
}
|
||||
}
|
||||
#ifdef USE_ESP_IDF
|
||||
if (sntp_get_sync_interval() != this->get_update_interval()) {
|
||||
sntp_set_sync_interval(this->get_update_interval());
|
||||
sntp_restart();
|
||||
}
|
||||
|
||||
// Stop pooler but ler the user update by the hands
|
||||
this->stop_poller();
|
||||
#endif
|
||||
sntp_set_time_sync_notification_cb([](struct timeval *tv){
|
||||
sync_time_to_report_ = tv->tv_sec;
|
||||
});
|
||||
#endif // USE_ESP_IDF
|
||||
|
||||
sntp_init();
|
||||
#endif
|
||||
#endif // USE_HOST
|
||||
}
|
||||
void SNTPComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "SNTP Time:");
|
||||
|
@ -64,29 +65,52 @@ void SNTPComponent::dump_config() {
|
|||
ESP_LOGCONFIG(TAG, " Server 3: '%s'", this->server_3_.c_str());
|
||||
ESP_LOGCONFIG(TAG, " Timezone: '%s'", this->timezone_.c_str());
|
||||
}
|
||||
void set_servers(const std::string &server_1, const std::string &server_2, const std::string &server_3);
|
||||
{
|
||||
#if !defined(USE_HOST)
|
||||
if(servers_was_setup_) {
|
||||
for(uint8_t i = 0; i<3; ++i) {
|
||||
const auto& buff = this->servers_[i].empty()
|
||||
? nullptr
|
||||
: this->servers_[i].c_str();
|
||||
if(buff != nullptr && buff == sntp_getservername(i))
|
||||
sntp_setservername(i, nullptr);
|
||||
max_setup_server = max(max_setup_server, i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
this->servers_ = {server_1, server_2, server_3};
|
||||
#if !defined(USE_HOST)
|
||||
if(this->servers_was_setup_) {
|
||||
setup_servers_();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void SNTPComponent::update() {
|
||||
#if !defined(USE_HOST)
|
||||
#if defined(USE_ESP_IDF)
|
||||
if (sntp_enabled()) {
|
||||
ESP_LOGD(TAG, "Restart SNTP");
|
||||
this->has_time_ = false;
|
||||
if (!sntp_restart()) {
|
||||
ESP_LOGD(TAG, "Can't restart SNTP");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGD(TAG, "SNTP is not enabled");
|
||||
}
|
||||
#else
|
||||
// force resync
|
||||
if (sntp_enabled()) {
|
||||
#if defined(USE_ESP_IDF)
|
||||
sntp_restart();
|
||||
#else
|
||||
sntp_stop();
|
||||
this->has_time_ = false;
|
||||
sntp_init();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void SNTPComponent::loop() {
|
||||
#ifdef USE_ESP_IDF
|
||||
if (sync_time_to_report_ != 0) {
|
||||
this->cancel_timeout(FORCE_UPDATE_SCHEDULE);
|
||||
time_t time_to_report = 0;
|
||||
swap(sync_time_to_report_, time_to_report);
|
||||
const ESPTime time = ESPTime::from_epoch_local(time_to_report);
|
||||
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);
|
||||
}
|
||||
#else
|
||||
if (this->has_time_)
|
||||
return;
|
||||
|
||||
|
@ -96,11 +120,37 @@ void SNTPComponent::loop() {
|
|||
|
||||
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);
|
||||
#endif
|
||||
this->time_sync_callback_.call();
|
||||
this->has_time_ = true;
|
||||
}
|
||||
#ifdef USE_ESP_IDF
|
||||
void SNTPComponent::set_update_interval(uint32_t update_interval) {
|
||||
time::RealTimeClock::set_update_interval(update_interval);
|
||||
const auto previous_sync_interval = sntp_get_sync_interval();
|
||||
|
||||
bool SNTPComponent::is_in_progress() const { return sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET; }
|
||||
sntp_set_sync_interval(update_interval);
|
||||
const auto new_sync_interval = sntp_get_sync_interval();
|
||||
|
||||
if(previous_sync_interval > new_sync_interval) {
|
||||
this->set_timeout(FORCE_UPDATE_SCHEDULE, new_sync_interval, []{
|
||||
sntp_restart();
|
||||
});
|
||||
}
|
||||
}
|
||||
uint32_t SNTPComponent::get_update_interval() const {
|
||||
return sntp_get_sync_interval();
|
||||
}
|
||||
#endif
|
||||
void SNTPComponent::setup_servers_() {
|
||||
for(uint8_t i = 0; i<3; ++i) {
|
||||
const auto& buff = server_name_buffer(this->servers_[i]);
|
||||
sntp_setservername(i, buff);
|
||||
if(buff != nullptr && buff != sntp_getservername()) {
|
||||
ESP_LOGE(TAG, "Can't set server %d", i+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sntp
|
||||
} // namespace esphome
|
||||
|
|
|
@ -17,23 +17,27 @@ class SNTPComponent : public time::RealTimeClock {
|
|||
void setup() override;
|
||||
void dump_config() override;
|
||||
/// Change the servers used by SNTP for timekeeping
|
||||
void set_servers(const std::string &server_1, const std::string &server_2, const std::string &server_3) {
|
||||
this->server_1_ = server_1;
|
||||
this->server_2_ = server_2;
|
||||
this->server_3_ = server_3;
|
||||
}
|
||||
void set_servers(const std::string &server_1, const std::string &server_2, const std::string &server_3);
|
||||
float get_setup_priority() const override { return setup_priority::BEFORE_CONNECTION; }
|
||||
|
||||
void update() override;
|
||||
void loop() override;
|
||||
|
||||
bool is_in_progress() const;
|
||||
#ifdef USE_ESP_IDF
|
||||
void set_update_interval(uint32_t update_interval) override;
|
||||
uint32_t get_update_interval() const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void setup_servers_();
|
||||
|
||||
private:
|
||||
// Private because buffer address should stay unchanged
|
||||
std::string servers_[3];
|
||||
|
||||
protected:
|
||||
std::string server_1_;
|
||||
std::string server_2_;
|
||||
std::string server_3_;
|
||||
bool has_time_{false};
|
||||
#endif
|
||||
bool servers_was_setup_{false};
|
||||
};
|
||||
|
||||
} // namespace sntp
|
||||
|
|
Loading…
Reference in a new issue