mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-19 13:32:21 +02:00
feat(examples): Add multiple netif demo: eth+wifi+PPP
This commit is contained in:
6
examples/esp_netif/multiple_netifs/CMakeLists.txt
Normal file
6
examples/esp_netif/multiple_netifs/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||||
|
# in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(multiple_netifs)
|
25
examples/esp_netif/multiple_netifs/README.md
Normal file
25
examples/esp_netif/multiple_netifs/README.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
| Supported Targets | ESP32 |
|
||||||
|
| ----------------- | ----- |
|
||||||
|
|
||||||
|
# Multiple Interface example
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This example demonstrates working with multiple different interfaces with different priorities. It creates these interfaces and tries to connect:
|
||||||
|
* WiFi Station
|
||||||
|
* Ethernet using ESP32 internal ethernet driver
|
||||||
|
* PPPoS over cellular modem
|
||||||
|
|
||||||
|
## How to use example
|
||||||
|
|
||||||
|
* Set the priorities and the host name for the example to ICMP ping.
|
||||||
|
* The example will initialize all interfaces
|
||||||
|
* The example will start looping and checking connectivity to the host name
|
||||||
|
* It prints the default interface and ping output
|
||||||
|
* It tries to reconfigure DNS server if host name resolution fails
|
||||||
|
* It tries to manually change the default interface if connection fails
|
||||||
|
|
||||||
|
### Hardware Required
|
||||||
|
|
||||||
|
To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html).
|
||||||
|
You would also need a modem connected to the board using UART interface.
|
2
examples/esp_netif/multiple_netifs/main/CMakeLists.txt
Normal file
2
examples/esp_netif/multiple_netifs/main/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
idf_component_register(SRCS ethernet_netif.c multi_netif_main.c wifi_connect.c check_connection.c ppp_connect.c
|
||||||
|
INCLUDE_DIRS ".")
|
42
examples/esp_netif/multiple_netifs/main/Kconfig.projbuild
Normal file
42
examples/esp_netif/multiple_netifs/main/Kconfig.projbuild
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
menu "Connection Configuration"
|
||||||
|
|
||||||
|
config ESP_WIFI_SSID
|
||||||
|
string "WiFi SSID"
|
||||||
|
default "myssid"
|
||||||
|
help
|
||||||
|
SSID (network name) for the example to connect to.
|
||||||
|
|
||||||
|
config ESP_WIFI_PASSWORD
|
||||||
|
string "WiFi Password"
|
||||||
|
default "mypassword"
|
||||||
|
help
|
||||||
|
WiFi password (WPA or WPA2) for the example to use.
|
||||||
|
|
||||||
|
config ESP_MAXIMUM_RETRY
|
||||||
|
int "Maximum retry"
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
Set the Maximum retry to avoid station reconnecting. Set to 0 to keep retrying indefinitely.
|
||||||
|
|
||||||
|
config EXAMPLE_MODEM_PPP_APN
|
||||||
|
string "Set MODEM APN"
|
||||||
|
default "default.apn"
|
||||||
|
help
|
||||||
|
Set APN (Access Point Name), a logical name to choose data network
|
||||||
|
|
||||||
|
config EXAMPLE_MODEM_UART_TX_PIN
|
||||||
|
int "TXD Pin Number"
|
||||||
|
default 15
|
||||||
|
range 0 31
|
||||||
|
help
|
||||||
|
Pin number of UART TX.
|
||||||
|
|
||||||
|
config EXAMPLE_MODEM_UART_RX_PIN
|
||||||
|
int "RXD Pin Number"
|
||||||
|
default 14
|
||||||
|
range 0 31
|
||||||
|
help
|
||||||
|
Pin number of UART RX.
|
||||||
|
|
||||||
|
|
||||||
|
endmenu
|
113
examples/esp_netif/multiple_netifs/main/check_connection.c
Normal file
113
examples/esp_netif/multiple_netifs/main/check_connection.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
/* Checks network connectivity by pinging configured host
|
||||||
|
|
||||||
|
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 "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
#include "ping/ping_sock.h"
|
||||||
|
#include "lwip/netdb.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#define SUCCESS (1)
|
||||||
|
#define FAIL (2)
|
||||||
|
|
||||||
|
static const char *TAG = "check_connection";
|
||||||
|
|
||||||
|
static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args)
|
||||||
|
{
|
||||||
|
uint8_t ttl;
|
||||||
|
uint16_t seqno;
|
||||||
|
uint32_t elapsed_time, recv_len;
|
||||||
|
ip_addr_t target_addr;
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
|
||||||
|
ESP_LOGI(TAG, "%" PRIu32 " bytes from %s icmp_seq=%d ttl=%d time=%" PRIu32 " ms",
|
||||||
|
recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmd_ping_on_ping_timeout(esp_ping_handle_t hdl, void *args)
|
||||||
|
{
|
||||||
|
uint16_t seqno;
|
||||||
|
ip_addr_t target_addr;
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||||
|
ESP_LOGE(TAG, "From %s icmp_seq=%d timeout", inet_ntoa(target_addr.u_addr.ip4), seqno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
|
||||||
|
{
|
||||||
|
EventGroupHandle_t events = args;
|
||||||
|
ip_addr_t target_addr;
|
||||||
|
uint32_t transmitted;
|
||||||
|
uint32_t received;
|
||||||
|
uint32_t total_time_ms;
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||||
|
esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
|
||||||
|
uint32_t loss = (uint32_t)((1 - ((float)received) / transmitted) * 100);
|
||||||
|
if (IP_IS_V4(&target_addr)) {
|
||||||
|
ESP_LOGI(TAG, "\n--- %s ping statistics ---", inet_ntoa(*ip_2_ip4(&target_addr)));
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "\n--- %s ping statistics ---\n", inet6_ntoa(*ip_2_ip6(&target_addr)));
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "%" PRIu32 " packets transmitted, %" PRIu32 " received, %" PRIu32 "%% packet loss, time %"PRIu32"ms\n",
|
||||||
|
transmitted, received, loss, total_time_ms);
|
||||||
|
xEventGroupSetBits(events, received == 0 ? FAIL : SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t check_connectivity(const char *host)
|
||||||
|
{
|
||||||
|
EventGroupHandle_t events = xEventGroupCreate();
|
||||||
|
|
||||||
|
ip_addr_t target_addr;
|
||||||
|
struct addrinfo hint;
|
||||||
|
struct addrinfo *res = NULL;
|
||||||
|
memset(&hint, 0, sizeof(hint));
|
||||||
|
memset(&target_addr, 0, sizeof(target_addr));
|
||||||
|
/* convert domain name to IP address */
|
||||||
|
if (getaddrinfo(host, NULL, &hint, &res) != 0) {
|
||||||
|
ESP_LOGE(TAG, "ping: unknown host %s\n", host);
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
if (res->ai_family == AF_INET) {
|
||||||
|
struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr;
|
||||||
|
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
|
||||||
|
} else {
|
||||||
|
struct in6_addr addr6 = ((struct sockaddr_in6 *) (res->ai_addr))->sin6_addr;
|
||||||
|
inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6);
|
||||||
|
}
|
||||||
|
freeaddrinfo(res);
|
||||||
|
|
||||||
|
esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG();
|
||||||
|
config.target_addr = target_addr;
|
||||||
|
|
||||||
|
esp_ping_callbacks_t cbs = {
|
||||||
|
.on_ping_success = cmd_ping_on_ping_success,
|
||||||
|
.on_ping_timeout = cmd_ping_on_ping_timeout,
|
||||||
|
.on_ping_end = cmd_ping_on_ping_end,
|
||||||
|
.cb_args = events
|
||||||
|
};
|
||||||
|
esp_ping_handle_t ping;
|
||||||
|
esp_ping_new_session(&config, &cbs, &ping);
|
||||||
|
esp_ping_start(ping);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(config.count * config.interval_ms));
|
||||||
|
EventBits_t bits = xEventGroupWaitBits(events, FAIL | SUCCESS, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||||
|
|
||||||
|
vEventGroupDelete(events);
|
||||||
|
esp_ping_delete_session(ping);
|
||||||
|
|
||||||
|
return bits == SUCCESS ? ESP_OK : ESP_FAIL;
|
||||||
|
}
|
137
examples/esp_netif/multiple_netifs/main/ethernet_netif.c
Normal file
137
examples/esp_netif/multiple_netifs/main/ethernet_netif.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
/* Ethernet Basic Initialization
|
||||||
|
|
||||||
|
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 "esp_netif.h"
|
||||||
|
#include "esp_eth.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "iface_info.h"
|
||||||
|
|
||||||
|
static const char *TAG = "ethernet_connect";
|
||||||
|
|
||||||
|
struct eth_info_t {
|
||||||
|
iface_info_t parent;
|
||||||
|
esp_eth_handle_t eth_handle;
|
||||||
|
esp_eth_netif_glue_handle_t glue;
|
||||||
|
esp_eth_mac_t *mac;
|
||||||
|
esp_eth_phy_t *phy;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void eth_event_handler(void *args, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
uint8_t mac_addr[6] = {0};
|
||||||
|
/* we can get the ethernet driver handle from event data */
|
||||||
|
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
|
||||||
|
struct eth_info_t *eth_info = args;
|
||||||
|
|
||||||
|
switch (event_id) {
|
||||||
|
case ETHERNET_EVENT_CONNECTED:
|
||||||
|
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
|
||||||
|
ESP_LOGI(TAG, "Ethernet Link Up");
|
||||||
|
ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||||
|
eth_info->parent.connected = true;
|
||||||
|
break;
|
||||||
|
case ETHERNET_EVENT_DISCONNECTED:
|
||||||
|
ESP_LOGI(TAG, "Ethernet Link Down");
|
||||||
|
eth_info->parent.connected = false;
|
||||||
|
break;
|
||||||
|
case ETHERNET_EVENT_START:
|
||||||
|
ESP_LOGI(TAG, "Ethernet Started");
|
||||||
|
break;
|
||||||
|
case ETHERNET_EVENT_STOP:
|
||||||
|
ESP_LOGI(TAG, "Ethernet Stopped");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void got_ip_event_handler(void *args, 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;
|
||||||
|
const esp_netif_ip_info_t *ip_info = &event->ip_info;
|
||||||
|
struct eth_info_t *eth_info = args;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Ethernet Got IP Address");
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||||
|
ESP_LOGI(TAG, "IP:" IPSTR, IP2STR(&ip_info->ip));
|
||||||
|
ESP_LOGI(TAG, "MASK:" IPSTR, IP2STR(&ip_info->netmask));
|
||||||
|
ESP_LOGI(TAG, "GW:" IPSTR, IP2STR(&ip_info->gw));
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
esp_netif_get_dns_info(eth_info->parent.netif, i, ð_info->parent.dns[i]);
|
||||||
|
ESP_LOGI(TAG, "DNS %i:" IPSTR, i, IP2STR(ð_info->parent.dns[i].ip.u_addr.ip4));
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void teardown_eth(iface_info_t *info)
|
||||||
|
{
|
||||||
|
struct eth_info_t *eth_info = __containerof(info, struct eth_info_t, parent);
|
||||||
|
|
||||||
|
esp_eth_stop(eth_info->eth_handle);
|
||||||
|
esp_eth_del_netif_glue(eth_info->glue);
|
||||||
|
esp_eth_driver_uninstall(eth_info->eth_handle);
|
||||||
|
eth_info->phy->del(eth_info->phy);
|
||||||
|
eth_info->mac->del(eth_info->mac);
|
||||||
|
esp_netif_destroy(eth_info->parent.netif);
|
||||||
|
free(eth_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
iface_info_t *setup_eth(int prio)
|
||||||
|
{
|
||||||
|
struct eth_info_t *eth_info = malloc(sizeof(struct eth_info_t));
|
||||||
|
assert(eth_info);
|
||||||
|
eth_info->parent.teardown = teardown_eth;
|
||||||
|
eth_info->parent.name = "Ethernet";
|
||||||
|
|
||||||
|
// Init common MAC and PHY configs to default
|
||||||
|
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||||
|
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||||
|
|
||||||
|
// Use internal ESP32's ethernet
|
||||||
|
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||||
|
eth_info->mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
||||||
|
eth_info->phy = esp_eth_phy_new_ip101(&phy_config);
|
||||||
|
// Init Ethernet driver to default and install it
|
||||||
|
esp_eth_config_t config = ETH_DEFAULT_CONFIG(eth_info->mac, eth_info->phy);
|
||||||
|
ESP_ERROR_CHECK(esp_eth_driver_install(&config, ð_info->eth_handle));
|
||||||
|
|
||||||
|
// Create an instance of esp-netif for Ethernet
|
||||||
|
esp_netif_inherent_config_t base_netif_cfg = ESP_NETIF_INHERENT_DEFAULT_ETH();
|
||||||
|
base_netif_cfg.route_prio = prio;
|
||||||
|
esp_netif_config_t cfg = {
|
||||||
|
.base = &base_netif_cfg,
|
||||||
|
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH,
|
||||||
|
};
|
||||||
|
eth_info->parent.netif = esp_netif_new(&cfg);
|
||||||
|
eth_info->glue = esp_eth_new_netif_glue(eth_info->eth_handle);
|
||||||
|
// Attach Ethernet driver to TCP/IP stack
|
||||||
|
ESP_ERROR_CHECK(esp_netif_attach(eth_info->parent.netif, eth_info->glue ));
|
||||||
|
|
||||||
|
// Register user defined event handers
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_info));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_info));
|
||||||
|
|
||||||
|
// Start Ethernet driver state machine
|
||||||
|
ESP_ERROR_CHECK(esp_eth_start(eth_info->eth_handle));
|
||||||
|
|
||||||
|
return ð_info->parent;
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
dependencies:
|
||||||
|
espressif/esp_modem:
|
||||||
|
version: "^1.0.0"
|
||||||
|
override_path: "../../../../components/esp_modem"
|
26
examples/esp_netif/multiple_netifs/main/iface_info.h
Normal file
26
examples/esp_netif/multiple_netifs/main/iface_info.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
/* Common interface info
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "esp_netif.h"
|
||||||
|
|
||||||
|
struct iface_info_t {
|
||||||
|
esp_netif_t *netif;
|
||||||
|
esp_netif_dns_info_t dns[2];
|
||||||
|
void (*teardown)(struct iface_info_t *);
|
||||||
|
const char *name;
|
||||||
|
bool connected;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct iface_info_t iface_info_t;
|
129
examples/esp_netif/multiple_netifs/main/multi_netif_main.c
Normal file
129
examples/esp_netif/multiple_netifs/main/multi_netif_main.c
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Multiple Network Interface Example
|
||||||
|
|
||||||
|
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 <lwip/dns.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
#include "iface_info.h"
|
||||||
|
|
||||||
|
iface_info_t *setup_eth(int prio);
|
||||||
|
iface_info_t *setup_wifi(int prio);
|
||||||
|
iface_info_t *setup_ppp(int prio);
|
||||||
|
esp_err_t check_connectivity(const char *host);
|
||||||
|
|
||||||
|
#define HOST "www.espressif.com"
|
||||||
|
#define ETH_PRIO 200
|
||||||
|
#define WIFI_PRIO 100
|
||||||
|
#define PPP_PRIO 50
|
||||||
|
|
||||||
|
static const char *TAG = "app_main";
|
||||||
|
|
||||||
|
static ssize_t get_default(iface_info_t *list[], size_t num)
|
||||||
|
{
|
||||||
|
esp_netif_t *default_netif = esp_netif_get_default_netif();
|
||||||
|
if (default_netif == NULL) {
|
||||||
|
ESP_LOGE(TAG, "default netif is NULL!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Default netif: %s", esp_netif_get_desc(default_netif));
|
||||||
|
|
||||||
|
for (int i = 0; i < num; ++i) {
|
||||||
|
if (list[i] && list[i]->netif == default_netif) {
|
||||||
|
ESP_LOGI(TAG, "Default interface: %s", list[i]->name);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// not found
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret = nvs_flash_init();
|
||||||
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
|
ret = nvs_flash_init();
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
|
// Create default event loop that running in background
|
||||||
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
|
||||||
|
// all interfaces
|
||||||
|
iface_info_t *ifaces[] = {
|
||||||
|
setup_eth(ETH_PRIO),
|
||||||
|
setup_wifi(WIFI_PRIO),
|
||||||
|
setup_ppp(PPP_PRIO),
|
||||||
|
};
|
||||||
|
size_t num_of_ifaces = sizeof(ifaces) / sizeof(ifaces[0]);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
dns_clear_cache();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||||
|
ssize_t i = get_default(ifaces, num_of_ifaces);
|
||||||
|
if (i == -1) { // default netif is NULL, probably all interfaces are down -> retry
|
||||||
|
continue;
|
||||||
|
} else if (i < 0) {
|
||||||
|
break; // some other error, exit
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t connect_status = check_connectivity(HOST);
|
||||||
|
if (connect_status == ESP_OK) {
|
||||||
|
// connectivity ok
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (connect_status == ESP_ERR_NOT_FOUND) {
|
||||||
|
// set the default DNS info to global DNS server list
|
||||||
|
for (int j = 0; j < 2; ++j) {
|
||||||
|
esp_netif_dns_info_t dns_info;
|
||||||
|
esp_netif_get_dns_info(ifaces[i]->netif, j, &dns_info);
|
||||||
|
if (memcmp(&dns_info.ip, &ifaces[i]->dns[j].ip, sizeof(esp_ip_addr_t)) == 0) {
|
||||||
|
connect_status = ESP_FAIL;
|
||||||
|
} else {
|
||||||
|
esp_netif_set_dns_info(ifaces[i]->netif, j, &ifaces[i]->dns[j]);
|
||||||
|
ESP_LOGI(TAG, "Reconfigured DNS%i=" IPSTR, j, IP2STR(&ifaces[i]->dns[j].ip.u_addr.ip4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (connect_status == ESP_FAIL) {
|
||||||
|
ESP_LOGE(TAG, "No connection via the default netif!");
|
||||||
|
// try to switch interfaces manually
|
||||||
|
// WARNING: Once we set_default_netif() manually, we disable the automatic prio-routing
|
||||||
|
int next = (i + 1) % num_of_ifaces;
|
||||||
|
while (ifaces[i] != ifaces[next]) {
|
||||||
|
if (ifaces[next]->connected) {
|
||||||
|
ESP_LOGE(TAG, "Trying another interface: %s", ifaces[next]->name);
|
||||||
|
esp_netif_set_default_netif(ifaces[next]->netif);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++next;
|
||||||
|
next = next % num_of_ifaces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Stop and cleanup all interfaces");
|
||||||
|
for (int i = 0; i < num_of_ifaces; ++i) {
|
||||||
|
if (ifaces[i]) {
|
||||||
|
ifaces[i]->teardown(ifaces[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
210
examples/esp_netif/multiple_netifs/main/ppp_connect.c
Normal file
210
examples/esp_netif/multiple_netifs/main/ppp_connect.c
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
/* PPPoS Initialization
|
||||||
|
|
||||||
|
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 "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "esp_netif_ppp.h"
|
||||||
|
#include "mqtt_client.h"
|
||||||
|
#include "esp_modem_api.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "iface_info.h"
|
||||||
|
|
||||||
|
struct ppp_info_t {
|
||||||
|
iface_info_t parent;
|
||||||
|
esp_modem_dce_t *dce;
|
||||||
|
bool stop_task;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int CONNECT_BIT = BIT0;
|
||||||
|
static const char *TAG = "pppos_connect";
|
||||||
|
static EventGroupHandle_t event_group = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "PPP state changed event %" PRIu32, event_id);
|
||||||
|
if (event_id == NETIF_PPP_ERRORUSER) {
|
||||||
|
struct ppp_info_t *ppp_info = arg;
|
||||||
|
esp_netif_t *netif = event_data;
|
||||||
|
ESP_LOGI(TAG, "User interrupted event from netif:%p", netif);
|
||||||
|
ppp_info->parent.connected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_ip_event(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "IP event! %" PRIu32, event_id);
|
||||||
|
struct ppp_info_t *ppp_info = arg;
|
||||||
|
|
||||||
|
if (event_id == IP_EVENT_PPP_GOT_IP) {
|
||||||
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||||
|
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
||||||
|
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
||||||
|
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
esp_netif_get_dns_info(ppp_info->parent.netif, i, &ppp_info->parent.dns[i]);
|
||||||
|
ESP_LOGI(TAG, "DNS %i:" IPSTR, i, IP2STR(&ppp_info->parent.dns[i].ip.u_addr.ip4));
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||||
|
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||||
|
ppp_info->parent.connected = true;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||||
|
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||||
|
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||||
|
ppp_info->parent.connected = false;
|
||||||
|
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||||
|
ESP_LOGI(TAG, "GOT IPv6 event!");
|
||||||
|
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
||||||
|
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void teardown_ppp(iface_info_t *info)
|
||||||
|
{
|
||||||
|
struct ppp_info_t *ppp_info = __containerof(info, struct ppp_info_t, parent);
|
||||||
|
|
||||||
|
esp_netif_action_disconnected(ppp_info->parent.netif, 0, 0, 0);
|
||||||
|
esp_netif_action_stop(ppp_info->parent.netif, 0, 0, 0);
|
||||||
|
esp_err_t err = esp_modem_set_mode(ppp_info->dce, ESP_MODEM_MODE_COMMAND);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_modem_set_mode(ESP_MODEM_MODE_COMMAND) failed with %d", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
esp_modem_destroy(ppp_info->dce);
|
||||||
|
vEventGroupDelete(event_group);
|
||||||
|
ppp_info->stop_task = true;
|
||||||
|
free(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppp_task(void *args)
|
||||||
|
{
|
||||||
|
struct ppp_info_t *ppp_info = args;
|
||||||
|
int backoff_time = 15000;
|
||||||
|
const int max_backoff = 60000;
|
||||||
|
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
|
||||||
|
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||||
|
dte_config.uart_config.tx_io_num = CONFIG_EXAMPLE_MODEM_UART_TX_PIN;
|
||||||
|
dte_config.uart_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
|
||||||
|
|
||||||
|
ppp_info->dce = esp_modem_new(&dte_config, &dce_config, ppp_info->parent.netif);
|
||||||
|
|
||||||
|
int rssi, ber;
|
||||||
|
esp_err_t ret = esp_modem_get_signal_quality(ppp_info->dce, &rssi, &ber);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_modem_get_signal_quality failed with %d %s", ret, esp_err_to_name(ret));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber);
|
||||||
|
ret = esp_modem_set_mode(ppp_info->dce, ESP_MODEM_MODE_DATA);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_modem_set_mode(ESP_MODEM_MODE_DATA) failed with %d", ret);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed:
|
||||||
|
|
||||||
|
#define CONTINUE_LATER() backoff_time *= 2; \
|
||||||
|
if (backoff_time > max_backoff) { backoff_time = max_backoff; } \
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// now let's keep retrying
|
||||||
|
while (!ppp_info->stop_task) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(backoff_time));
|
||||||
|
if (ppp_info->parent.connected) {
|
||||||
|
backoff_time = 5000;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// try if the modem got stuck in data mode
|
||||||
|
ESP_LOGI(TAG, "Trying to Sync with modem");
|
||||||
|
ret = esp_modem_sync(ppp_info->dce);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGI(TAG, "Switching to command mode");
|
||||||
|
esp_modem_set_mode(ppp_info->dce, ESP_MODEM_MODE_COMMAND);
|
||||||
|
ESP_LOGI(TAG, "Retry sync 3 times");
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
ret = esp_modem_sync(ppp_info->dce);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
CONTINUE_LATER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Manual hang-up before reconnecting");
|
||||||
|
ret = esp_modem_at(ppp_info->dce, "ATH", NULL, 2000);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
CONTINUE_LATER();
|
||||||
|
}
|
||||||
|
ret = esp_modem_get_signal_quality(ppp_info->dce, &rssi, &ber);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
CONTINUE_LATER();
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber);
|
||||||
|
ret = esp_modem_set_mode(ppp_info->dce, ESP_MODEM_MODE_DATA);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
CONTINUE_LATER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CONTINUE_LATER
|
||||||
|
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
iface_info_t *setup_ppp(int prio)
|
||||||
|
{
|
||||||
|
struct ppp_info_t *ppp_info = calloc(1, sizeof(struct ppp_info_t));
|
||||||
|
assert(ppp_info);
|
||||||
|
ppp_info->parent.teardown = teardown_ppp;
|
||||||
|
ppp_info->parent.name = "Modem";
|
||||||
|
event_group = xEventGroupCreate();
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event, ppp_info));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, ppp_info));
|
||||||
|
|
||||||
|
esp_netif_inherent_config_t base_netif_cfg = ESP_NETIF_INHERENT_DEFAULT_PPP();
|
||||||
|
base_netif_cfg.route_prio = prio;
|
||||||
|
esp_netif_config_t netif_ppp_config = { .base = &base_netif_cfg,
|
||||||
|
.stack = ESP_NETIF_NETSTACK_DEFAULT_PPP
|
||||||
|
};
|
||||||
|
|
||||||
|
ppp_info->parent.netif = esp_netif_new(&netif_ppp_config);
|
||||||
|
if (ppp_info->parent.netif == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (xTaskCreate(ppp_task, "ppp_retry_task", 4096, ppp_info, 5, NULL) != pdTRUE) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Waiting for IP address");
|
||||||
|
xEventGroupWaitBits(event_group, CONNECT_BIT, pdFALSE, pdFALSE, pdMS_TO_TICKS(10000));
|
||||||
|
|
||||||
|
return &ppp_info->parent;
|
||||||
|
|
||||||
|
err:
|
||||||
|
|
||||||
|
teardown_ppp(&ppp_info->parent);
|
||||||
|
return NULL;
|
||||||
|
}
|
128
examples/esp_netif/multiple_netifs/main/wifi_connect.c
Normal file
128
examples/esp_netif/multiple_netifs/main/wifi_connect.c
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
/* WiFi 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 "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "iface_info.h"
|
||||||
|
|
||||||
|
#define WIFI_CONNECTED_BIT BIT0
|
||||||
|
#define WIFI_FAIL_BIT BIT1
|
||||||
|
|
||||||
|
|
||||||
|
static const char *TAG = "wifi_connect";
|
||||||
|
static int s_retry_num = 0;
|
||||||
|
static EventGroupHandle_t s_wifi_event_group;
|
||||||
|
|
||||||
|
static void event_handler(void *args, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
struct iface_info_t *wifi_info = args;
|
||||||
|
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||||
|
esp_wifi_connect();
|
||||||
|
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||||
|
wifi_info->connected = false;
|
||||||
|
if (s_retry_num < CONFIG_ESP_MAXIMUM_RETRY || CONFIG_ESP_MAXIMUM_RETRY == 0) {
|
||||||
|
esp_wifi_connect();
|
||||||
|
s_retry_num++;
|
||||||
|
ESP_LOGI(TAG, "retry to connect to the AP");
|
||||||
|
} else {
|
||||||
|
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "connect to the AP fail");
|
||||||
|
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||||
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
|
||||||
|
const esp_netif_ip_info_t *ip_info = &event->ip_info;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "WiFi station Got IP Address");
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||||
|
ESP_LOGI(TAG, "IP:" IPSTR, IP2STR(&ip_info->ip));
|
||||||
|
ESP_LOGI(TAG, "MASK:" IPSTR, IP2STR(&ip_info->netmask));
|
||||||
|
ESP_LOGI(TAG, "GW:" IPSTR, IP2STR(&ip_info->gw));
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
esp_netif_get_dns_info(wifi_info->netif, i, &wifi_info->dns[i]);
|
||||||
|
ESP_LOGI(TAG, "DNS %i:" IPSTR, i, IP2STR(&wifi_info->dns[i].ip.u_addr.ip4));
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||||
|
s_retry_num = 0;
|
||||||
|
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||||
|
wifi_info->connected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void teardown_wifi(iface_info_t *info)
|
||||||
|
{
|
||||||
|
esp_netif_action_disconnected(info->netif, 0, 0, 0);
|
||||||
|
esp_netif_action_stop(info->netif, 0, 0, 0);
|
||||||
|
esp_wifi_stop();
|
||||||
|
esp_wifi_deinit();
|
||||||
|
free(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
iface_info_t *setup_wifi(int prio)
|
||||||
|
{
|
||||||
|
struct iface_info_t *wifi_info = malloc(sizeof(iface_info_t));
|
||||||
|
assert(wifi_info);
|
||||||
|
wifi_info->teardown = teardown_wifi;
|
||||||
|
wifi_info->name = "WiFi station";
|
||||||
|
s_wifi_event_group = xEventGroupCreate();
|
||||||
|
|
||||||
|
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
|
||||||
|
esp_netif_config.route_prio = prio;
|
||||||
|
wifi_info->netif = esp_netif_create_wifi(WIFI_IF_STA, &esp_netif_config);
|
||||||
|
esp_wifi_set_default_wifi_sta_handlers();
|
||||||
|
|
||||||
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler, wifi_info));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler, wifi_info));
|
||||||
|
|
||||||
|
wifi_config_t wifi_config = {
|
||||||
|
.sta = {
|
||||||
|
.ssid = CONFIG_ESP_WIFI_SSID,
|
||||||
|
.password = CONFIG_ESP_WIFI_PASSWORD,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
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_LOGI(TAG, "wifi_init_sta finished.");
|
||||||
|
|
||||||
|
/* Waiting until either the connection or a failure (connection failed or a timeout) */
|
||||||
|
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, (WIFI_CONNECTED_BIT | WIFI_FAIL_BIT), pdFALSE, pdFALSE, pdMS_TO_TICKS(5000));
|
||||||
|
|
||||||
|
if (bits & WIFI_CONNECTED_BIT) {
|
||||||
|
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
|
||||||
|
CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD);
|
||||||
|
} else if (bits & WIFI_FAIL_BIT) {
|
||||||
|
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
|
||||||
|
CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD);
|
||||||
|
teardown_wifi(wifi_info);
|
||||||
|
wifi_info = NULL;
|
||||||
|
} else if (CONFIG_ESP_MAXIMUM_RETRY == 0) {
|
||||||
|
ESP_LOGI(TAG, "No connection at the moment, will keep retrying...");
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Failed to connect withing specified timeout");
|
||||||
|
teardown_wifi(wifi_info);
|
||||||
|
wifi_info = NULL;
|
||||||
|
}
|
||||||
|
return wifi_info;
|
||||||
|
}
|
2
examples/esp_netif/multiple_netifs/sdkconfig.defaults
Normal file
2
examples/esp_netif/multiple_netifs/sdkconfig.defaults
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_LWIP_PPP_SUPPORT=y
|
||||||
|
CONFIG_LWIP_PPP_NOTIFY_PHASE_SUPPORT=y
|
Reference in New Issue
Block a user