mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-26 08:47:27 +02:00
Compare commits
11 Commits
modem-v1.0
...
mdns-v1.2.
Author | SHA1 | Date | |
---|---|---|---|
ecc465daa3 | |||
181b6e4013 | |||
40e3875f76 | |||
ddc3eb62d0 | |||
3625889049 | |||
2bd6163ec8 | |||
f1eb46580e | |||
1c20328dcf | |||
6de22f3893 | |||
e280b3b541 | |||
00d7c40848 |
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@ -8,7 +8,7 @@ body:
|
||||
label: Answers checklist.
|
||||
description: Before submitting a new issue, please follow the checklist and try to find the answer.
|
||||
options:
|
||||
- label: I have read the documentation for [esp-protocols components](https://espressif.github.io/esp-protocols/) and the issue is not addressed there.
|
||||
- label: I have read the documentation for esp-protocols [components](https://github.com/espressif/esp-protocols#readme) and the issue is not addressed there.
|
||||
required: true
|
||||
- label: I have updated my esp-protocols branch (master or release) to the latest version and checked that the issue is present there.
|
||||
required: true
|
||||
|
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,7 +1,7 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: esp-protocols documentation
|
||||
url: https://espressif.github.io/esp-protocols/
|
||||
- name: esp-protocols documentation links
|
||||
url: https://github.com/espressif/esp-protocols#readme
|
||||
about: Documenation for esp-protocols components.
|
||||
- name: ESP-IDF Programming Guide
|
||||
url: https://docs.espressif.com/projects/esp-idf/en/latest/
|
||||
|
2
.github/ISSUE_TEMPLATE/other-issue.yml
vendored
2
.github/ISSUE_TEMPLATE/other-issue.yml
vendored
@ -7,7 +7,7 @@ body:
|
||||
label: Answers checklist.
|
||||
description: Before submitting a new issue, please follow the checklist and try to find the answer.
|
||||
options:
|
||||
- label: I have read the documentation for [esp-protocols components](https://espressif.github.io/esp-protocols/) and the issue is not addressed there.
|
||||
- label: I have read the documentation for esp-protocols [components](https://github.com/espressif/esp-protocols#readme) and the issue is not addressed there.
|
||||
required: true
|
||||
- label: I have updated my esp-protocols branch (master or release) to the latest version and checked that the issue is present there.
|
||||
required: true
|
||||
|
48
.github/workflows/examples_build-host-test.yml
vendored
Normal file
48
.github/workflows/examples_build-host-test.yml
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
name: "examples: build/host-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
build_all_examples:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'examples') || github.event_name == 'push'
|
||||
name: Build examples
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.1"]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
python -m pip install idf-build-apps
|
||||
# Build default configs for all targets
|
||||
python ./ci/build_apps.py examples -m examples/.build-test-rules.yml -d -c
|
||||
|
||||
build_and_run_on_host:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'examples') || github.event_name == 'push'
|
||||
name: Build and run examples on linux
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
python -m pip install idf-build-apps
|
||||
python ./ci/build_apps.py examples/mqtt -l -t linux
|
||||
timeout 5 ./examples/mqtt/build_linux_default/esp_mqtt_demo.elf | tee test.log || true
|
||||
grep 'MQTT_EVENT_DATA' test.log
|
@ -26,20 +26,29 @@ if __name__ == '__main__':
|
||||
parser.add_argument('-r', '--rules', nargs='*', default=['sdkconfig.ci=default', 'sdkconfig.ci.*=', '=default'], help='Rules how to treat configs')
|
||||
parser.add_argument('-m', '--manifests', nargs='*', default=[], help='list of manifest files')
|
||||
parser.add_argument('-d', '--delete', action='store_true', help='Delete build artifacts')
|
||||
parser.add_argument('-c', '--recursive', action='store_true', help='Build recursively')
|
||||
parser.add_argument('-l', '--linux', action='store_true', help='Include linux build (dont check warnings)')
|
||||
args = parser.parse_args()
|
||||
|
||||
IDF_PATH = os.environ['IDF_PATH']
|
||||
|
||||
print(args.paths)
|
||||
# Compose the ignore warning strings from the global list and from the environment
|
||||
ignore_warning_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),'ignore_build_warnings.txt')
|
||||
ignore_warning = open(ignore_warning_file).read().rstrip('\n').split('\n')
|
||||
if 'EXPECTED_WARNING' in os.environ:
|
||||
ignore_warning += os.environ['EXPECTED_WARNING'].split('\n')
|
||||
if args.linux:
|
||||
SUPPORTED_TARGETS.append('linux')
|
||||
ignore_warning = 'warning: ' # Ignore all common warnings on linux builds
|
||||
setup_logging(2)
|
||||
apps = find_apps(
|
||||
args.paths,
|
||||
recursive=False,
|
||||
recursive=args.recursive,
|
||||
target=args.target,
|
||||
build_dir='build_@t_@w',
|
||||
config_rules_str=args.rules,
|
||||
build_log_path='build_log.txt',
|
||||
size_json_path='size.json',
|
||||
size_json_path='size.json' if not args.linux else None,
|
||||
check_warnings=True,
|
||||
preserve=not args.delete,
|
||||
manifest_files=args.manifests,
|
||||
@ -54,5 +63,5 @@ if __name__ == '__main__':
|
||||
build_apps(apps,
|
||||
dry_run=False,
|
||||
keep_going=False,
|
||||
ignore_warning_strs=os.environ['EXPECTED_WARNING']
|
||||
if 'EXPECTED_WARNING' in os.environ else None))
|
||||
ignore_warning_strs=ignore_warning)
|
||||
)
|
||||
|
1
ci/ignore_build_warnings.txt
Normal file
1
ci/ignore_build_warnings.txt
Normal file
@ -0,0 +1 @@
|
||||
DeprecationWarning: pkg_resources is deprecated as an API
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(mdns): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py mdns
|
||||
tag_format: mdns-v$version
|
||||
version: 1.1.0
|
||||
version: 1.2.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,24 @@
|
||||
# Changelog
|
||||
|
||||
## [1.2.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.2.0)
|
||||
|
||||
### Features
|
||||
|
||||
- add an API for setting address to a delegated host ([ddc3eb6](https://github.com/espressif/esp-protocols/commit/ddc3eb6))
|
||||
- Add support for lwip build under linux ([588465d](https://github.com/espressif/esp-protocols/commit/588465d))
|
||||
- Allow for adding a delegated host with no address ([c562461](https://github.com/espressif/esp-protocols/commit/c562461))
|
||||
- Add APIs for looking up self hosted services and getting the self hostname ([f0df12d](https://github.com/espressif/esp-protocols/commit/f0df12d))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Refactor freertos linux compat layers ([79a0e57](https://github.com/espressif/esp-protocols/commit/79a0e57))
|
||||
- Fix delegated service PTR response ([cab0e1d](https://github.com/espressif/esp-protocols/commit/cab0e1d))
|
||||
- Added unit tests to CI + minor fix to pass it ([c974c14](https://github.com/espressif/esp-protocols/commit/c974c14))
|
||||
|
||||
### Updated
|
||||
|
||||
- docs: update documentation links ([4de5298](https://github.com/espressif/esp-protocols/commit/4de5298))
|
||||
|
||||
## [1.1.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.1.0)
|
||||
|
||||
### Features
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: "1.1.0"
|
||||
version: "1.2.0"
|
||||
description: mDNS
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/mdns
|
||||
dependencies:
|
||||
|
@ -158,6 +158,21 @@ esp_err_t mdns_hostname_get(char *hostname);
|
||||
*/
|
||||
esp_err_t mdns_delegate_hostname_add(const char *hostname, const mdns_ip_addr_t *address_list);
|
||||
|
||||
/**
|
||||
* @brief Set the address to a delegated hostname
|
||||
*
|
||||
* @param hostname Hostname to set
|
||||
* @param address_list The IP address list of the host
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_STATE mDNS is not running
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_NO_MEM memory error
|
||||
*
|
||||
*/
|
||||
esp_err_t mdns_delegate_hostname_set_address(const char *hostname, const mdns_ip_addr_t *address_list);
|
||||
|
||||
/**
|
||||
* @brief Remove a delegated hostname
|
||||
* All the services added to this host will also be removed.
|
||||
|
@ -2993,6 +2993,27 @@ static void free_address_list(mdns_ip_addr_t *address_list)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool _mdns_delegate_hostname_set_address(const char *hostname, mdns_ip_addr_t *address_list)
|
||||
{
|
||||
if (!_str_null_or_empty(_mdns_server->hostname) &&
|
||||
strcasecmp(hostname, _mdns_server->hostname) == 0) {
|
||||
return false;
|
||||
}
|
||||
mdns_host_item_t *host = _mdns_host_list;
|
||||
while (host != NULL) {
|
||||
if (strcasecmp(hostname, host->hostname) == 0) {
|
||||
// free previous address list
|
||||
free_address_list(host->address_list);
|
||||
// set current address list to the host
|
||||
host->address_list = address_list;
|
||||
return true;
|
||||
}
|
||||
host = host->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list)
|
||||
{
|
||||
mdns_ip_addr_t *head = NULL;
|
||||
@ -4845,6 +4866,7 @@ static void _mdns_free_action(mdns_action_t *action)
|
||||
case ACTION_RX_HANDLE:
|
||||
_mdns_packet_free(action->data.rx_handle.packet);
|
||||
break;
|
||||
case ACTION_DELEGATE_HOSTNAME_SET_ADDR:
|
||||
case ACTION_DELEGATE_HOSTNAME_ADD:
|
||||
free((char *)action->data.delegate_hostname.hostname);
|
||||
free_address_list(action->data.delegate_hostname.address_list);
|
||||
@ -5065,6 +5087,13 @@ static void _mdns_execute_action(mdns_action_t *action)
|
||||
free_address_list(action->data.delegate_hostname.address_list);
|
||||
}
|
||||
break;
|
||||
case ACTION_DELEGATE_HOSTNAME_SET_ADDR:
|
||||
if (!_mdns_delegate_hostname_set_address(action->data.delegate_hostname.hostname,
|
||||
action->data.delegate_hostname.address_list)) {
|
||||
free_address_list(action->data.delegate_hostname.address_list);
|
||||
}
|
||||
free((char *)action->data.delegate_hostname.hostname);
|
||||
break;
|
||||
case ACTION_DELEGATE_HOSTNAME_REMOVE:
|
||||
_mdns_delegate_hostname_remove(action->data.delegate_hostname.hostname);
|
||||
free((char *)action->data.delegate_hostname.hostname);
|
||||
@ -5634,6 +5663,36 @@ esp_err_t mdns_delegate_hostname_remove(const char *hostname)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t mdns_delegate_hostname_set_address(const char *hostname, const mdns_ip_addr_t *address_list)
|
||||
{
|
||||
if (!_mdns_server) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
char *new_hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1);
|
||||
if (!new_hostname) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
mdns_action_t *action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
|
||||
if (!action) {
|
||||
HOOK_MALLOC_FAILED;
|
||||
free(new_hostname);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
action->type = ACTION_DELEGATE_HOSTNAME_SET_ADDR;
|
||||
action->data.delegate_hostname.hostname = new_hostname;
|
||||
action->data.delegate_hostname.address_list = copy_address_list(address_list);
|
||||
if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) {
|
||||
free(new_hostname);
|
||||
free(action);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool mdns_hostname_exists(const char *hostname)
|
||||
{
|
||||
return _hostname_is_ours(hostname);
|
||||
|
@ -196,6 +196,7 @@ typedef enum {
|
||||
ACTION_TASK_STOP,
|
||||
ACTION_DELEGATE_HOSTNAME_ADD,
|
||||
ACTION_DELEGATE_HOSTNAME_REMOVE,
|
||||
ACTION_DELEGATE_HOSTNAME_SET_ADDR,
|
||||
ACTION_MAX
|
||||
} mdns_action_type_t;
|
||||
|
||||
|
3
examples/.build-test-rules.yml
Normal file
3
examples/.build-test-rules.yml
Normal file
@ -0,0 +1,3 @@
|
||||
examples/esp_netif/multiple_netifs:
|
||||
disable:
|
||||
- if: IDF_TARGET != "esp32"
|
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.
|
13
examples/esp_netif/multiple_netifs/main/CMakeLists.txt
Normal file
13
examples/esp_netif/multiple_netifs/main/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
set(ppp_connect_srcs ppp_connect.c)
|
||||
if(CONFIG_EXAMPLE_PPP_CONNECT_ESP_MODEM)
|
||||
list(APPEND ppp_connect_srcs ppp_connect_esp_modem.c)
|
||||
else()
|
||||
list(APPEND ppp_connect_srcs ppp_connect_simple.c)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS multi_netif_main.c
|
||||
check_connection.c
|
||||
wifi_connect.c
|
||||
ethernet_connect.c
|
||||
${ppp_connect_srcs}
|
||||
INCLUDE_DIRS ".")
|
57
examples/esp_netif/multiple_netifs/main/Kconfig.projbuild
Normal file
57
examples/esp_netif/multiple_netifs/main/Kconfig.projbuild
Normal file
@ -0,0 +1,57 @@
|
||||
menu "Example 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_PPP_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 15
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_PPP_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 14
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
choice EXAMPLE_PPP_CONNECT
|
||||
prompt "Connect to PPP server"
|
||||
default EXAMPLE_PPP_CONNECT_ESP_MODEM
|
||||
help
|
||||
Choose modem interface library.
|
||||
We use esp_modem by default, but in some
|
||||
simple cases (and a very constrained environment)
|
||||
we could simply connect UART directly to lwIP.
|
||||
To experiment with this option, choose EXAMPLE_PPP_CONNECT_SIMPLE
|
||||
|
||||
config EXAMPLE_PPP_CONNECT_ESP_MODEM
|
||||
bool "Using esp_modem library"
|
||||
config EXAMPLE_PPP_CONNECT_SIMPLE
|
||||
bool "Using simple UART-PPP driver"
|
||||
endchoice
|
||||
|
||||
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_connect.c
Normal file
137
examples/esp_netif/multiple_netifs/main/ethernet_connect.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 eth_destroy(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 *eth_init(int prio)
|
||||
{
|
||||
struct eth_info_t *eth_info = malloc(sizeof(struct eth_info_t));
|
||||
assert(eth_info);
|
||||
eth_info->parent.destroy = eth_destroy;
|
||||
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 (*destroy)(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 *eth_init(int prio);
|
||||
iface_info_t *wifi_init(int prio);
|
||||
iface_info_t *ppp_init(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[] = {
|
||||
eth_init(ETH_PRIO),
|
||||
wifi_init(WIFI_PRIO),
|
||||
ppp_init(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]->destroy(ifaces[i]);
|
||||
}
|
||||
}
|
||||
}
|
123
examples/esp_netif/multiple_netifs/main/ppp_connect.c
Normal file
123
examples/esp_netif/multiple_netifs/main/ppp_connect.c
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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_log.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "iface_info.h"
|
||||
#include "ppp_connect.h"
|
||||
|
||||
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 ppp_destroy(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);
|
||||
ppp_destroy_context(ppp_info);
|
||||
vEventGroupDelete(event_group);
|
||||
ppp_info->stop_task = true;
|
||||
free(info);
|
||||
}
|
||||
|
||||
iface_info_t *init_ppp(int prio)
|
||||
{
|
||||
struct ppp_info_t *ppp_info = calloc(1, sizeof(struct ppp_info_t));
|
||||
assert(ppp_info);
|
||||
ppp_info->parent.destroy = ppp_destroy;
|
||||
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,
|
||||
.driver = ppp_driver_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:
|
||||
|
||||
ppp_destroy(&ppp_info->parent);
|
||||
return NULL;
|
||||
}
|
18
examples/esp_netif/multiple_netifs/main/ppp_connect.h
Normal file
18
examples/esp_netif/multiple_netifs/main/ppp_connect.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
struct ppp_info_t {
|
||||
iface_info_t parent;
|
||||
void *context;
|
||||
bool stop_task;
|
||||
};
|
||||
|
||||
extern const esp_netif_driver_ifconfig_t *ppp_driver_cfg;
|
||||
|
||||
void ppp_task(void *args);
|
||||
|
||||
void ppp_destroy_context(struct ppp_info_t *ppp_info);
|
109
examples/esp_netif/multiple_netifs/main/ppp_connect_esp_modem.c
Normal file
109
examples/esp_netif/multiple_netifs/main/ppp_connect_esp_modem.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#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"
|
||||
#include "ppp_connect.h"
|
||||
|
||||
static const char *TAG = "ppp_esp_modem";
|
||||
|
||||
const esp_netif_driver_ifconfig_t *ppp_driver_cfg = NULL;
|
||||
|
||||
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_PPP_UART_TX_PIN;
|
||||
dte_config.uart_config.rx_io_num = CONFIG_EXAMPLE_PPP_UART_RX_PIN;
|
||||
|
||||
esp_modem_dce_t *dce = esp_modem_new(&dte_config, &dce_config, ppp_info->parent.netif);
|
||||
ppp_info->context = dce;
|
||||
|
||||
int rssi, ber;
|
||||
esp_err_t ret = esp_modem_get_signal_quality(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(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(dce);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGI(TAG, "Switching to command mode");
|
||||
esp_modem_set_mode(dce, ESP_MODEM_MODE_COMMAND);
|
||||
ESP_LOGI(TAG, "Retry sync 3 times");
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
ret = esp_modem_sync(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(dce, "ATH", NULL, 2000);
|
||||
if (ret != ESP_OK) {
|
||||
CONTINUE_LATER();
|
||||
}
|
||||
ret = esp_modem_get_signal_quality(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(dce, ESP_MODEM_MODE_DATA);
|
||||
if (ret != ESP_OK) {
|
||||
CONTINUE_LATER();
|
||||
}
|
||||
}
|
||||
|
||||
#undef CONTINUE_LATER
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void ppp_destroy_context(struct ppp_info_t *ppp_info)
|
||||
{
|
||||
esp_modem_dce_t *dce = ppp_info->context;
|
||||
esp_err_t err = esp_modem_set_mode(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(dce);
|
||||
}
|
122
examples/esp_netif/multiple_netifs/main/ppp_connect_simple.c
Normal file
122
examples/esp_netif/multiple_netifs/main/ppp_connect_simple.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "esp_netif.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_event.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "iface_info.h"
|
||||
#include "ppp_connect.h"
|
||||
#include "driver/uart.h"
|
||||
|
||||
static const char *TAG = "ppp_connect_simple";
|
||||
|
||||
static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||
{
|
||||
ESP_LOG_BUFFER_HEXDUMP("ppp_connect_tx", buffer, len, ESP_LOG_VERBOSE);
|
||||
uart_write_bytes(UART_NUM_1, buffer, len);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_netif_driver_ifconfig_t driver_cfg = {
|
||||
.handle = (void *)1, // singleton driver, just to != NULL
|
||||
.transmit = transmit,
|
||||
};
|
||||
|
||||
const esp_netif_driver_ifconfig_t *ppp_driver_cfg = &driver_cfg;
|
||||
|
||||
#define BUF_SIZE (1024)
|
||||
#define CONNECTED "CONNECT 115200"
|
||||
|
||||
void ppp_task(void *args)
|
||||
{
|
||||
struct ppp_info_t *ppp_info = args;
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = 115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
|
||||
QueueHandle_t event_queue;
|
||||
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, BUF_SIZE, 0, 16, &event_queue, 0));
|
||||
ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &uart_config));
|
||||
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, CONFIG_EXAMPLE_PPP_UART_TX_PIN, CONFIG_EXAMPLE_PPP_UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
ESP_ERROR_CHECK(uart_set_rx_timeout(UART_NUM_1, 1));
|
||||
|
||||
char *buffer = malloc(BUF_SIZE);
|
||||
ppp_info->context = buffer;
|
||||
const struct seq_t {
|
||||
const char *cmd;
|
||||
const char *expect;
|
||||
bool allow_fail;
|
||||
} init_sequence[] = {
|
||||
{ .cmd = "AT\r\n", .expect = "OK" },
|
||||
{ .cmd = "AT+CGDCONT=1,\"IP\",\"" CONFIG_EXAMPLE_MODEM_PPP_APN "\"\r\n", .expect = "OK" },
|
||||
{ .cmd = "ATD*99##\r\n", .expect = "CONNECT", .allow_fail = true },
|
||||
{ .cmd = "ATO\r\n", .expect = "CONNECT" },
|
||||
};
|
||||
int cmd_i = 0;
|
||||
int retry = 0;
|
||||
char *reply = buffer;
|
||||
const int max_retries = 3;
|
||||
uart_event_t event;
|
||||
uart_write_bytes(UART_NUM_1, "+++", 3);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
while (retry < max_retries) {
|
||||
ESP_LOGD(TAG, "Sending command: %s", init_sequence[cmd_i].cmd);
|
||||
uart_write_bytes(UART_NUM_1, init_sequence[cmd_i].cmd, strlen(init_sequence[cmd_i].cmd));
|
||||
xQueueReceive(event_queue, &event, pdMS_TO_TICKS(pdMS_TO_TICKS(1000)));
|
||||
size_t len;
|
||||
uart_get_buffered_data_len(UART_NUM_1, &len);
|
||||
if (!len) {
|
||||
continue;
|
||||
}
|
||||
len = uart_read_bytes(UART_NUM_1, reply, BUF_SIZE, 0);
|
||||
ESP_LOGD(TAG, "Received: %.*s", len, reply);
|
||||
if (strstr(reply, init_sequence[cmd_i].expect) || init_sequence[cmd_i].allow_fail) {
|
||||
if (strstr(reply, CONNECTED)) { // are we connected already?
|
||||
break;
|
||||
}
|
||||
cmd_i++;
|
||||
continue;
|
||||
}
|
||||
++retry;
|
||||
vTaskDelay(pdMS_TO_TICKS(retry * 1000));
|
||||
}
|
||||
if (retry >= max_retries) {
|
||||
ESP_LOGE(TAG, "Failed to perform initial modem connection");
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
ESP_LOGI(TAG, "Modem configured correctly, switching to PPP protocol");
|
||||
esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected, ppp_info->parent.netif);
|
||||
esp_netif_action_start(ppp_info->parent.netif, 0, 0, 0);
|
||||
while (!ppp_info->stop_task) {
|
||||
xQueueReceive(event_queue, &event, pdMS_TO_TICKS(pdMS_TO_TICKS(1000)));
|
||||
if (event.type == UART_DATA) {
|
||||
size_t len;
|
||||
uart_get_buffered_data_len(UART_NUM_1, &len);
|
||||
if (len) {
|
||||
len = uart_read_bytes(UART_NUM_1, buffer, BUF_SIZE, 0);
|
||||
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_recv", buffer, len, ESP_LOG_VERBOSE);
|
||||
esp_netif_receive(ppp_info->parent.netif, buffer, len, NULL);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Received UART event: %d", event.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppp_destroy_context(struct ppp_info_t *ppp_info)
|
||||
{
|
||||
char *buffer = ppp_info->context;
|
||||
ppp_info->stop_task = true;
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
free(buffer);
|
||||
uart_driver_delete(UART_NUM_1);
|
||||
}
|
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 wifi_destroy(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 *wifi_init(int prio)
|
||||
{
|
||||
struct iface_info_t *wifi_info = malloc(sizeof(iface_info_t));
|
||||
assert(wifi_info);
|
||||
wifi_info->destroy = wifi_destroy;
|
||||
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);
|
||||
wifi_destroy(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");
|
||||
wifi_destroy(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
|
@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16)
|
||||
# For ESP32 platform target
|
||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
||||
|
||||
if(${IDF_TARGET} STREQUAL "linux")
|
||||
if("${IDF_TARGET}" STREQUAL "linux")
|
||||
# For linux-target we have two options:
|
||||
# - With lwIP (must be defined on command line, e.g. idf.py -DWITH_LWIP=1)
|
||||
# access networking from linux `tap` interface (TAP networking mode)
|
||||
|
@ -1,2 +0,0 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
# CONFIG_ESP_EVENT_POST_FROM_ISR is not set
|
||||
|
3
examples/mqtt/sdkconfig.defaults.esp32h2
Normal file
3
examples/mqtt/sdkconfig.defaults.esp32h2
Normal file
@ -0,0 +1,3 @@
|
||||
CONFIG_IDF_TARGET="esp32h2"
|
||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
2
examples/mqtt/sdkconfig.defaults.linux
Normal file
2
examples/mqtt/sdkconfig.defaults.linux
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
# CONFIG_ESP_EVENT_POST_FROM_ISR is not set
|
Reference in New Issue
Block a user