// // Created by erki on 25/01/24. // #include "clock_core.hpp" #include "esp_expected.hpp" #include #include #include #include #include #include #include namespace { const char* TAG = "clock_core"; constexpr EventBits_t WIFI_FAIL_BIT = BIT0; constexpr EventBits_t WIFI_CONNECTED_BIT = BIT1; constexpr EventBits_t SNTP_SYNCED_BIT = BIT2; constexpr EventBits_t CLOCK_UPDATE_BIT = BIT3; EventGroupHandle_t clock_core_event_group_; void wifiEventHandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { static int retry_num = 0; if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { if (retry_num < 10) { esp_wifi_connect(); retry_num++; ESP_LOGI(TAG, "Retrying to connect to AP."); } else { xEventGroupSetBits(clock_core_event_group_, WIFI_FAIL_BIT); } ESP_LOGW(TAG, "Connection to AP failed."); } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { auto* event = static_cast(event_data); ESP_LOGI(TAG, "Connected to AP. Got IP: " IPSTR, IP2STR(&event->ip_info.ip)); retry_num = 0; xEventGroupSetBits(clock_core_event_group_, WIFI_CONNECTED_BIT); } } void sntpEventHandler(struct timeval*) { xEventGroupSetBits(clock_core_event_group_, SNTP_SYNCED_BIT); } void timerEventHandler(TimerHandle_t) { xEventGroupSetBits(clock_core_event_group_, CLOCK_UPDATE_BIT); } esp_err_t sntpInitialize() { esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org"); config.smooth_sync = true; config.server_from_dhcp = true; config.renew_servers_after_new_IP = true; config.sync_cb = sntpEventHandler; config.start = false; config.ip_event_to_renew = IP_EVENT_STA_GOT_IP; return esp_netif_sntp_init(&config); } std::expected wifiInitialize(const char* wifi_ssid, const char* wifi_password) { TRY_ESP(esp_netif_init()); TRY_ESP(esp_event_loop_create_default()); esp_netif_create_default_wifi_sta(); wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT(); TRY_ESP(esp_wifi_init(&config)); TRY_ESP(sntpInitialize()); esp_event_handler_instance_t instance_any_id; esp_event_handler_instance_t instance_got_ip; TRY_ESP(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifiEventHandler, nullptr, &instance_any_id)); TRY_ESP(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifiEventHandler, nullptr, &instance_got_ip)); wifi_sta_config_t sta_config; std::memset(&sta_config, 0, sizeof(sta_config)); std::strncpy((char*) sta_config.ssid, wifi_ssid, 32); std::strncpy((char*) sta_config.password, wifi_password, 64); sta_config.threshold.authmode = WIFI_AUTH_WPA2_PSK; wifi_config_t wifi_config = { .sta = sta_config }; TRY_ESP(esp_wifi_set_mode(WIFI_MODE_STA)); TRY_ESP(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); TRY_ESP(esp_wifi_start()); return {}; } } namespace clock_core { void run(const char* wifi_ssid, const char* wifi_password) { clock_core_event_group_ = xEventGroupCreate(); auto clock_timer = xTimerCreate("clock_core", pdMS_TO_TICKS(60'000), pdTRUE, nullptr, timerEventHandler); if (const auto res = wifiInitialize(wifi_ssid, wifi_password); !res.has_value()) { ESP_LOGI(TAG, "WiFi setup errored in clock_core::run. Error: %s", esp_err_to_name(res.error())); abort(); } while (true) { const EventBits_t bits = xEventGroupWaitBits(clock_core_event_group_, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT | SNTP_SYNCED_BIT | CLOCK_UPDATE_BIT, pdTRUE, pdFALSE, portMAX_DELAY); if (bits & WIFI_CONNECTED_BIT) { ESP_LOGI(TAG, "WiFi setup in clock_core::run successful."); if (const auto res = esp_netif_sntp_start(); res != ESP_OK) { ESP_LOGE(TAG, "SNTP setup failed. Error: %s", esp_err_to_name(res)); abort(); } xTimerStart(clock_timer, pdMS_TO_TICKS(10)); } else if (bits & WIFI_FAIL_BIT) { ESP_LOGE(TAG, "WiFi setup in clock_core::run failed."); } else if (bits & SNTP_SYNCED_BIT) { ESP_LOGI(TAG, "SNTP sync successful."); } else if (bits & CLOCK_UPDATE_BIT) { char time_buf[64]; std::time_t time_now; std::tm time_info{}; std::time(&time_now); localtime_r(&time_now, &time_info); std::strftime(time_buf, sizeof(time_buf), "%c", &time_info); ESP_LOGI(TAG, "Current time: %s", time_buf); } else { ESP_LOGE(TAG, "WiFi setup encountered an unexpected set of bits. %lu", bits); } } } }