#include "network.h" #include #include #include #include #include #include #if SOC_EMAC_SUPPORTED #include #include #include #endif ESP_EVENT_DEFINE_BASE(SNTP_EVENT); static const char *TAG = "network"; static const struct wifi_networks_t *wifi_nets; static int hidden_net_n = -1; void time_sync_notification_cb(struct timeval *tv) { // NOLINT, it cant ESP_LOGI(TAG, "time synced, unix time is %llu", tv->tv_sec); esp_event_post(SNTP_EVENT, SNTP_EVENT_SYNCED, nullptr, 0, portMAX_DELAY); } // logs IP, starts sntp static void on_get_ip(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { const ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; ESP_LOGI(TAG, "ip getto: " IPSTR, IP2STR(&event->ip_info.ip)); hidden_net_n = -1; // we're connected, nothing left to be attempting sntp_set_time_sync_notification_cb(time_sync_notification_cb); sntp_set_sync_interval(SNTP_TIME_SYNC_INTERVAL_MINUTES * 60 * 1000); esp_sntp_setservername(0, SNTP_SERVER); esp_sntp_init(); } static void start_scan(void) { const wifi_scan_config_t scan_cfg = {.show_hidden = true}; esp_wifi_scan_start(&scan_cfg, false); } // connect to a network 'n' from the list we gave it static void connect_to_net(int n) { const struct wifi_network_t *net = &wifi_nets->nets[n]; wifi_config_t wifi_cfg = {}; strncpy((char *)wifi_cfg.sta.ssid, net->ssid, sizeof(wifi_cfg.sta.ssid) - 1); strncpy((char *)wifi_cfg.sta.password, net->password, sizeof(wifi_cfg.sta.password) - 1); wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; wifi_cfg.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; // check every channel, don't settle for the first probe reply ESP_LOGI(TAG, "connecting to %s%s", net->ssid, net->hidden ? " (hidden)" : ""); esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); esp_wifi_connect(); } static void try_next_hidden_network(void) { for (int i = hidden_net_n + 1; i < wifi_nets->num_nets; i++) { // we only try hidden networks here, skip otherwise if (!wifi_nets->nets[i].hidden) continue; // if network from the list is hidden, try to connect to it hidden_net_n = i; connect_to_net(i); return; } ESP_LOGW(TAG, "no hidden networks left to try, rescanning"); hidden_net_n = -1; start_scan(); } static void on_wifi_disconnect(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { if (hidden_net_n >= 0) { ESP_LOGI(TAG, "connecting to %s failed, trying next hidden network", wifi_nets->nets[hidden_net_n].ssid); try_next_hidden_network(); return; } ESP_LOGI(TAG, "Wi-Fi disconnected, scanning for networks..."); start_scan(); } static void on_scan_done(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { uint16_t ap_count = 0; esp_wifi_scan_get_ap_num(&ap_count); wifi_ap_record_t *ap_list = malloc(ap_count * sizeof(wifi_ap_record_t)); esp_wifi_scan_get_ap_records(&ap_count, ap_list); int best_match = -1; int best_rssi = INT_MIN; for (int i = 0; i < ap_count; i++) { for (int k = 0; k < wifi_nets->num_nets; k++) { if (strcmp((char *)ap_list[i].ssid, wifi_nets->nets[k].ssid) == 0) { if (ap_list[i].rssi > best_rssi) { best_rssi = ap_list[i].rssi; best_match = k; } } } } free(ap_list); hidden_net_n = -1; if (best_match >= 0) { connect_to_net(best_match); return; } ESP_LOGI(TAG, "no visible known networks found, trying hidden ones"); try_next_hidden_network(); } static void set_tz(void) { setenv("TZ", POSIX_TIMEZONE_STRING, true); tzset(); } #if SOC_EMAC_SUPPORTED void init_ethernet(const char *hostname) { set_tz(); ESP_ERROR_CHECK(esp_netif_init()); uint8_t eth_port_cnt = 0; esp_eth_handle_t *eth_handles; // allow ethernet oscillator ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); // install eth chip driver ESP_ERROR_CHECK(ethernet_init_all(ð_handles, ð_port_cnt)); const esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_t *eth_netif = esp_netif_new(&cfg); esp_netif_set_hostname(eth_netif, hostname); ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0]))); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_get_ip, nullptr)); ESP_ERROR_CHECK(esp_eth_start(eth_handles[0])); } #endif void init_wifi(const struct wifi_networks_t *nets, const char *hostname) { set_tz(); nvs_flash_init(); esp_netif_init(); esp_netif_t *netif = esp_netif_create_default_wifi_sta(); esp_netif_set_hostname(netif, hostname); wifi_nets = nets; esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_SCAN_DONE, &on_scan_done, nullptr); esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, nullptr); esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_get_ip, nullptr); const wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg); esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_start(); start_scan(); }