Fri, 20 Oct 2023 15:57:56 +0200
Added framework for the DCF77 transmitter. Added two debug LEDs.
/** * @file task_wifi.c * @brief WiFi task. Connect to the known AP with the strongest signal. */ #include "dcf77tx.h" #define MAX_AP_NUM 10 static const char *TAG = "task_wifi"; SemaphoreHandle_t xSemaphoreWiFi = NULL; ///< Semaphore WiFi task. EventGroupHandle_t xEventGroupWifi; ///< Events WiFi task. wifi_config_t *task_wifi_ConfigSTA = NULL; ///< Current STA configuration. WIFI_State *wifi_state = NULL; ///< Public state for other tasks. esp_netif_t *sta_netif = NULL; ///< Station interface //wifi_scan_config_t scan_config = { ///< WiFi scanner configuration. // .ssid = (uint8_t *)CONFIG_ESP_WIFI_SSID, // .bssid = 0, // .channel = 0, // .show_hidden = false //}; bool System_TimeOk = false; ///< True if online and sntp sync. int8_t _wifi_RSSI = -127; ///< Latest RSSI level. extern char hostname[]; ///< Generated hostname const int TASK_WIFI_REQUEST_STA_DISCONNECT = BIT0; ///< When set, means a client requested to disconnect from currently connected AP. const int TASK_WIFI_REQUEST_STA_CONNECT = BIT1; ///< When set, means a client requested to connect to an access point. const int TASK_WIFI_HAS_IP = BIT4; ///< Indicate that we have an IP address const int TASK_WIFI_STA_FAILED = BIT5; ///< Indicate that we could not get a connection to AP as station. const int TASK_WIFI_STA_DISCONNECTED = BIT6; ///< Indicate that we are disconnected from an ap station. const int TASK_WIFI_STA_CONNECTED = BIT7; ///< Indicate that we are connected to AP as station, flip of BIT5. /** * @brief Array with AP security names */ const char *apsec[] = { "Open", "WEP", "WPA", "WPA2", "WPA WPA2", "Enterprise" }; /****************************************************************************/ bool ready_WiFi(void) { if (wifi_state->STA_connected && wifi_state->STA_online) return true; return false; } void request_WiFi(void) { xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); } void disconnect_WiFi(void) { xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT); xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); } static void print_servers(void) { ESP_LOGI(TAG, "List of configured NTP servers:"); for (uint8_t i = 0; i < SNTP_MAX_SERVERS; ++i){ if (esp_sntp_getservername(i)){ ESP_LOGI(TAG, "server %d: %s", i, esp_sntp_getservername(i)); } else { // we have either IPv4 or IPv6 address, let's print it char buff[64]; ip_addr_t const *ip = esp_sntp_getserver(i); if (ipaddr_ntoa_r(ip, buff, 64) != NULL) ESP_LOGI(TAG, "server %d: %s", i, buff); } } } static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { switch (event_id) { case WIFI_EVENT_STA_START: { ESP_LOGI(TAG, "Event wifi START"); // Set the configured hostname for the dhcp client. ESP_ERROR_CHECK(esp_netif_set_hostname(sta_netif, hostname)); esp_wifi_connect(); break; } case WIFI_EVENT_STA_CONNECTED: { wifi_event_sta_connected_t* event = (wifi_event_sta_connected_t*) event_data; wifi_ap_record_t ap_info; esp_wifi_sta_get_ap_info(&ap_info); ESP_LOGI(TAG, "Event STA connected, ssid:%s, bssid:" MACSTR ", channel:%d, rssi: %d, authmode:%s", ap_info.ssid, MAC2STR(ap_info.bssid), event->channel, ap_info.rssi, apsec[event->authmode]); if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) { wifi_state->STA_connected = true; wifi_state->STA_rssi = ap_info.rssi; wifi_state->STA_channel = ap_info.primary; sprintf(wifi_state->STA_ssid, "%s", ap_info.ssid); snprintf(wifi_state->STA_bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x", ap_info.bssid[0], ap_info.bssid[1], ap_info.bssid[2], ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]); xSemaphoreGive(xSemaphoreWiFi); } else { ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_CONNECTED"); } print_servers(); xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); break; } case WIFI_EVENT_STA_DISCONNECTED: { wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data; ESP_LOGI(TAG, "Event STA disconnected, ssid:%s, ssid_len:%d, bssid:" MACSTR ", reason:%d", disconnected->ssid, disconnected->ssid_len, MAC2STR(disconnected->bssid), disconnected->reason); if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) { wifi_state->STA_connected = false; wifi_state->STA_online = false; wifi_state->STA_rssi = 0; xSemaphoreGive(xSemaphoreWiFi); } else { ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_DISCONNECTED"); } System_TimeOk = false; xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); break; } default: ESP_LOGW(TAG, "Unknown WiFi event %ld", event_id); break; } } static void got_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { switch (event_id) { case IP_EVENT_STA_GOT_IP: xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_HAS_IP); ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { wifi_state->STA_online = true; snprintf(wifi_state->STA_ip, 16, IPSTR, IP2STR(&event->ip_info.ip)); snprintf(wifi_state->STA_nm, 16, IPSTR, IP2STR(&event->ip_info.netmask)); snprintf(wifi_state->STA_gw, 16, IPSTR, IP2STR(&event->ip_info.gw)); xSemaphoreGive(xSemaphoreWiFi); } else { ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_GOT_IP"); } // ESP_LOGI(TAG, "Starting SNTP"); // esp_netif_sntp_start(); break; case IP_EVENT_STA_LOST_IP: ESP_LOGW(TAG, "Lost IP address"); xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_HAS_IP); if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { wifi_state->STA_ip[0] = '\0'; wifi_state->STA_nm[0] = '\0'; wifi_state->STA_gw[0] = '\0'; wifi_state->STA_online = false; xSemaphoreGive(xSemaphoreWiFi); } else { ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_LOST_IP"); } System_TimeOk = false; break; case IP_EVENT_AP_STAIPASSIGNED: ESP_LOGI(TAG, "IP_EVENT_AP_STAIPASSIGNED"); break; default: ESP_LOGW(TAG, "Unknown IP event %ld", event_id); break; } } void time_sync_notification_cb(struct timeval *tv) { time_t now; char strftime_buf[64]; struct tm timeinfo; ESP_LOGI(TAG, "Notification of a time synchronization event"); int rc = sntp_get_sync_status(); if (rc == SNTP_SYNC_STATUS_COMPLETED) { time(&now); localtime_r(&now, &timeinfo); System_TimeOk = true; strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); ESP_LOGI(TAG, "NTP time is set: %s", strftime_buf); } else { ESP_LOGI(TAG, "NTP unknown time sync event rc=%d", rc); System_TimeOk = false; } } void task_wifi( void * pvParameters ) { ESP_LOGI(TAG, "Starting WiFi"); /* event handler and event group for the wifi driver */ xEventGroupWifi = xEventGroupCreate(); /* initialize the tcp stack */ ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); sta_netif = esp_netif_create_default_wifi_sta(); assert(sta_netif); /* * Setup SNTP configuration */ /** * NTP server address could be acquired via DHCP, * see following menuconfig options: * 'LWIP_DHCP_GET_NTP_SRV' - enable STNP over DHCP * 'LWIP_SNTP_DEBUG' - enable debugging messages * * NOTE: This call should be made BEFORE esp acquires IP address from DHCP, * otherwise NTP option would be rejected by default. */ ESP_LOGI(TAG, "Initializing SNTP"); esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org"); config.start = false; // start SNTP service explicitly (after connecting) config.server_from_dhcp = true; // accept NTP offers from DHCP server, if any (need to enable *before* connecting) config.renew_servers_after_new_IP = true; // let esp-netif update configured SNTP server(s) after receiving DHCP lease config.index_of_first_server = 1; // updates from server num 1, leaving server 0 (from DHCP) intact config.ip_event_to_renew = IP_EVENT_STA_GOT_IP; config.sync_cb = time_sync_notification_cb; // only if we need the notification function esp_netif_sntp_init(&config); ESP_LOGI(TAG, "Starting SNTP"); esp_netif_sntp_start(); /* * memory allocation of objects used by the task */ xSemaphoreWiFi = xSemaphoreCreateMutex(); wifi_state = malloc(sizeof(WIFI_State)); memset(wifi_state, 0x00, sizeof(WIFI_State)); /* * init wifi as station */ esp_event_handler_instance_t instance_any_id; esp_event_handler_instance_t instance_got_ip; ESP_ERROR_CHECK( esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, &instance_any_id) ); ESP_ERROR_CHECK( esp_event_handler_instance_register(IP_EVENT, ESP_EVENT_ANY_ID, &got_ip_event_handler, NULL, &instance_got_ip) ); wifi_config_t wifi_config = { .sta = { .ssid = CONFIG_ESP_WIFI_SSID, .password = CONFIG_ESP_WIFI_PASSWORD, .scan_method = WIFI_FAST_SCAN, .failure_retry_cnt = 3, .sort_method = WIFI_CONNECT_AP_BY_SIGNAL, .threshold.authmode = WIFI_AUTH_WPA2_PSK, }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); EventBits_t uxBits; for(;;) { /* actions that can trigger: request a connection, a scan, or a disconnection */ uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT | TASK_WIFI_REQUEST_STA_DISCONNECT, pdFALSE, pdFALSE, portMAX_DELAY ); if (uxBits & TASK_WIFI_REQUEST_STA_DISCONNECT) { /* * user requested a disconnect, this will in effect disconnect the wifi */ ESP_LOGI(TAG, "Request STA disconnect"); ESP_ERROR_CHECK(esp_wifi_disconnect()); xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY ); /* finally: release the scan request bit */ xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT); ESP_LOGI(TAG, "Request STA disconnect is done"); } else if (uxBits & TASK_WIFI_REQUEST_STA_CONNECT) { ESP_LOGI(TAG, "Request STA connect"); xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_FAILED); xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); ESP_LOGI(TAG, "Connecting to `%s'", CONFIG_ESP_WIFI_SSID); esp_err_t wifierror = esp_wifi_connect(); if (wifierror != ESP_OK) { ESP_LOGE(TAG, "esp_wifi_connect() `%s' rc=%04x", CONFIG_ESP_WIFI_SSID, (int)wifierror); xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_FAILED); } uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED, pdFALSE, pdFALSE, 5000 / portTICK_PERIOD_MS); } } /* for(;;) */ }