diff --git a/examples/protocols/sockets/tcp_client/CMakeLists.txt b/examples/protocols/sockets/tcp_client/CMakeLists.txt index 22aa37f1c..aee70cad5 100644 --- a/examples/protocols/sockets/tcp_client/CMakeLists.txt +++ b/examples/protocols/sockets/tcp_client/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(tcp_client) diff --git a/examples/protocols/sockets/tcp_client/Makefile b/examples/protocols/sockets/tcp_client/Makefile index b390190f2..eee056b3d 100644 --- a/examples/protocols/sockets/tcp_client/Makefile +++ b/examples/protocols/sockets/tcp_client/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := tcp_client +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sockets/tcp_client/README.md b/examples/protocols/sockets/tcp_client/README.md index be9e9f2d4..415dea814 100644 --- a/examples/protocols/sockets/tcp_client/README.md +++ b/examples/protocols/sockets/tcp_client/README.md @@ -44,10 +44,6 @@ Set following parameter under Serial Flasher Options: Set following parameters under Example Configuration Options: -* Set `WiFi SSID` of the Router (Access-Point). - -* Set `WiFi Password` of the Router (Access-Point). - * Set `IP version` of example to be IPV4 or IPV6. * Set `IPV4 Address` in case your chose IP version IPV4 above. @@ -56,6 +52,8 @@ Set following parameters under Example Configuration Options: * Set `Port` number that represents remote port the example will connect to. +Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. + ## Build and Flash Build the project and flash it to the board, then run monitor tool to view serial output: diff --git a/examples/protocols/sockets/tcp_client/main/Kconfig.projbuild b/examples/protocols/sockets/tcp_client/main/Kconfig.projbuild index 9f0298f49..beabfa6f4 100644 --- a/examples/protocols/sockets/tcp_client/main/Kconfig.projbuild +++ b/examples/protocols/sockets/tcp_client/main/Kconfig.projbuild @@ -1,18 +1,5 @@ menu "Example Configuration" - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - choice EXAMPLE_IP_MODE prompt "IP Version" help diff --git a/examples/protocols/sockets/tcp_client/main/tcp_client.c b/examples/protocols/sockets/tcp_client/main/tcp_client.c index 1d2486184..96657d798 100644 --- a/examples/protocols/sockets/tcp_client/main/tcp_client.c +++ b/examples/protocols/sockets/tcp_client/main/tcp_client.c @@ -13,9 +13,11 @@ #include "freertos/event_groups.h" #include "esp_system.h" #include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_event.h" #include "esp_log.h" #include "nvs_flash.h" +#include "tcpip_adapter.h" +#include "protocol_examples_common.h" #include "lwip/err.h" #include "lwip/sockets.h" @@ -23,14 +25,6 @@ #include -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #ifdef CONFIG_EXAMPLE_IPV4 #define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR #else @@ -39,77 +33,9 @@ #define PORT CONFIG_EXAMPLE_PORT -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -const int IPV4_GOTIP_BIT = BIT0; -const int IPV6_GOTIP_BIT = BIT1; - static const char *TAG = "example"; static const char *payload = "Message from ESP32 "; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - break; - case SYSTEM_EVENT_STA_CONNECTED: - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP6"); - - char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip); - ESP_LOGI(TAG, "IPv6: %s", ip6); - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -static void wait_for_ip() -{ - uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT ; - - ESP_LOGI(TAG, "Waiting for AP connection..."); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); -} - static void tcp_client_task(void *pvParameters) { char rx_buffer[128]; @@ -120,21 +46,21 @@ static void tcp_client_task(void *pvParameters) while (1) { #ifdef CONFIG_EXAMPLE_IPV4 - struct sockaddr_in destAddr; - destAddr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR); - destAddr.sin_family = AF_INET; - destAddr.sin_port = htons(PORT); + struct sockaddr_in dest_addr; + dest_addr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(PORT); addr_family = AF_INET; ip_protocol = IPPROTO_IP; - inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); + inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1); #else // IPV6 - struct sockaddr_in6 destAddr; - inet6_aton(HOST_IP_ADDR, &destAddr.sin6_addr); - destAddr.sin6_family = AF_INET6; - destAddr.sin6_port = htons(PORT); + struct sockaddr_in6 dest_addr; + inet6_aton(HOST_IP_ADDR, &dest_addr.sin6_addr); + dest_addr.sin6_family = AF_INET6; + dest_addr.sin6_port = htons(PORT); addr_family = AF_INET6; ip_protocol = IPPROTO_IPV6; - inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); + inet6_ntoa_r(dest_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); #endif int sock = socket(addr_family, SOCK_STREAM, ip_protocol); @@ -142,9 +68,9 @@ static void tcp_client_task(void *pvParameters) ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); break; } - ESP_LOGI(TAG, "Socket created"); + ESP_LOGI(TAG, "Socket created, connecting to %s:%d", HOST_IP_ADDR, PORT); - int err = connect(sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); + int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (err != 0) { ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno); break; @@ -154,12 +80,12 @@ static void tcp_client_task(void *pvParameters) while (1) { int err = send(sock, payload, strlen(payload), 0); if (err < 0) { - ESP_LOGE(TAG, "Error occured during sending: errno %d", errno); + ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno); break; } int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0); - // Error occured during receiving + // Error occurred during receiving if (len < 0) { ESP_LOGE(TAG, "recv failed: errno %d", errno); break; @@ -185,9 +111,15 @@ static void tcp_client_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); - wait_for_ip(); + ESP_ERROR_CHECK(nvs_flash_init()); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); xTaskCreate(tcp_client_task, "tcp_client", 4096, NULL, 5, NULL); } diff --git a/examples/protocols/sockets/tcp_server/CMakeLists.txt b/examples/protocols/sockets/tcp_server/CMakeLists.txt index 3514e60fc..9865464bd 100644 --- a/examples/protocols/sockets/tcp_server/CMakeLists.txt +++ b/examples/protocols/sockets/tcp_server/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(tcp_server) diff --git a/examples/protocols/sockets/tcp_server/Makefile b/examples/protocols/sockets/tcp_server/Makefile index e965b9093..ccdc6d541 100644 --- a/examples/protocols/sockets/tcp_server/Makefile +++ b/examples/protocols/sockets/tcp_server/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := tcp_server +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sockets/tcp_server/README.md b/examples/protocols/sockets/tcp_server/README.md index f43dc0791..ce47646c9 100644 --- a/examples/protocols/sockets/tcp_server/README.md +++ b/examples/protocols/sockets/tcp_server/README.md @@ -46,14 +46,12 @@ Set following parameter under Serial Flasher Options: Set following parameters under Example Configuration Options: -* Set `WiFi SSID` of the Router (Access-Point). - -* Set `WiFi Password` of the Router (Access-Point). - * Set `IP version` of the example to be IPV4 or IPV6. * Set `Port` number of the socket, that server example will create. +Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. + ## Build and Flash Build the project and flash it to the board, then run monitor tool to view serial output: diff --git a/examples/protocols/sockets/tcp_server/main/Kconfig.projbuild b/examples/protocols/sockets/tcp_server/main/Kconfig.projbuild index 45a00225c..822c019be 100644 --- a/examples/protocols/sockets/tcp_server/main/Kconfig.projbuild +++ b/examples/protocols/sockets/tcp_server/main/Kconfig.projbuild @@ -1,18 +1,5 @@ menu "Example Configuration" - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - choice EXAMPLE_IP_MODE prompt "IP Version" help @@ -23,6 +10,7 @@ menu "Example Configuration" config EXAMPLE_IPV6 bool "IPV6" + select EXAMPLE_CONNECT_IPV6 endchoice diff --git a/examples/protocols/sockets/tcp_server/main/tcp_server.c b/examples/protocols/sockets/tcp_server/main/tcp_server.c index 4f2c07d32..1e71096dc 100644 --- a/examples/protocols/sockets/tcp_server/main/tcp_server.c +++ b/examples/protocols/sockets/tcp_server/main/tcp_server.c @@ -10,12 +10,13 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" #include "esp_system.h" #include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_event.h" #include "esp_log.h" #include "nvs_flash.h" +#include "tcpip_adapter.h" +#include "protocol_examples_common.h" #include "lwip/err.h" #include "lwip/sockets.h" @@ -23,85 +24,10 @@ #include -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #define PORT CONFIG_EXAMPLE_PORT -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -const int IPV4_GOTIP_BIT = BIT0; -const int IPV6_GOTIP_BIT = BIT1; - static const char *TAG = "example"; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - break; - case SYSTEM_EVENT_STA_CONNECTED: - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP6"); - - char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip); - ESP_LOGI(TAG, "IPv6: %s", ip6); - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -static void wait_for_ip() -{ - uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT ; - - ESP_LOGI(TAG, "Waiting for AP connection..."); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); -} static void tcp_server_task(void *pvParameters) { @@ -113,21 +39,21 @@ static void tcp_server_task(void *pvParameters) while (1) { #ifdef CONFIG_EXAMPLE_IPV4 - struct sockaddr_in destAddr; - destAddr.sin_addr.s_addr = htonl(INADDR_ANY); - destAddr.sin_family = AF_INET; - destAddr.sin_port = htons(PORT); + struct sockaddr_in dest_addr; + dest_addr.sin_addr.s_addr = htonl(INADDR_ANY); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(PORT); addr_family = AF_INET; ip_protocol = IPPROTO_IP; - inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); + inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1); #else // IPV6 - struct sockaddr_in6 destAddr; - bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un)); - destAddr.sin6_family = AF_INET6; - destAddr.sin6_port = htons(PORT); + struct sockaddr_in6 dest_addr; + bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un)); + dest_addr.sin6_family = AF_INET6; + dest_addr.sin6_port = htons(PORT); addr_family = AF_INET6; ip_protocol = IPPROTO_IPV6; - inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); + inet6_ntoa_r(dest_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); #endif int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol); @@ -137,23 +63,23 @@ static void tcp_server_task(void *pvParameters) } ESP_LOGI(TAG, "Socket created"); - int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); + int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (err != 0) { ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); break; } - ESP_LOGI(TAG, "Socket binded"); + ESP_LOGI(TAG, "Socket bound, port %d", PORT); err = listen(listen_sock, 1); if (err != 0) { - ESP_LOGE(TAG, "Error occured during listen: errno %d", errno); + ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno); break; } ESP_LOGI(TAG, "Socket listening"); - struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6 - uint addrLen = sizeof(sourceAddr); - int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); + struct sockaddr_in6 source_addr; // Large enough for both IPv4 or IPv6 + uint addr_len = sizeof(source_addr); + int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len); if (sock < 0) { ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno); break; @@ -162,7 +88,7 @@ static void tcp_server_task(void *pvParameters) while (1) { int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0); - // Error occured during receiving + // Error occurred during receiving if (len < 0) { ESP_LOGE(TAG, "recv failed: errno %d", errno); break; @@ -175,10 +101,10 @@ static void tcp_server_task(void *pvParameters) // Data received else { // Get the sender's ip address as string - if (sourceAddr.sin6_family == PF_INET) { - inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); - } else if (sourceAddr.sin6_family == PF_INET6) { - inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); + if (source_addr.sin6_family == PF_INET) { + inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + } else if (source_addr.sin6_family == PF_INET6) { + inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); } rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string @@ -187,7 +113,7 @@ static void tcp_server_task(void *pvParameters) int err = send(sock, rx_buffer, len, 0); if (err < 0) { - ESP_LOGE(TAG, "Error occured during sending: errno %d", errno); + ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno); break; } } @@ -204,9 +130,15 @@ static void tcp_server_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); - wait_for_ip(); + ESP_ERROR_CHECK(nvs_flash_init()); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL); } diff --git a/examples/protocols/sockets/udp_client/CMakeLists.txt b/examples/protocols/sockets/udp_client/CMakeLists.txt index ee1d3f532..2049b8193 100644 --- a/examples/protocols/sockets/udp_client/CMakeLists.txt +++ b/examples/protocols/sockets/udp_client/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(udp_client) diff --git a/examples/protocols/sockets/udp_client/Makefile b/examples/protocols/sockets/udp_client/Makefile index 34849eee2..604aa5af3 100644 --- a/examples/protocols/sockets/udp_client/Makefile +++ b/examples/protocols/sockets/udp_client/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := udp_client +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sockets/udp_client/README.md b/examples/protocols/sockets/udp_client/README.md index 80994e2c0..7232fb9f4 100644 --- a/examples/protocols/sockets/udp_client/README.md +++ b/examples/protocols/sockets/udp_client/README.md @@ -54,10 +54,6 @@ Set following parameter under Serial Flasher Options: Set following parameters under Example Configuration Options: -* Set `WiFi SSID` of the Router (Access-Point). - -* Set `WiFi Password` of the Router (Access-Point). - * Set `IP version` of example to be IPV4 or IPV6. * Set `IPV4 Address` in case your chose IP version IPV4 above. @@ -66,6 +62,9 @@ Set following parameters under Example Configuration Options: * Set `Port` number that represents remote port the example will send data and receive data from. +Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. + + ## Build and Flash Build the project and flash it to the board, then run monitor tool to view serial output: diff --git a/examples/protocols/sockets/udp_client/main/Kconfig.projbuild b/examples/protocols/sockets/udp_client/main/Kconfig.projbuild index e06465e0d..d9b77d185 100644 --- a/examples/protocols/sockets/udp_client/main/Kconfig.projbuild +++ b/examples/protocols/sockets/udp_client/main/Kconfig.projbuild @@ -1,18 +1,5 @@ menu "Example Configuration" - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - choice EXAMPLE_IP_MODE prompt "IP Version" help @@ -23,6 +10,7 @@ menu "Example Configuration" config EXAMPLE_IPV6 bool "IPV6" + select EXAMPLE_CONNECT_IPV6 endchoice diff --git a/examples/protocols/sockets/udp_client/main/udp_client.c b/examples/protocols/sockets/udp_client/main/udp_client.c index 39a1d3a91..6639082a1 100644 --- a/examples/protocols/sockets/udp_client/main/udp_client.c +++ b/examples/protocols/sockets/udp_client/main/udp_client.c @@ -13,9 +13,11 @@ #include "freertos/event_groups.h" #include "esp_system.h" #include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_event.h" #include "esp_log.h" #include "nvs_flash.h" +#include "tcpip_adapter.h" +#include "protocol_examples_common.h" #include "lwip/err.h" #include "lwip/sockets.h" @@ -23,14 +25,6 @@ #include -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #ifdef CONFIG_EXAMPLE_IPV4 #define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR #else @@ -39,76 +33,9 @@ #define PORT CONFIG_EXAMPLE_PORT -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -const int IPV4_GOTIP_BIT = BIT0; -const int IPV6_GOTIP_BIT = BIT1; - static const char *TAG = "example"; static const char *payload = "Message from ESP32 "; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - break; - case SYSTEM_EVENT_STA_CONNECTED: - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP6"); - - char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip); - ESP_LOGI(TAG, "IPv6: %s", ip6); - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -static void wait_for_ip() -{ - uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT ; - - ESP_LOGI(TAG, "Waiting for AP connection..."); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); -} static void udp_client_task(void *pvParameters) { @@ -120,21 +47,21 @@ static void udp_client_task(void *pvParameters) while (1) { #ifdef CONFIG_EXAMPLE_IPV4 - struct sockaddr_in destAddr; - destAddr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR); - destAddr.sin_family = AF_INET; - destAddr.sin_port = htons(PORT); + struct sockaddr_in dest_addr; + dest_addr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(PORT); addr_family = AF_INET; ip_protocol = IPPROTO_IP; - inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); + inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1); #else // IPV6 - struct sockaddr_in6 destAddr; - inet6_aton(HOST_IP_ADDR, &destAddr.sin6_addr); - destAddr.sin6_family = AF_INET6; - destAddr.sin6_port = htons(PORT); + struct sockaddr_in6 dest_addr; + inet6_aton(HOST_IP_ADDR, &dest_addr.sin6_addr); + dest_addr.sin6_family = AF_INET6; + dest_addr.sin6_port = htons(PORT); addr_family = AF_INET6; ip_protocol = IPPROTO_IPV6; - inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); + inet6_ntoa_r(dest_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); #endif int sock = socket(addr_family, SOCK_DGRAM, ip_protocol); @@ -142,22 +69,22 @@ static void udp_client_task(void *pvParameters) ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); break; } - ESP_LOGI(TAG, "Socket created"); + ESP_LOGI(TAG, "Socket created, sending to %s:%d", HOST_IP_ADDR, PORT); while (1) { - int err = sendto(sock, payload, strlen(payload), 0, (struct sockaddr *)&destAddr, sizeof(destAddr)); + int err = sendto(sock, payload, strlen(payload), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (err < 0) { - ESP_LOGE(TAG, "Error occured during sending: errno %d", errno); + ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno); break; } ESP_LOGI(TAG, "Message sent"); - struct sockaddr_in sourceAddr; // Large enough for both IPv4 or IPv6 - socklen_t socklen = sizeof(sourceAddr); - int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&sourceAddr, &socklen); + struct sockaddr_in source_addr; // Large enough for both IPv4 or IPv6 + socklen_t socklen = sizeof(source_addr); + int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&source_addr, &socklen); - // Error occured during receiving + // Error occurred during receiving if (len < 0) { ESP_LOGE(TAG, "recvfrom failed: errno %d", errno); break; @@ -183,9 +110,15 @@ static void udp_client_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); - wait_for_ip(); + ESP_ERROR_CHECK(nvs_flash_init()); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); xTaskCreate(udp_client_task, "udp_client", 4096, NULL, 5, NULL); } diff --git a/examples/protocols/sockets/udp_multicast/CMakeLists.txt b/examples/protocols/sockets/udp_multicast/CMakeLists.txt index fe4b8fe8e..f89b3347a 100644 --- a/examples/protocols/sockets/udp_multicast/CMakeLists.txt +++ b/examples/protocols/sockets/udp_multicast/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(udp-multicast) diff --git a/examples/protocols/sockets/udp_multicast/Makefile b/examples/protocols/sockets/udp_multicast/Makefile index 60f3d59db..47e26b953 100644 --- a/examples/protocols/sockets/udp_multicast/Makefile +++ b/examples/protocols/sockets/udp_multicast/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := udp-multicast +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sockets/udp_multicast/README.md b/examples/protocols/sockets/udp_multicast/README.md index 8a937afc1..7bc066db0 100644 --- a/examples/protocols/sockets/udp_multicast/README.md +++ b/examples/protocols/sockets/udp_multicast/README.md @@ -12,9 +12,12 @@ The behaviour of the example is: ## Configuration -The "Example Configuration" menu "make menuconfig" allows you to configure the details of the example: +Run `make menuconfig` (or `idf.py menuconfig` if using CMake build system). + +Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. + +The "Example Configuration" menu allows you to configure the details of the example: -* WiFi SSD & Password * IP Mode: IPV4 & IPV6 dual, IPV4 only, or IPv6 only. * Multicast addresses for IPV4 and/or IPV6. * Enable multicast socket loopback (ie should the socket receive its own multicast transmissions.) diff --git a/examples/protocols/sockets/udp_multicast/main/Kconfig.projbuild b/examples/protocols/sockets/udp_multicast/main/Kconfig.projbuild index 7be240281..99e01387b 100644 --- a/examples/protocols/sockets/udp_multicast/main/Kconfig.projbuild +++ b/examples/protocols/sockets/udp_multicast/main/Kconfig.projbuild @@ -1,19 +1,5 @@ menu "Example Configuration" - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - choice EXAMPLE_IP_MODE prompt "Multicast IP type" help @@ -38,6 +24,7 @@ menu "Example Configuration" bool config EXAMPLE_IPV6 bool + select EXAMPLE_CONNECT_IPV6 config EXAMPLE_MULTICAST_IPV4_ADDR string "Multicast IPV4 Address (send & receive)" @@ -53,8 +40,9 @@ menu "Example Configuration" help IPV6 multicast address. Example will both send to and listen to this address. - The default FF02::FC address is a link-local multicast address. Consult IPV6 specifications or - documentation for information about meaning of different IPV6 multicast ranges. + The default FF02::FC address is a link-local multicast address. + Consult IPV6 specifications or documentation for information about + meaning of different IPV6 multicast ranges. config EXAMPLE_PORT int "Multicast port (send & receive)" @@ -78,15 +66,16 @@ menu "Example Configuration" choice EXAMPLE_MULTICAST_IF prompt "Multicast Interface" + default EXAMPLE_MULTICAST_LISTEN_DEFAULT_IF help Multicast socket can bind to default interface, or all interfaces. + config EXAMPLE_MULTICAST_LISTEN_ALL_IF + bool "All interfaces" + config EXAMPLE_MULTICAST_LISTEN_DEFAULT_IF bool "Default interface" - config EXAMPLE_MULTICAST_LISTEN_STA_IF - bool "WiFi STA interface" - endchoice endmenu diff --git a/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c b/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c index a21c24a60..e3bb74284 100644 --- a/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c +++ b/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c @@ -13,24 +13,23 @@ #include "freertos/event_groups.h" #include "esp_system.h" #include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_event.h" #include "esp_log.h" #include "nvs_flash.h" +#include "tcpip_adapter.h" +#include "protocol_examples_common.h" #include "lwip/err.h" #include "lwip/sockets.h" #include "lwip/sys.h" #include -/* The examples use simple WiFi configuration that you can set via +/* The examples use simple configuration that you can set via 'make menuconfig'. If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" + the config you want - ie #define UDP_PORT 3333 */ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #define UDP_PORT CONFIG_EXAMPLE_PORT #define MULTICAST_LOOPBACK CONFIG_EXAMPLE_LOOPBACK @@ -40,16 +39,7 @@ #define MULTICAST_IPV4_ADDR CONFIG_EXAMPLE_MULTICAST_IPV4_ADDR #define MULTICAST_IPV6_ADDR CONFIG_EXAMPLE_MULTICAST_IPV6_ADDR -#define LISTEN_DEFAULT_IF CONFIG_EXAMPLE_LISTEN_DEFAULT_IF - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - we use two - one for IPv4 "got ip", and - one for IPv6 "got ip". */ -const int IPV4_GOTIP_BIT = BIT0; -const int IPV6_GOTIP_BIT = BIT1; +#define LISTEN_ALL_IF EXAMPLE_MULTICAST_LISTEN_ALL_IF static const char *TAG = "multicast"; #ifdef CONFIG_EXAMPLE_IPV4 @@ -59,53 +49,6 @@ static const char *V4TAG = "mcast-ipv4"; static const char *V6TAG = "mcast-ipv6"; #endif -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_CONNECTED: - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} #ifdef CONFIG_EXAMPLE_IPV4 /* Add a socket, either IPV4-only or IPV6 dual mode, to the IPV4 @@ -116,17 +59,17 @@ static int socket_add_ipv4_multicast_group(int sock, bool assign_source_if) struct in_addr iaddr = { 0 }; int err = 0; // Configure source interface -#if USE_DEFAULT_IF +#if LISTEN_ALL_IF imreq.imr_interface.s_addr = IPADDR_ANY; #else tcpip_adapter_ip_info_t ip_info = { 0 }; - err = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info); + err = tcpip_adapter_get_ip_info(EXAMPLE_INTERFACE, &ip_info); if (err != ESP_OK) { ESP_LOGE(V4TAG, "Failed to get IP address info. Error 0x%x", err); goto err; } inet_addr_from_ip4addr(&iaddr, &ip_info.ip); -#endif +#endif // LISTEN_ALL_IF // Configure multicast address to listen to err = inet_aton(MULTICAST_IPV4_ADDR, &imreq.imr_multiaddr.s_addr); if (err != 1) { @@ -248,7 +191,7 @@ static int create_multicast_ipv6_socket() } // Selct the interface to use as multicast source for this socket. -#if USE_DEFAULT_IF +#if LISTEN_ALL_IF bzero(&if_inaddr.un, sizeof(if_inaddr.un)); #else // Read interface adapter link-local address and use it @@ -257,13 +200,13 @@ static int create_multicast_ipv6_socket() // (Note the interface may have other non-LL IPV6 addresses as well, // but it doesn't matter in this context as the address is only // used to identify the interface.) - err = tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_STA, &if_ipaddr); + err = tcpip_adapter_get_ip6_linklocal(EXAMPLE_INTERFACE, &if_ipaddr); inet6_addr_from_ip6addr(&if_inaddr, &if_ipaddr); if (err != ESP_OK) { ESP_LOGE(V6TAG, "Failed to get IPV6 LL address. Error 0x%x", err); goto err; } -#endif +#endif // LISTEN_ALL_IF // Assign the multicast source interface, via its IP err = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_inaddr, @@ -297,11 +240,11 @@ static int create_multicast_ipv6_socket() // group for listening... // Configure source interface -#if USE_DEFAULT_IF +#if LISTEN_ALL_IF v6imreq.imr_interface.s_addr = IPADDR_ANY; #else inet6_addr_from_ip6addr(&v6imreq.ipv6mr_interface, &if_ipaddr); -#endif +#endif // LISTEN_ALL_IF #ifdef CONFIG_EXAMPLE_IPV6 // Configure multicast address to listen to err = inet6_aton(MULTICAST_IPV6_ADDR, &v6imreq.ipv6mr_multiaddr); @@ -356,19 +299,6 @@ err: static void mcast_example_task(void *pvParameters) { while (1) { - /* Wait for all the IPs we care about to be set - */ - uint32_t bits = 0; -#ifdef CONFIG_EXAMPLE_IPV4 - bits |= IPV4_GOTIP_BIT; -#endif -#ifdef CONFIG_EXAMPLE_IPV6 - bits |= IPV6_GOTIP_BIT; -#endif - ESP_LOGI(TAG, "Waiting for AP connection..."); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); - int sock; #ifdef CONFIG_EXAMPLE_IPV4_ONLY @@ -547,7 +477,15 @@ static void mcast_example_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); + ESP_ERROR_CHECK(nvs_flash_init()); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + xTaskCreate(&mcast_example_task, "mcast_task", 4096, NULL, 5, NULL); } diff --git a/examples/protocols/sockets/udp_server/CMakeLists.txt b/examples/protocols/sockets/udp_server/CMakeLists.txt index d1edab0fc..861431809 100644 --- a/examples/protocols/sockets/udp_server/CMakeLists.txt +++ b/examples/protocols/sockets/udp_server/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(udp_server) diff --git a/examples/protocols/sockets/udp_server/Makefile b/examples/protocols/sockets/udp_server/Makefile index 36552c9bf..bc11a4303 100644 --- a/examples/protocols/sockets/udp_server/Makefile +++ b/examples/protocols/sockets/udp_server/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := udp_server +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sockets/udp_server/README.md b/examples/protocols/sockets/udp_server/README.md index 8fe64a73e..3bf1fe370 100644 --- a/examples/protocols/sockets/udp_server/README.md +++ b/examples/protocols/sockets/udp_server/README.md @@ -56,14 +56,12 @@ Set following parameter under Serial Flasher Options: Set following parameters under Example Configuration Options: -* Set `WiFi SSID` of the Router (Access-Point). - -* Set `WiFi Password` of the Router (Access-Point). - * Set `IP version` of the example to be IPV4 or IPV6. * Set `Port` number that represents remote port the example will create. +Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. + ## Build and Flash Build the project and flash it to the board, then run monitor tool to view serial output: diff --git a/examples/protocols/sockets/udp_server/main/Kconfig.projbuild b/examples/protocols/sockets/udp_server/main/Kconfig.projbuild index 45a00225c..822c019be 100644 --- a/examples/protocols/sockets/udp_server/main/Kconfig.projbuild +++ b/examples/protocols/sockets/udp_server/main/Kconfig.projbuild @@ -1,18 +1,5 @@ menu "Example Configuration" - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - choice EXAMPLE_IP_MODE prompt "IP Version" help @@ -23,6 +10,7 @@ menu "Example Configuration" config EXAMPLE_IPV6 bool "IPV6" + select EXAMPLE_CONNECT_IPV6 endchoice diff --git a/examples/protocols/sockets/udp_server/main/udp_server.c b/examples/protocols/sockets/udp_server/main/udp_server.c index 336388f70..ce8216832 100644 --- a/examples/protocols/sockets/udp_server/main/udp_server.c +++ b/examples/protocols/sockets/udp_server/main/udp_server.c @@ -10,99 +10,23 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" #include "esp_system.h" #include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_event.h" #include "esp_log.h" #include "nvs_flash.h" +#include "tcpip_adapter.h" +#include "protocol_examples_common.h" #include "lwip/err.h" #include "lwip/sockets.h" #include "lwip/sys.h" #include - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #define PORT CONFIG_EXAMPLE_PORT -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -const int IPV4_GOTIP_BIT = BIT0; -const int IPV6_GOTIP_BIT = BIT1; - static const char *TAG = "example"; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - break; - case SYSTEM_EVENT_STA_CONNECTED: - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP6"); - - char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip); - ESP_LOGI(TAG, "IPv6: %s", ip6); - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -static void wait_for_ip() -{ - uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT ; - - ESP_LOGI(TAG, "Waiting for AP connection..."); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); -} - static void udp_server_task(void *pvParameters) { char rx_buffer[128]; @@ -113,21 +37,21 @@ static void udp_server_task(void *pvParameters) while (1) { #ifdef CONFIG_EXAMPLE_IPV4 - struct sockaddr_in destAddr; - destAddr.sin_addr.s_addr = htonl(INADDR_ANY); - destAddr.sin_family = AF_INET; - destAddr.sin_port = htons(PORT); + struct sockaddr_in dest_addr; + dest_addr.sin_addr.s_addr = htonl(INADDR_ANY); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(PORT); addr_family = AF_INET; ip_protocol = IPPROTO_IP; - inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); + inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1); #else // IPV6 - struct sockaddr_in6 destAddr; - bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un)); - destAddr.sin6_family = AF_INET6; - destAddr.sin6_port = htons(PORT); + struct sockaddr_in6 dest_addr; + bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un)); + dest_addr.sin6_family = AF_INET6; + dest_addr.sin6_port = htons(PORT); addr_family = AF_INET6; ip_protocol = IPPROTO_IPV6; - inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); + inet6_ntoa_r(dest_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); #endif int sock = socket(addr_family, SOCK_DGRAM, ip_protocol); @@ -137,20 +61,20 @@ static void udp_server_task(void *pvParameters) } ESP_LOGI(TAG, "Socket created"); - int err = bind(sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); + int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (err < 0) { ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); } - ESP_LOGI(TAG, "Socket binded"); + ESP_LOGI(TAG, "Socket bound, port %d", PORT); while (1) { ESP_LOGI(TAG, "Waiting for data"); - struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6 - socklen_t socklen = sizeof(sourceAddr); - int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&sourceAddr, &socklen); + struct sockaddr_in6 source_addr; // Large enough for both IPv4 or IPv6 + socklen_t socklen = sizeof(source_addr); + int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&source_addr, &socklen); - // Error occured during receiving + // Error occurred during receiving if (len < 0) { ESP_LOGE(TAG, "recvfrom failed: errno %d", errno); break; @@ -158,19 +82,19 @@ static void udp_server_task(void *pvParameters) // Data received else { // Get the sender's ip address as string - if (sourceAddr.sin6_family == PF_INET) { - inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); - } else if (sourceAddr.sin6_family == PF_INET6) { - inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); + if (source_addr.sin6_family == PF_INET) { + inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + } else if (source_addr.sin6_family == PF_INET6) { + inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); } rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string... ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str); ESP_LOGI(TAG, "%s", rx_buffer); - int err = sendto(sock, rx_buffer, len, 0, (struct sockaddr *)&sourceAddr, sizeof(sourceAddr)); + int err = sendto(sock, rx_buffer, len, 0, (struct sockaddr *)&source_addr, sizeof(source_addr)); if (err < 0) { - ESP_LOGE(TAG, "Error occured during sending: errno %d", errno); + ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno); break; } } @@ -187,9 +111,15 @@ static void udp_server_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); - wait_for_ip(); + ESP_ERROR_CHECK(nvs_flash_init()); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); xTaskCreate(udp_server_task, "udp_server", 4096, NULL, 5, NULL); }