mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
common_components: add wifi connect console commands
This commit is contained in:
parent
c0312e3242
commit
bf0e4943be
@ -1,4 +1,25 @@
|
|||||||
idf_component_register(SRCS "connect.c" "stdin_out.c" "addr_from_stdin.c"
|
set(srcs "stdin_out.c"
|
||||||
INCLUDE_DIRS "include"
|
"addr_from_stdin.c"
|
||||||
PRIV_REQUIRES esp_netif driver esp_eth
|
"connect.c"
|
||||||
)
|
"wifi_connect.c")
|
||||||
|
|
||||||
|
if(CONFIG_EXAMPLE_PROVIDE_WIFI_CONSOLE_CMD)
|
||||||
|
list(APPEND srcs "console_cmd.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_EXAMPLE_CONNECT_ETHERNET)
|
||||||
|
list(APPEND srcs "eth_connect.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
idf_component_register(SRCS "${srcs}"
|
||||||
|
INCLUDE_DIRS "include"
|
||||||
|
PRIV_REQUIRES esp_netif driver)
|
||||||
|
|
||||||
|
if(CONFIG_EXAMPLE_PROVIDE_WIFI_CONSOLE_CMD)
|
||||||
|
idf_component_optional_requires(PRIVATE console)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_EXAMPLE_CONNECT_ETHERNET)
|
||||||
|
idf_component_optional_requires(PRIVATE esp_eth)
|
||||||
|
endif()
|
||||||
|
@ -10,13 +10,29 @@ menu "Example Connection Configuration"
|
|||||||
Choose this option to connect with WiFi
|
Choose this option to connect with WiFi
|
||||||
|
|
||||||
if EXAMPLE_CONNECT_WIFI
|
if EXAMPLE_CONNECT_WIFI
|
||||||
|
config EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
|
||||||
|
bool "Get ssid and password from stdin"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Give the WiFi SSID and password from stdin.
|
||||||
|
|
||||||
|
config EXAMPLE_PROVIDE_WIFI_CONSOLE_CMD
|
||||||
|
depends on !EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
|
||||||
|
bool "Provide wifi connect commands"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Provide wifi connect commands for esp_console.
|
||||||
|
Please use `register_wifi_connect_commands` to register them.
|
||||||
|
|
||||||
config EXAMPLE_WIFI_SSID
|
config EXAMPLE_WIFI_SSID
|
||||||
|
depends on !EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
|
||||||
string "WiFi SSID"
|
string "WiFi SSID"
|
||||||
default "myssid"
|
default "myssid"
|
||||||
help
|
help
|
||||||
SSID (network name) for the example to connect to.
|
SSID (network name) for the example to connect to.
|
||||||
|
|
||||||
config EXAMPLE_WIFI_PASSWORD
|
config EXAMPLE_WIFI_PASSWORD
|
||||||
|
depends on !EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
|
||||||
string "WiFi Password"
|
string "WiFi Password"
|
||||||
default "mypassword"
|
default "mypassword"
|
||||||
help
|
help
|
||||||
@ -282,9 +298,9 @@ menu "Example Connection Configuration"
|
|||||||
endif # EXAMPLE_CONNECT_ETHERNET
|
endif # EXAMPLE_CONNECT_ETHERNET
|
||||||
|
|
||||||
config EXAMPLE_CONNECT_IPV6
|
config EXAMPLE_CONNECT_IPV6
|
||||||
|
depends on (EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET)
|
||||||
bool "Obtain IPv6 address"
|
bool "Obtain IPv6 address"
|
||||||
default y
|
default y
|
||||||
depends on EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET
|
|
||||||
select LWIP_IPV6
|
select LWIP_IPV6
|
||||||
help
|
help
|
||||||
By default, examples will wait until IPv4 and IPv6 local link addresses are obtained.
|
By default, examples will wait until IPv4 and IPv6 local link addresses are obtained.
|
||||||
|
@ -50,7 +50,7 @@ esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *ad
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
#if CONFIG_LWIP_IPV6
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
else if (cur->ai_family == AF_INET6) {
|
else if (cur->ai_family == AF_INET6) {
|
||||||
*ip_protocol = IPPROTO_IPV6;
|
*ip_protocol = IPPROTO_IPV6;
|
||||||
*addr_family = AF_INET6;
|
*addr_family = AF_INET6;
|
||||||
|
@ -1,94 +1,29 @@
|
|||||||
/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection.
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "protocol_examples_common.h"
|
#include "protocol_examples_common.h"
|
||||||
|
#include "example_common_private.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
#include "esp_wifi_default.h"
|
#include "esp_wifi_default.h"
|
||||||
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
||||||
#include "esp_eth.h"
|
|
||||||
#if CONFIG_ETH_USE_SPI_ETHERNET
|
|
||||||
#include "driver/spi_master.h"
|
|
||||||
#endif // CONFIG_ETH_USE_SPI_ETHERNET
|
|
||||||
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/event_groups.h"
|
#include "freertos/event_groups.h"
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
static const char *TAG = "example_common";
|
||||||
#define MAX_IP6_ADDRS_PER_NETIF (5)
|
|
||||||
#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces*2)
|
|
||||||
|
|
||||||
#if defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK)
|
|
||||||
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_LINK_LOCAL
|
|
||||||
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_GLOBAL)
|
|
||||||
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_GLOBAL
|
|
||||||
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL)
|
|
||||||
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_SITE_LOCAL
|
|
||||||
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL)
|
|
||||||
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_UNIQUE_LOCAL
|
|
||||||
#endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_...
|
|
||||||
|
|
||||||
#else
|
|
||||||
#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define EXAMPLE_DO_CONNECT CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_WIFI_SCAN_METHOD_FAST
|
|
||||||
#define EXAMPLE_WIFI_SCAN_METHOD WIFI_FAST_SCAN
|
|
||||||
#elif CONFIG_EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL
|
|
||||||
#define EXAMPLE_WIFI_SCAN_METHOD WIFI_ALL_CHANNEL_SCAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL
|
|
||||||
#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL
|
|
||||||
#elif CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SECURITY
|
|
||||||
#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SECURITY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_WIFI_AUTH_OPEN
|
|
||||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
|
|
||||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WEP
|
|
||||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
|
|
||||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_PSK
|
|
||||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
|
|
||||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_PSK
|
|
||||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
|
|
||||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_WPA2_PSK
|
|
||||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
|
|
||||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_ENTERPRISE
|
|
||||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_ENTERPRISE
|
|
||||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA3_PSK
|
|
||||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
|
|
||||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_WPA3_PSK
|
|
||||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
|
|
||||||
#elif CONFIG_EXAMPLE_WIFI_AUTH_WAPI_PSK
|
|
||||||
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int s_active_interfaces = 0;
|
|
||||||
static SemaphoreHandle_t s_semph_get_ip_addrs;
|
|
||||||
static esp_netif_t *s_example_esp_netif = NULL;
|
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
static esp_ip6_addr_t s_ipv6_addr;
|
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
/* types of ipv6 addresses to be displayed on ipv6 events */
|
/* types of ipv6 addresses to be displayed on ipv6 events */
|
||||||
static const char *s_ipv6_addr_types[] = {
|
const char *example_ipv6_addr_types_to_str[6] = {
|
||||||
"ESP_IP6_ADDR_IS_UNKNOWN",
|
"ESP_IP6_ADDR_IS_UNKNOWN",
|
||||||
"ESP_IP6_ADDR_IS_GLOBAL",
|
"ESP_IP6_ADDR_IS_GLOBAL",
|
||||||
"ESP_IP6_ADDR_IS_LINK_LOCAL",
|
"ESP_IP6_ADDR_IS_LINK_LOCAL",
|
||||||
@ -98,406 +33,84 @@ static const char *s_ipv6_addr_types[] = {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char *TAG = "example_connect";
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
|
||||||
static esp_netif_t *wifi_start(void);
|
|
||||||
static void wifi_stop(void);
|
|
||||||
#endif
|
|
||||||
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
||||||
static esp_netif_t *eth_start(void);
|
|
||||||
static void eth_stop(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks the netif description if it contains specified prefix.
|
* @brief Checks the netif description if it contains specified prefix.
|
||||||
* All netifs created withing common connect component are prefixed with the module TAG,
|
* All netifs created withing common connect component are prefixed with the module TAG,
|
||||||
* so it returns true if the specified netif is owned by this module
|
* so it returns true if the specified netif is owned by this module
|
||||||
*/
|
*/
|
||||||
static bool is_our_netif(const char *prefix, esp_netif_t *netif)
|
bool example_is_our_netif(const char *prefix, esp_netif_t *netif)
|
||||||
{
|
{
|
||||||
return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0;
|
return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set up connection, Wi-Fi and/or Ethernet */
|
|
||||||
static void start(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
|
||||||
s_example_esp_netif = wifi_start();
|
|
||||||
s_active_interfaces++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
||||||
s_example_esp_netif = eth_start();
|
|
||||||
s_active_interfaces++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_CONNECT_WIFI && CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
||||||
/* if both intefaces at once, clear out to indicate that multiple netifs are active */
|
|
||||||
s_example_esp_netif = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if EXAMPLE_DO_CONNECT
|
|
||||||
/* create semaphore if at least one interface is active */
|
|
||||||
s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tear down connection, release resources */
|
|
||||||
static void stop(void)
|
|
||||||
{
|
|
||||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
|
||||||
wifi_stop();
|
|
||||||
s_active_interfaces--;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
||||||
eth_stop();
|
|
||||||
s_active_interfaces--;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if EXAMPLE_DO_CONNECT
|
|
||||||
static esp_ip4_addr_t s_ip_addr;
|
|
||||||
|
|
||||||
static void on_got_ip(void *arg, esp_event_base_t event_base,
|
|
||||||
int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
|
||||||
if (!is_our_netif(TAG, event->esp_netif)) {
|
|
||||||
ESP_LOGW(TAG, "Got IPv4 from another interface \"%s\": ignored", esp_netif_get_desc(event->esp_netif));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
|
|
||||||
memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr));
|
|
||||||
xSemaphoreGive(s_semph_get_ip_addrs);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
|
|
||||||
static void on_got_ipv6(void *arg, esp_event_base_t event_base,
|
|
||||||
int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
|
||||||
if (!is_our_netif(TAG, event->esp_netif)) {
|
|
||||||
ESP_LOGW(TAG, "Got IPv6 from another netif: ignored");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
|
|
||||||
ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
|
|
||||||
IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]);
|
|
||||||
if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) {
|
|
||||||
memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr));
|
|
||||||
xSemaphoreGive(s_semph_get_ip_addrs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
|
|
||||||
esp_err_t example_connect(void)
|
|
||||||
{
|
|
||||||
#if EXAMPLE_DO_CONNECT
|
|
||||||
if (s_semph_get_ip_addrs != NULL) {
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
start();
|
|
||||||
ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop));
|
|
||||||
ESP_LOGI(TAG, "Waiting for IP(s)");
|
|
||||||
for (int i = 0; i < NR_OF_IP_ADDRESSES_TO_WAIT_FOR; ++i) {
|
|
||||||
xSemaphoreTake(s_semph_get_ip_addrs, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
// iterate over active interfaces, and print out IPs of "our" netifs
|
|
||||||
esp_netif_t *netif = NULL;
|
|
||||||
esp_netif_ip_info_t ip;
|
|
||||||
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) {
|
|
||||||
netif = esp_netif_next(netif);
|
|
||||||
if (is_our_netif(TAG, netif)) {
|
|
||||||
ESP_LOGI(TAG, "Connected to %s", esp_netif_get_desc(netif));
|
|
||||||
ESP_ERROR_CHECK(esp_netif_get_ip_info(netif, &ip));
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "- IPv4 address: " IPSTR, IP2STR(&ip.ip));
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
esp_ip6_addr_t ip6[MAX_IP6_ADDRS_PER_NETIF];
|
|
||||||
int ip6_addrs = esp_netif_get_all_ip6(netif, ip6);
|
|
||||||
for (int j = 0; j < ip6_addrs; ++j) {
|
|
||||||
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&(ip6[j]));
|
|
||||||
ESP_LOGI(TAG, "- IPv6 address: " IPV6STR ", type: %s", IPV62STR(ip6[j]), s_ipv6_addr_types[ipv6_type]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t example_disconnect(void)
|
|
||||||
{
|
|
||||||
if (s_semph_get_ip_addrs == NULL) {
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
vSemaphoreDelete(s_semph_get_ip_addrs);
|
|
||||||
s_semph_get_ip_addrs = NULL;
|
|
||||||
stop();
|
|
||||||
ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&stop));
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI
|
|
||||||
|
|
||||||
static void on_wifi_disconnect(void *arg, esp_event_base_t event_base,
|
|
||||||
int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect...");
|
|
||||||
esp_err_t err = esp_wifi_connect();
|
|
||||||
if (err == ESP_ERR_WIFI_NOT_STARTED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ESP_ERROR_CHECK(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
|
|
||||||
static void on_wifi_connect(void *esp_netif, esp_event_base_t event_base,
|
|
||||||
int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
esp_netif_create_ip6_linklocal(esp_netif);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
|
|
||||||
static esp_netif_t *wifi_start(void)
|
|
||||||
{
|
|
||||||
char *desc;
|
|
||||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
|
||||||
|
|
||||||
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
|
|
||||||
// Prefix the interface description with the module TAG
|
|
||||||
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
|
|
||||||
asprintf(&desc, "%s: %s", TAG, esp_netif_config.if_desc);
|
|
||||||
esp_netif_config.if_desc = desc;
|
|
||||||
esp_netif_config.route_prio = 128;
|
|
||||||
esp_netif_t *netif = esp_netif_create_wifi(WIFI_IF_STA, &esp_netif_config);
|
|
||||||
free(desc);
|
|
||||||
esp_wifi_set_default_wifi_sta_handlers();
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL));
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL));
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect, netif));
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
|
||||||
wifi_config_t wifi_config = {
|
|
||||||
.sta = {
|
|
||||||
.ssid = CONFIG_EXAMPLE_WIFI_SSID,
|
|
||||||
.password = CONFIG_EXAMPLE_WIFI_PASSWORD,
|
|
||||||
.scan_method = EXAMPLE_WIFI_SCAN_METHOD,
|
|
||||||
.sort_method = EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD,
|
|
||||||
.threshold.rssi = CONFIG_EXAMPLE_WIFI_SCAN_RSSI_THRESHOLD,
|
|
||||||
.threshold.authmode = EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid);
|
|
||||||
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());
|
|
||||||
esp_wifi_connect();
|
|
||||||
return netif;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wifi_stop(void)
|
|
||||||
{
|
|
||||||
esp_netif_t *wifi_netif = get_example_netif_from_desc("sta");
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect));
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip));
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6));
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect));
|
|
||||||
#endif
|
|
||||||
esp_err_t err = esp_wifi_stop();
|
|
||||||
if (err == ESP_ERR_WIFI_NOT_INIT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ESP_ERROR_CHECK(err);
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_deinit());
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(wifi_netif));
|
|
||||||
esp_netif_destroy(wifi_netif);
|
|
||||||
s_example_esp_netif = NULL;
|
|
||||||
}
|
|
||||||
#endif // CONFIG_EXAMPLE_CONNECT_WIFI
|
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
|
|
||||||
/** Event handler for Ethernet events */
|
|
||||||
static void on_eth_event(void *esp_netif, esp_event_base_t event_base,
|
|
||||||
int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
switch (event_id) {
|
|
||||||
case ETHERNET_EVENT_CONNECTED:
|
|
||||||
ESP_LOGI(TAG, "Ethernet Link Up");
|
|
||||||
ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
|
|
||||||
static esp_eth_handle_t s_eth_handle = NULL;
|
|
||||||
static esp_eth_mac_t *s_mac = NULL;
|
|
||||||
static esp_eth_phy_t *s_phy = NULL;
|
|
||||||
static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
|
|
||||||
|
|
||||||
static esp_netif_t *eth_start(void)
|
|
||||||
{
|
|
||||||
char *desc;
|
|
||||||
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
|
|
||||||
// Prefix the interface description with the module TAG
|
|
||||||
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
|
|
||||||
asprintf(&desc, "%s: %s", TAG, esp_netif_config.if_desc);
|
|
||||||
esp_netif_config.if_desc = desc;
|
|
||||||
esp_netif_config.route_prio = 64;
|
|
||||||
esp_netif_config_t netif_config = {
|
|
||||||
.base = &esp_netif_config,
|
|
||||||
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
|
|
||||||
};
|
|
||||||
esp_netif_t *netif = esp_netif_new(&netif_config);
|
|
||||||
assert(netif);
|
|
||||||
free(desc);
|
|
||||||
|
|
||||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
|
||||||
mac_config.rx_task_stack_size = CONFIG_EXAMPLE_ETHERNET_EMAC_TASK_STACK_SIZE;
|
|
||||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
|
||||||
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
|
|
||||||
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
|
|
||||||
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
|
||||||
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
|
||||||
esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
|
|
||||||
esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
|
|
||||||
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
|
||||||
#if CONFIG_EXAMPLE_ETH_PHY_IP101
|
|
||||||
s_phy = esp_eth_phy_new_ip101(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
|
|
||||||
s_phy = esp_eth_phy_new_rtl8201(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX
|
|
||||||
s_phy = esp_eth_phy_new_lan87xx(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_DP83848
|
|
||||||
s_phy = esp_eth_phy_new_dp83848(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX
|
|
||||||
s_phy = esp_eth_phy_new_ksz80xx(&phy_config);
|
|
||||||
#endif
|
|
||||||
#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
|
||||||
gpio_install_isr_service(0);
|
|
||||||
spi_bus_config_t buscfg = {
|
|
||||||
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
|
|
||||||
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
|
|
||||||
.sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
|
|
||||||
.quadwp_io_num = -1,
|
|
||||||
.quadhd_io_num = -1,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1));
|
|
||||||
spi_device_interface_config_t spi_devcfg = {
|
|
||||||
.mode = 0,
|
|
||||||
.clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
|
|
||||||
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
|
|
||||||
.queue_size = 20
|
|
||||||
};
|
|
||||||
#if CONFIG_EXAMPLE_USE_DM9051
|
|
||||||
/* dm9051 ethernet driver is based on spi driver */
|
|
||||||
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
|
|
||||||
dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
|
|
||||||
s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
|
||||||
s_phy = esp_eth_phy_new_dm9051(&phy_config);
|
|
||||||
#elif CONFIG_EXAMPLE_USE_W5500
|
|
||||||
/* w5500 ethernet driver is based on spi driver */
|
|
||||||
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
|
|
||||||
w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
|
|
||||||
s_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
|
||||||
s_phy = esp_eth_phy_new_w5500(&phy_config);
|
|
||||||
#endif
|
|
||||||
#elif CONFIG_EXAMPLE_USE_OPENETH
|
|
||||||
phy_config.autonego_timeout_ms = 100;
|
|
||||||
s_mac = esp_eth_mac_new_openeth(&mac_config);
|
|
||||||
s_phy = esp_eth_phy_new_dp83848(&phy_config);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Install Ethernet driver
|
|
||||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
|
||||||
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle));
|
|
||||||
#if !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
|
||||||
/* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually.
|
|
||||||
02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.
|
|
||||||
*/
|
|
||||||
ESP_ERROR_CHECK(esp_eth_ioctl(s_eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
|
|
||||||
0x02, 0x00, 0x00, 0x12, 0x34, 0x56
|
|
||||||
}));
|
|
||||||
#endif
|
|
||||||
// combine driver with netif
|
|
||||||
s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
|
|
||||||
esp_netif_attach(netif, s_eth_glue);
|
|
||||||
|
|
||||||
// Register user defined event handers
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL));
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif));
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
esp_eth_start(s_eth_handle);
|
|
||||||
return netif;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void eth_stop(void)
|
|
||||||
{
|
|
||||||
esp_netif_t *eth_netif = get_example_netif_from_desc("eth");
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip));
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6));
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event));
|
|
||||||
#endif
|
|
||||||
ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle));
|
|
||||||
ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue));
|
|
||||||
ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle));
|
|
||||||
s_eth_handle = NULL;
|
|
||||||
ESP_ERROR_CHECK(s_phy->del(s_phy));
|
|
||||||
ESP_ERROR_CHECK(s_mac->del(s_mac));
|
|
||||||
|
|
||||||
esp_netif_destroy(eth_netif);
|
|
||||||
s_example_esp_netif = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_eth_handle_t get_example_eth_handle(void)
|
|
||||||
{
|
|
||||||
return s_eth_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
||||||
|
|
||||||
esp_netif_t *get_example_netif(void)
|
|
||||||
{
|
|
||||||
return s_example_esp_netif;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_netif_t *get_example_netif_from_desc(const char *desc)
|
esp_netif_t *get_example_netif_from_desc(const char *desc)
|
||||||
{
|
{
|
||||||
esp_netif_t *netif = NULL;
|
esp_netif_t *netif = NULL;
|
||||||
char *expected_desc;
|
|
||||||
asprintf(&expected_desc, "%s: %s", TAG, desc);
|
|
||||||
while ((netif = esp_netif_next(netif)) != NULL) {
|
while ((netif = esp_netif_next(netif)) != NULL) {
|
||||||
if (strcmp(esp_netif_get_desc(netif), expected_desc) == 0) {
|
if (strcmp(esp_netif_get_desc(netif), desc) == 0) {
|
||||||
free(expected_desc);
|
|
||||||
return netif;
|
return netif;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(expected_desc);
|
|
||||||
return netif;
|
return netif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void example_print_all_netif_ips(const char *prefix)
|
||||||
|
{
|
||||||
|
// iterate over active interfaces, and print out IPs of "our" netifs
|
||||||
|
esp_netif_t *netif = NULL;
|
||||||
|
esp_netif_ip_info_t ip;
|
||||||
|
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) {
|
||||||
|
netif = esp_netif_next(netif);
|
||||||
|
if (example_is_our_netif(prefix, netif)) {
|
||||||
|
ESP_LOGI(TAG, "Connected to %s", esp_netif_get_desc(netif));
|
||||||
|
ESP_ERROR_CHECK(esp_netif_get_ip_info(netif, &ip));
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "- IPv4 address: " IPSTR ",", IP2STR(&ip.ip));
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
esp_ip6_addr_t ip6[MAX_IP6_ADDRS_PER_NETIF];
|
||||||
|
int ip6_addrs = esp_netif_get_all_ip6(netif, ip6);
|
||||||
|
for (int j = 0; j < ip6_addrs; ++j) {
|
||||||
|
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&(ip6[j]));
|
||||||
|
ESP_LOGI(TAG, "- IPv6 address: " IPV6STR ", type: %s", IPV62STR(ip6[j]), example_ipv6_addr_types_to_str[ipv6_type]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t example_connect(void)
|
||||||
|
{
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||||
|
example_ethernet_connect();
|
||||||
|
ESP_ERROR_CHECK(esp_register_shutdown_handler(&example_ethernet_shutdown));
|
||||||
|
#endif
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||||
|
example_wifi_connect();
|
||||||
|
ESP_ERROR_CHECK(esp_register_shutdown_handler(&example_wifi_shutdown));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||||
|
example_print_all_netif_ips(EXAMPLE_NETIF_DESC_ETH);
|
||||||
|
#endif
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||||
|
example_print_all_netif_ips(EXAMPLE_NETIF_DESC_STA);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t example_disconnect(void)
|
||||||
|
{
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||||
|
example_ethernet_shutdown();
|
||||||
|
ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&example_ethernet_shutdown));
|
||||||
|
#endif
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||||
|
example_wifi_shutdown();
|
||||||
|
ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&example_wifi_shutdown));
|
||||||
|
#endif
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "protocol_examples_common.h"
|
||||||
|
#include "example_common_private.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_console.h"
|
||||||
|
#include "argtable3/argtable3.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const char *TAG = "example_console";
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct arg_str *ssid;
|
||||||
|
struct arg_str *password;
|
||||||
|
struct arg_int *channel;
|
||||||
|
struct arg_end *end;
|
||||||
|
} wifi_connect_args_t;
|
||||||
|
static wifi_connect_args_t connect_args;
|
||||||
|
|
||||||
|
static int cmd_do_wifi_connect(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int nerrors = arg_parse(argc, argv, (void **) &connect_args);
|
||||||
|
|
||||||
|
if (nerrors != 0) {
|
||||||
|
arg_print_errors(stderr, connect_args.end, argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wifi_config_t wifi_config = {
|
||||||
|
.sta = {
|
||||||
|
.scan_method = WIFI_ALL_CHANNEL_SCAN,
|
||||||
|
.sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (connect_args.channel->count > 0) {
|
||||||
|
wifi_config.sta.channel = (uint8_t)(connect_args.channel->ival[0]);
|
||||||
|
}
|
||||||
|
const char *ssid = connect_args.ssid->sval[0];
|
||||||
|
const char *pass = connect_args.password->sval[0];
|
||||||
|
strlcpy((char *) wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
|
||||||
|
if (pass) {
|
||||||
|
strlcpy((char *) wifi_config.sta.password, pass, sizeof(wifi_config.sta.password));
|
||||||
|
}
|
||||||
|
example_wifi_sta_do_connect(wifi_config, false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_do_wifi_disconnect(int argc, char **argv)
|
||||||
|
{
|
||||||
|
example_wifi_sta_do_disconnect();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_wifi_connect_commands(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Registering WiFi connect commands.");
|
||||||
|
example_wifi_start();
|
||||||
|
|
||||||
|
connect_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
|
||||||
|
connect_args.password = arg_str0(NULL, NULL, "<pass>", "password of AP");
|
||||||
|
connect_args.channel = arg_int0("n", "channel", "<channel>", "channel of AP");
|
||||||
|
connect_args.end = arg_end(2);
|
||||||
|
const esp_console_cmd_t wifi_connect_cmd = {
|
||||||
|
.command = "wifi_connect",
|
||||||
|
.help = "WiFi is station mode, join specified soft-AP",
|
||||||
|
.hint = NULL,
|
||||||
|
.func = &cmd_do_wifi_connect,
|
||||||
|
.argtable = &connect_args
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK( esp_console_cmd_register(&wifi_connect_cmd) );
|
||||||
|
|
||||||
|
|
||||||
|
const esp_console_cmd_t wifi_disconnect_cmd = {
|
||||||
|
.command = "wifi_disconnect",
|
||||||
|
.help = "Do wifi disconnect",
|
||||||
|
.hint = NULL,
|
||||||
|
.func = &cmd_do_wifi_disconnect,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK( esp_console_cmd_register(&wifi_disconnect_cmd) );
|
||||||
|
}
|
@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "protocol_examples_common.h"
|
||||||
|
#include "example_common_private.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_eth.h"
|
||||||
|
#if CONFIG_ETH_USE_SPI_ETHERNET
|
||||||
|
#include "driver/spi_master.h"
|
||||||
|
#endif // CONFIG_ETH_USE_SPI_ETHERNET
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const char *TAG = "ethernet_connect";
|
||||||
|
static SemaphoreHandle_t s_semph_get_ip_addrs = NULL;
|
||||||
|
|
||||||
|
static esp_netif_t *eth_start(void);
|
||||||
|
static void eth_stop(void);
|
||||||
|
|
||||||
|
|
||||||
|
/** Event handler for Ethernet events */
|
||||||
|
|
||||||
|
static void eth_on_got_ip(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||||
|
if (!example_is_our_netif(EXAMPLE_NETIF_DESC_ETH, event->esp_netif)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
|
||||||
|
if (s_semph_get_ip_addrs) {
|
||||||
|
xSemaphoreGive(s_semph_get_ip_addrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
|
||||||
|
static void eth_on_got_ipv6(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
||||||
|
if (!example_is_our_netif(EXAMPLE_NETIF_DESC_ETH, event->esp_netif)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
|
||||||
|
ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
|
||||||
|
IPV62STR(event->ip6_info.ip), example_ipv6_addr_types_to_str[ipv6_type]);
|
||||||
|
if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) {
|
||||||
|
xSemaphoreGive(s_semph_get_ip_addrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_eth_event(void *esp_netif, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
switch (event_id) {
|
||||||
|
case ETHERNET_EVENT_CONNECTED:
|
||||||
|
ESP_LOGI(TAG, "Ethernet Link Up");
|
||||||
|
ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
|
||||||
|
static esp_eth_handle_t s_eth_handle = NULL;
|
||||||
|
static esp_eth_mac_t *s_mac = NULL;
|
||||||
|
static esp_eth_phy_t *s_phy = NULL;
|
||||||
|
static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
|
||||||
|
|
||||||
|
static esp_netif_t *eth_start(void)
|
||||||
|
{
|
||||||
|
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
|
||||||
|
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
|
||||||
|
esp_netif_config.if_desc = EXAMPLE_NETIF_DESC_ETH;
|
||||||
|
esp_netif_config.route_prio = 64;
|
||||||
|
esp_netif_config_t netif_config = {
|
||||||
|
.base = &esp_netif_config,
|
||||||
|
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
|
||||||
|
};
|
||||||
|
esp_netif_t *netif = esp_netif_new(&netif_config);
|
||||||
|
assert(netif);
|
||||||
|
|
||||||
|
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||||
|
mac_config.rx_task_stack_size = CONFIG_EXAMPLE_ETHERNET_EMAC_TASK_STACK_SIZE;
|
||||||
|
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||||
|
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
|
||||||
|
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
|
||||||
|
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
||||||
|
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||||
|
esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
|
||||||
|
esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
|
||||||
|
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
||||||
|
#if CONFIG_EXAMPLE_ETH_PHY_IP101
|
||||||
|
s_phy = esp_eth_phy_new_ip101(&phy_config);
|
||||||
|
#elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
|
||||||
|
s_phy = esp_eth_phy_new_rtl8201(&phy_config);
|
||||||
|
#elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX
|
||||||
|
s_phy = esp_eth_phy_new_lan87xx(&phy_config);
|
||||||
|
#elif CONFIG_EXAMPLE_ETH_PHY_DP83848
|
||||||
|
s_phy = esp_eth_phy_new_dp83848(&phy_config);
|
||||||
|
#elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX
|
||||||
|
s_phy = esp_eth_phy_new_ksz80xx(&phy_config);
|
||||||
|
#endif
|
||||||
|
#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET
|
||||||
|
gpio_install_isr_service(0);
|
||||||
|
spi_bus_config_t buscfg = {
|
||||||
|
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
|
||||||
|
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
|
||||||
|
.sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
|
||||||
|
.quadwp_io_num = -1,
|
||||||
|
.quadhd_io_num = -1,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1));
|
||||||
|
spi_device_interface_config_t spi_devcfg = {
|
||||||
|
.mode = 0,
|
||||||
|
.clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
|
||||||
|
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
|
||||||
|
.queue_size = 20
|
||||||
|
};
|
||||||
|
#if CONFIG_EXAMPLE_USE_DM9051
|
||||||
|
/* dm9051 ethernet driver is based on spi driver */
|
||||||
|
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
|
||||||
|
dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
|
||||||
|
s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
||||||
|
s_phy = esp_eth_phy_new_dm9051(&phy_config);
|
||||||
|
#elif CONFIG_EXAMPLE_USE_W5500
|
||||||
|
/* w5500 ethernet driver is based on spi driver */
|
||||||
|
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
|
||||||
|
w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
|
||||||
|
s_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
||||||
|
s_phy = esp_eth_phy_new_w5500(&phy_config);
|
||||||
|
#endif
|
||||||
|
#elif CONFIG_EXAMPLE_USE_OPENETH
|
||||||
|
phy_config.autonego_timeout_ms = 100;
|
||||||
|
s_mac = esp_eth_mac_new_openeth(&mac_config);
|
||||||
|
s_phy = esp_eth_phy_new_dp83848(&phy_config);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Install Ethernet driver
|
||||||
|
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
||||||
|
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle));
|
||||||
|
#if !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
|
||||||
|
/* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually.
|
||||||
|
02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.
|
||||||
|
*/
|
||||||
|
ESP_ERROR_CHECK(esp_eth_ioctl(s_eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
|
||||||
|
0x02, 0x00, 0x00, 0x12, 0x34, 0x56
|
||||||
|
}));
|
||||||
|
#endif
|
||||||
|
// combine driver with netif
|
||||||
|
s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
|
||||||
|
esp_netif_attach(netif, s_eth_glue);
|
||||||
|
|
||||||
|
// Register user defined event handers
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, ð_on_got_ip, NULL));
|
||||||
|
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, ð_on_got_ipv6, NULL));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
esp_eth_start(s_eth_handle);
|
||||||
|
return netif;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eth_stop(void)
|
||||||
|
{
|
||||||
|
esp_netif_t *eth_netif = get_example_netif_from_desc(EXAMPLE_NETIF_DESC_ETH);
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, ð_on_got_ip));
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, ð_on_got_ipv6));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event));
|
||||||
|
#endif
|
||||||
|
ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle));
|
||||||
|
ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue));
|
||||||
|
ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle));
|
||||||
|
s_eth_handle = NULL;
|
||||||
|
ESP_ERROR_CHECK(s_phy->del(s_phy));
|
||||||
|
ESP_ERROR_CHECK(s_mac->del(s_mac));
|
||||||
|
|
||||||
|
esp_netif_destroy(eth_netif);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_eth_handle_t get_example_eth_handle(void)
|
||||||
|
{
|
||||||
|
return s_eth_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tear down connection, release resources */
|
||||||
|
void example_ethernet_shutdown(void)
|
||||||
|
{
|
||||||
|
if (s_semph_get_ip_addrs == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vSemaphoreDelete(s_semph_get_ip_addrs);
|
||||||
|
s_semph_get_ip_addrs = NULL;
|
||||||
|
eth_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t example_ethernet_connect(void)
|
||||||
|
{
|
||||||
|
s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0);
|
||||||
|
eth_start();
|
||||||
|
ESP_LOGI(TAG, "Waiting for IP(s).");
|
||||||
|
for (int i = 0; i < NR_OF_IP_ADDRESSES_TO_WAIT_FOR; ++i) {
|
||||||
|
xSemaphoreTake(s_semph_get_ip_addrs, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
@ -12,14 +12,14 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
#include <lwip/netdb.h>
|
#include <lwip/netdb.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read and evaluate IP address from stdin
|
* @brief Read and evaluate IP address from stdin
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
/* Private Funtions of protocol example common */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (2)
|
||||||
|
#else
|
||||||
|
#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
#define MAX_IP6_ADDRS_PER_NETIF (5)
|
||||||
|
|
||||||
|
#if defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK)
|
||||||
|
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_LINK_LOCAL
|
||||||
|
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_GLOBAL)
|
||||||
|
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_GLOBAL
|
||||||
|
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL)
|
||||||
|
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_SITE_LOCAL
|
||||||
|
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL)
|
||||||
|
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_UNIQUE_LOCAL
|
||||||
|
#endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_...
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
extern const char *example_ipv6_addr_types_to_str[6];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void example_wifi_start(void);
|
||||||
|
void example_wifi_stop(void);
|
||||||
|
esp_err_t example_wifi_sta_do_connect(wifi_config_t wifi_config, bool wait);
|
||||||
|
esp_err_t example_wifi_sta_do_disconnect(void);
|
||||||
|
bool example_is_our_netif(const char *prefix, esp_netif_t *netif);
|
||||||
|
void example_print_all_netif_ips(const char *prefix);
|
||||||
|
void example_wifi_shutdown(void);
|
||||||
|
esp_err_t example_wifi_connect(void);
|
||||||
|
void example_ethernet_shutdown(void);
|
||||||
|
esp_err_t example_ethernet_connect(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -9,25 +9,32 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||||
|
#include "esp_eth.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "esp_err.h"
|
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||||
#include "esp_netif.h"
|
#define EXAMPLE_NETIF_DESC_STA "example_netif_sta"
|
||||||
#include "esp_eth.h"
|
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
|
|
||||||
#define EXAMPLE_INTERFACE get_example_netif()
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI
|
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||||
#define EXAMPLE_INTERFACE get_example_netif()
|
#define EXAMPLE_NETIF_DESC_ETH "example_netif_eth"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined (CONFIG_EXAMPLE_CONNECT_ETHERNET) && !defined (CONFIG_EXAMPLE_CONNECT_WIFI)
|
/* Example default interface, prefer the ethernet one if running in example-test (CI) configuration */
|
||||||
// This is useful for some tests which do not need a network connection
|
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||||
#define EXAMPLE_INTERFACE NULL
|
#define EXAMPLE_INTERFACE get_example_netif_from_desc(EXAMPLE_NETIF_DESC_ETH)
|
||||||
|
#define get_example_netif() get_example_netif_from_desc(EXAMPLE_NETIF_DESC_ETH)
|
||||||
|
#elif CONFIG_EXAMPLE_CONNECT_WIFI
|
||||||
|
#define EXAMPLE_INTERFACE get_example_netif_from_desc(EXAMPLE_NETIF_DESC_STA)
|
||||||
|
#define get_example_netif() get_example_netif_from_desc(EXAMPLE_NETIF_DESC_STA)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,15 +67,6 @@ esp_err_t example_disconnect(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t example_configure_stdin_stdout(void);
|
esp_err_t example_configure_stdin_stdout(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns esp-netif pointer created by example_connect()
|
|
||||||
*
|
|
||||||
* @note If multiple interfaces active at once, this API return NULL
|
|
||||||
* In that case the get_example_netif_from_desc() should be used
|
|
||||||
* to get esp-netif pointer based on interface description
|
|
||||||
*/
|
|
||||||
esp_netif_t *get_example_netif(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns esp-netif pointer created by example_connect() described by
|
* @brief Returns esp-netif pointer created by example_connect() described by
|
||||||
* the supplied desc field
|
* the supplied desc field
|
||||||
@ -79,7 +77,16 @@ esp_netif_t *get_example_netif(void);
|
|||||||
*/
|
*/
|
||||||
esp_netif_t *get_example_netif_from_desc(const char *desc);
|
esp_netif_t *get_example_netif_from_desc(const char *desc);
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
|
#if CONFIG_EXAMPLE_PROVIDE_WIFI_CONSOLE_CMD
|
||||||
|
/**
|
||||||
|
* @brief Register wifi connect commands
|
||||||
|
*
|
||||||
|
* @note Provide wifi connect commands using esp_console.
|
||||||
|
*/
|
||||||
|
void register_wifi_connect_commands(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||||
/**
|
/**
|
||||||
* @brief Get the example Ethernet driver handle
|
* @brief Get the example Ethernet driver handle
|
||||||
*
|
*
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
|
|
||||||
esp_err_t example_configure_stdin_stdout(void)
|
esp_err_t example_configure_stdin_stdout(void)
|
||||||
{
|
{
|
||||||
|
static bool configured = false;
|
||||||
|
if (configured) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
// Initialize VFS & UART so we can use std::cout/cin
|
// Initialize VFS & UART so we can use std::cout/cin
|
||||||
setvbuf(stdin, NULL, _IONBF, 0);
|
setvbuf(stdin, NULL, _IONBF, 0);
|
||||||
/* Install UART driver for interrupt-driven reads and writes */
|
/* Install UART driver for interrupt-driven reads and writes */
|
||||||
@ -25,5 +29,6 @@ esp_err_t example_configure_stdin_stdout(void)
|
|||||||
esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR);
|
esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR);
|
||||||
/* Move the caret to the beginning of the next line on '\n' */
|
/* Move the caret to the beginning of the next line on '\n' */
|
||||||
esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF);
|
esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF);
|
||||||
|
configured = true;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,236 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection.
|
||||||
|
|
||||||
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, this
|
||||||
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "protocol_examples_common.h"
|
||||||
|
#include "example_common_private.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||||
|
|
||||||
|
static const char *TAG = "example_connect";
|
||||||
|
static esp_netif_t *s_example_sta_netif = NULL;
|
||||||
|
static SemaphoreHandle_t s_semph_get_ip_addrs = NULL;
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_WIFI_SCAN_METHOD_FAST
|
||||||
|
#define EXAMPLE_WIFI_SCAN_METHOD WIFI_FAST_SCAN
|
||||||
|
#elif CONFIG_EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL
|
||||||
|
#define EXAMPLE_WIFI_SCAN_METHOD WIFI_ALL_CHANNEL_SCAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL
|
||||||
|
#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL
|
||||||
|
#elif CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SECURITY
|
||||||
|
#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SECURITY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_WIFI_AUTH_OPEN
|
||||||
|
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
|
||||||
|
#elif CONFIG_EXAMPLE_WIFI_AUTH_WEP
|
||||||
|
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
|
||||||
|
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_PSK
|
||||||
|
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
|
||||||
|
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_PSK
|
||||||
|
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
|
||||||
|
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_WPA2_PSK
|
||||||
|
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
|
||||||
|
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_ENTERPRISE
|
||||||
|
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_ENTERPRISE
|
||||||
|
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA3_PSK
|
||||||
|
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
|
||||||
|
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_WPA3_PSK
|
||||||
|
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
|
||||||
|
#elif CONFIG_EXAMPLE_WIFI_AUTH_WAPI_PSK
|
||||||
|
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static void example_handler_on_wifi_disconnect(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect...");
|
||||||
|
esp_err_t err = esp_wifi_connect();
|
||||||
|
if (err == ESP_ERR_WIFI_NOT_STARTED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void example_handler_on_wifi_connect(void *esp_netif, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
esp_netif_create_ip6_linklocal(esp_netif);
|
||||||
|
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
}
|
||||||
|
|
||||||
|
static void example_handler_on_sta_got_ip(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||||
|
if (!example_is_our_netif(EXAMPLE_NETIF_DESC_STA, event->esp_netif)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
|
||||||
|
if (s_semph_get_ip_addrs) {
|
||||||
|
xSemaphoreGive(s_semph_get_ip_addrs);
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "- IPv4 address: " IPSTR ",", IP2STR(&event->ip_info.ip));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
static void example_handler_on_sta_got_ipv6(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
||||||
|
if (!example_is_our_netif(EXAMPLE_NETIF_DESC_STA, event->esp_netif)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
|
||||||
|
ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
|
||||||
|
IPV62STR(event->ip6_info.ip), example_ipv6_addr_types_to_str[ipv6_type]);
|
||||||
|
|
||||||
|
if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) {
|
||||||
|
if (s_semph_get_ip_addrs) {
|
||||||
|
xSemaphoreGive(s_semph_get_ip_addrs);
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "- IPv6 address: " IPV6STR ", type: %s", IPV62STR(event->ip6_info.ip), example_ipv6_addr_types_to_str[ipv6_type]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
|
||||||
|
|
||||||
|
void example_wifi_start(void)
|
||||||
|
{
|
||||||
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||||
|
|
||||||
|
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
|
||||||
|
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
|
||||||
|
esp_netif_config.if_desc = EXAMPLE_NETIF_DESC_STA;
|
||||||
|
esp_netif_config.route_prio = 128;
|
||||||
|
s_example_sta_netif = esp_netif_create_wifi(WIFI_IF_STA, &esp_netif_config);
|
||||||
|
esp_wifi_set_default_wifi_sta_handlers();
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_start());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void example_wifi_stop(void)
|
||||||
|
{
|
||||||
|
esp_err_t err = esp_wifi_stop();
|
||||||
|
if (err == ESP_ERR_WIFI_NOT_INIT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_deinit());
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(s_example_sta_netif));
|
||||||
|
esp_netif_destroy(s_example_sta_netif);
|
||||||
|
s_example_sta_netif = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t example_wifi_sta_do_connect(wifi_config_t wifi_config, bool wait)
|
||||||
|
{
|
||||||
|
if (wait) {
|
||||||
|
s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &example_handler_on_wifi_disconnect, NULL));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &example_handler_on_sta_got_ip, NULL));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &example_handler_on_wifi_connect, s_example_sta_netif));
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &example_handler_on_sta_got_ipv6, NULL));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid);
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||||
|
esp_err_t ret = esp_wifi_connect();
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "WiFi connect failed! ret:%x", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (wait) {
|
||||||
|
ESP_LOGI(TAG, "Waiting for IP(s)");
|
||||||
|
for (int i = 0; i < NR_OF_IP_ADDRESSES_TO_WAIT_FOR; ++i) {
|
||||||
|
xSemaphoreTake(s_semph_get_ip_addrs, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t example_wifi_sta_do_disconnect(void)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &example_handler_on_wifi_disconnect));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &example_handler_on_sta_got_ip));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &example_handler_on_wifi_connect));
|
||||||
|
#if CONFIG_EXAMPLE_CONNECT_IPV6
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &example_handler_on_sta_got_ipv6));
|
||||||
|
#endif
|
||||||
|
if (s_semph_get_ip_addrs) {
|
||||||
|
vSemaphoreDelete(s_semph_get_ip_addrs);
|
||||||
|
}
|
||||||
|
return esp_wifi_disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void example_wifi_shutdown(void)
|
||||||
|
{
|
||||||
|
example_wifi_sta_do_disconnect();
|
||||||
|
example_wifi_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t example_wifi_connect(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Start example_connect.");
|
||||||
|
example_wifi_start();
|
||||||
|
wifi_config_t wifi_config = {
|
||||||
|
.sta = {
|
||||||
|
#if !CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
|
||||||
|
.ssid = CONFIG_EXAMPLE_WIFI_SSID,
|
||||||
|
.password = CONFIG_EXAMPLE_WIFI_PASSWORD,
|
||||||
|
#endif
|
||||||
|
.scan_method = EXAMPLE_WIFI_SCAN_METHOD,
|
||||||
|
.sort_method = EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD,
|
||||||
|
.threshold.rssi = CONFIG_EXAMPLE_WIFI_SCAN_RSSI_THRESHOLD,
|
||||||
|
.threshold.authmode = EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
#if CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
|
||||||
|
example_configure_stdin_stdout();
|
||||||
|
char buf[32+64+2] = {0};
|
||||||
|
ESP_LOGI(TAG, "Please input ssid password:");
|
||||||
|
fgets(buf, sizeof(buf), stdin);
|
||||||
|
int len = strlen(buf);
|
||||||
|
buf[len-1] = '\0';
|
||||||
|
memset(wifi_config.sta.ssid, 0, 32);
|
||||||
|
char *temp = strtok(buf, " ");
|
||||||
|
strncpy((char*)wifi_config.sta.ssid, temp, 32);
|
||||||
|
memset(wifi_config.sta.password, 0, 64);
|
||||||
|
temp = strtok(NULL, " ");
|
||||||
|
if (temp) {
|
||||||
|
strncpy((char*)wifi_config.sta.password, temp, 64);
|
||||||
|
} else {
|
||||||
|
wifi_config.sta.threshold.authmode = WIFI_AUTH_OPEN;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
example_wifi_sta_do_connect(wifi_config, true);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CONFIG_EXAMPLE_CONNECT_WIFI */
|
@ -8,7 +8,7 @@ See the [README.md](../README.md) file in the upper level [examples](../) direct
|
|||||||
|
|
||||||
### About the `example_connect()` Function
|
### About the `example_connect()` Function
|
||||||
|
|
||||||
Protocols examples use a simple helper function, `example_connect()`, to establish Wi-Fi and/or Ethernet connection. This function is implemented in [examples/common_components/protocol_examples/common/connect.c](../common_components/protocol_examples_common/connect.c), and has a very simple behavior: block until connection is established and IP address is obtained, then return. This function is used to reduce the amount of boilerplate and to keep the example code focused on the protocol or library being demonstrated.
|
Protocols examples use a simple helper function, `example_connect()`, to establish Wi-Fi and/or Ethernet connection. This function is implemented in [examples/common_components/protocol_examples_common/include/protocol_examples_common.h](../common_components/protocol_examples_common/include/protocol_examples_common.h), and has a very simple behavior: block until connection is established and IP address is obtained, then return. This function is used to reduce the amount of boilerplate and to keep the example code focused on the protocol or library being demonstrated.
|
||||||
|
|
||||||
The simple `example_connect()` function does not handle timeouts, does not gracefully handle various error conditions, and is only suited for use in examples. When developing real applications, this helper function needs to be replaced with full Wi-Fi / Ethernet connection handling code. Such code can be found in [examples/wifi/getting_started/](../wifi/getting_started) and [examples/ethernet/basic/](../ethernet/basic) examples.
|
The simple `example_connect()` function does not handle timeouts, does not gracefully handle various error conditions, and is only suited for use in examples. When developing real applications, this helper function needs to be replaced with full Wi-Fi / Ethernet connection handling code. Such code can be found in [examples/wifi/getting_started/](../wifi/getting_started) and [examples/ethernet/basic/](../ethernet/basic) examples.
|
||||||
|
|
||||||
|
@ -33,9 +33,9 @@
|
|||||||
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
|
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
|
||||||
/* The interface name value can refer to if_desc in esp_netif_defaults.h */
|
/* The interface name value can refer to if_desc in esp_netif_defaults.h */
|
||||||
#if CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_ETH
|
#if CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_ETH
|
||||||
static const char *bind_interface_name = "eth";
|
static const char *bind_interface_name = EXAMPLE_NETIF_DESC_ETH;
|
||||||
#elif CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_STA
|
#elif CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_STA
|
||||||
static const char *bind_interface_name = "sta";
|
static const char *bind_interface_name = EXAMPLE_NETIF_DESC_STA;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1744,7 +1744,6 @@ examples/build_system/cmake/multi_config/main/multi_config_example_main.c
|
|||||||
examples/common_components/iperf/include/iperf.h
|
examples/common_components/iperf/include/iperf.h
|
||||||
examples/common_components/iperf/iperf.c
|
examples/common_components/iperf/iperf.c
|
||||||
examples/common_components/protocol_examples_common/addr_from_stdin.c
|
examples/common_components/protocol_examples_common/addr_from_stdin.c
|
||||||
examples/common_components/protocol_examples_common/connect.c
|
|
||||||
examples/common_components/protocol_examples_common/include/addr_from_stdin.h
|
examples/common_components/protocol_examples_common/include/addr_from_stdin.h
|
||||||
examples/common_components/protocol_examples_common/include/protocol_examples_common.h
|
examples/common_components/protocol_examples_common/include/protocol_examples_common.h
|
||||||
examples/common_components/protocol_examples_common/stdin_out.c
|
examples/common_components/protocol_examples_common/stdin_out.c
|
||||||
|
Loading…
Reference in New Issue
Block a user