From 00d7c408489a6cca973376b637c71d786724d9b9 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 26 Apr 2023 19:10:16 +0200 Subject: [PATCH 1/4] feat(examples): Add multiple netif demo: eth+wifi+PPP --- .../esp_netif/multiple_netifs/CMakeLists.txt | 6 + examples/esp_netif/multiple_netifs/README.md | 25 +++ .../multiple_netifs/main/CMakeLists.txt | 2 + .../multiple_netifs/main/Kconfig.projbuild | 42 ++++ .../multiple_netifs/main/check_connection.c | 113 ++++++++++ .../multiple_netifs/main/ethernet_netif.c | 137 ++++++++++++ .../multiple_netifs/main/idf_component.yml | 4 + .../multiple_netifs/main/iface_info.h | 26 +++ .../multiple_netifs/main/multi_netif_main.c | 129 +++++++++++ .../multiple_netifs/main/ppp_connect.c | 210 ++++++++++++++++++ .../multiple_netifs/main/wifi_connect.c | 128 +++++++++++ .../multiple_netifs/sdkconfig.defaults | 2 + 12 files changed, 824 insertions(+) create mode 100644 examples/esp_netif/multiple_netifs/CMakeLists.txt create mode 100644 examples/esp_netif/multiple_netifs/README.md create mode 100644 examples/esp_netif/multiple_netifs/main/CMakeLists.txt create mode 100644 examples/esp_netif/multiple_netifs/main/Kconfig.projbuild create mode 100644 examples/esp_netif/multiple_netifs/main/check_connection.c create mode 100644 examples/esp_netif/multiple_netifs/main/ethernet_netif.c create mode 100644 examples/esp_netif/multiple_netifs/main/idf_component.yml create mode 100644 examples/esp_netif/multiple_netifs/main/iface_info.h create mode 100644 examples/esp_netif/multiple_netifs/main/multi_netif_main.c create mode 100644 examples/esp_netif/multiple_netifs/main/ppp_connect.c create mode 100644 examples/esp_netif/multiple_netifs/main/wifi_connect.c create mode 100644 examples/esp_netif/multiple_netifs/sdkconfig.defaults diff --git a/examples/esp_netif/multiple_netifs/CMakeLists.txt b/examples/esp_netif/multiple_netifs/CMakeLists.txt new file mode 100644 index 000000000..3d86dc916 --- /dev/null +++ b/examples/esp_netif/multiple_netifs/CMakeLists.txt @@ -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) diff --git a/examples/esp_netif/multiple_netifs/README.md b/examples/esp_netif/multiple_netifs/README.md new file mode 100644 index 000000000..09ba1a1b9 --- /dev/null +++ b/examples/esp_netif/multiple_netifs/README.md @@ -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. diff --git a/examples/esp_netif/multiple_netifs/main/CMakeLists.txt b/examples/esp_netif/multiple_netifs/main/CMakeLists.txt new file mode 100644 index 000000000..1d2d3000b --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/CMakeLists.txt @@ -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 ".") diff --git a/examples/esp_netif/multiple_netifs/main/Kconfig.projbuild b/examples/esp_netif/multiple_netifs/main/Kconfig.projbuild new file mode 100644 index 000000000..7ad68cf71 --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/Kconfig.projbuild @@ -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 diff --git a/examples/esp_netif/multiple_netifs/main/check_connection.c b/examples/esp_netif/multiple_netifs/main/check_connection.c new file mode 100644 index 000000000..64c2e21ca --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/check_connection.c @@ -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; +} diff --git a/examples/esp_netif/multiple_netifs/main/ethernet_netif.c b/examples/esp_netif/multiple_netifs/main/ethernet_netif.c new file mode 100644 index 000000000..2b6276e2a --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/ethernet_netif.c @@ -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 +#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; +} diff --git a/examples/esp_netif/multiple_netifs/main/idf_component.yml b/examples/esp_netif/multiple_netifs/main/idf_component.yml new file mode 100644 index 000000000..186d064b4 --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/idf_component.yml @@ -0,0 +1,4 @@ +dependencies: + espressif/esp_modem: + version: "^1.0.0" + override_path: "../../../../components/esp_modem" diff --git a/examples/esp_netif/multiple_netifs/main/iface_info.h b/examples/esp_netif/multiple_netifs/main/iface_info.h new file mode 100644 index 000000000..d3457eb9e --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/iface_info.h @@ -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; diff --git a/examples/esp_netif/multiple_netifs/main/multi_netif_main.c b/examples/esp_netif/multiple_netifs/main/multi_netif_main.c new file mode 100644 index 000000000..32be8b91b --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/multi_netif_main.c @@ -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 +#include +#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]); + } + } +} diff --git a/examples/esp_netif/multiple_netifs/main/ppp_connect.c b/examples/esp_netif/multiple_netifs/main/ppp_connect.c new file mode 100644 index 000000000..e1f4c1b43 --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/ppp_connect.c @@ -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 +#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; +} diff --git a/examples/esp_netif/multiple_netifs/main/wifi_connect.c b/examples/esp_netif/multiple_netifs/main/wifi_connect.c new file mode 100644 index 000000000..31f3a587d --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/wifi_connect.c @@ -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 +#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; +} diff --git a/examples/esp_netif/multiple_netifs/sdkconfig.defaults b/examples/esp_netif/multiple_netifs/sdkconfig.defaults new file mode 100644 index 000000000..3c08a9a30 --- /dev/null +++ b/examples/esp_netif/multiple_netifs/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_LWIP_PPP_SUPPORT=y +CONFIG_LWIP_PPP_NOTIFY_PHASE_SUPPORT=y From 1c20328dcf9922521d11c01188fb802a9e459074 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 22 Jun 2023 17:27:16 +0200 Subject: [PATCH 2/4] feat(examples): Support simple PPP connect in multinet example --- .../multiple_netifs/main/CMakeLists.txt | 13 +- .../multiple_netifs/main/Kconfig.projbuild | 21 ++- .../{ethernet_netif.c => ethernet_connect.c} | 6 +- .../multiple_netifs/main/iface_info.h | 2 +- .../multiple_netifs/main/multi_netif_main.c | 14 +- .../multiple_netifs/main/ppp_connect.c | 101 +-------------- .../multiple_netifs/main/ppp_connect.h | 18 +++ .../main/ppp_connect_esp_modem.c | 109 ++++++++++++++++ .../multiple_netifs/main/ppp_connect_simple.c | 122 ++++++++++++++++++ .../multiple_netifs/main/wifi_connect.c | 10 +- 10 files changed, 302 insertions(+), 114 deletions(-) rename examples/esp_netif/multiple_netifs/main/{ethernet_netif.c => ethernet_connect.c} (97%) create mode 100644 examples/esp_netif/multiple_netifs/main/ppp_connect.h create mode 100644 examples/esp_netif/multiple_netifs/main/ppp_connect_esp_modem.c create mode 100644 examples/esp_netif/multiple_netifs/main/ppp_connect_simple.c diff --git a/examples/esp_netif/multiple_netifs/main/CMakeLists.txt b/examples/esp_netif/multiple_netifs/main/CMakeLists.txt index 1d2d3000b..db05dfb88 100644 --- a/examples/esp_netif/multiple_netifs/main/CMakeLists.txt +++ b/examples/esp_netif/multiple_netifs/main/CMakeLists.txt @@ -1,2 +1,13 @@ -idf_component_register(SRCS ethernet_netif.c multi_netif_main.c wifi_connect.c check_connection.c ppp_connect.c +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 ".") diff --git a/examples/esp_netif/multiple_netifs/main/Kconfig.projbuild b/examples/esp_netif/multiple_netifs/main/Kconfig.projbuild index 7ad68cf71..c038535a6 100644 --- a/examples/esp_netif/multiple_netifs/main/Kconfig.projbuild +++ b/examples/esp_netif/multiple_netifs/main/Kconfig.projbuild @@ -1,4 +1,4 @@ -menu "Connection Configuration" +menu "Example Configuration" config ESP_WIFI_SSID string "WiFi SSID" @@ -24,19 +24,34 @@ menu "Connection Configuration" help Set APN (Access Point Name), a logical name to choose data network - config EXAMPLE_MODEM_UART_TX_PIN + config EXAMPLE_PPP_UART_TX_PIN int "TXD Pin Number" default 15 range 0 31 help Pin number of UART TX. - config EXAMPLE_MODEM_UART_RX_PIN + 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 diff --git a/examples/esp_netif/multiple_netifs/main/ethernet_netif.c b/examples/esp_netif/multiple_netifs/main/ethernet_connect.c similarity index 97% rename from examples/esp_netif/multiple_netifs/main/ethernet_netif.c rename to examples/esp_netif/multiple_netifs/main/ethernet_connect.c index 2b6276e2a..53ec398f5 100644 --- a/examples/esp_netif/multiple_netifs/main/ethernet_netif.c +++ b/examples/esp_netif/multiple_netifs/main/ethernet_connect.c @@ -82,7 +82,7 @@ static void got_ip_event_handler(void *args, esp_event_base_t event_base, } -static void teardown_eth(iface_info_t *info) +static void eth_destroy(iface_info_t *info) { struct eth_info_t *eth_info = __containerof(info, struct eth_info_t, parent); @@ -95,11 +95,11 @@ static void teardown_eth(iface_info_t *info) free(eth_info); } -iface_info_t *setup_eth(int prio) +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.teardown = teardown_eth; + eth_info->parent.destroy = eth_destroy; eth_info->parent.name = "Ethernet"; // Init common MAC and PHY configs to default diff --git a/examples/esp_netif/multiple_netifs/main/iface_info.h b/examples/esp_netif/multiple_netifs/main/iface_info.h index d3457eb9e..faa94b53f 100644 --- a/examples/esp_netif/multiple_netifs/main/iface_info.h +++ b/examples/esp_netif/multiple_netifs/main/iface_info.h @@ -18,7 +18,7 @@ struct iface_info_t { esp_netif_t *netif; esp_netif_dns_info_t dns[2]; - void (*teardown)(struct iface_info_t *); + void (*destroy)(struct iface_info_t *); const char *name; bool connected; }; diff --git a/examples/esp_netif/multiple_netifs/main/multi_netif_main.c b/examples/esp_netif/multiple_netifs/main/multi_netif_main.c index 32be8b91b..26f8dab44 100644 --- a/examples/esp_netif/multiple_netifs/main/multi_netif_main.c +++ b/examples/esp_netif/multiple_netifs/main/multi_netif_main.c @@ -23,9 +23,9 @@ #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); +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" @@ -69,9 +69,9 @@ void app_main(void) // all interfaces iface_info_t *ifaces[] = { - setup_eth(ETH_PRIO), - setup_wifi(WIFI_PRIO), - setup_ppp(PPP_PRIO), + eth_init(ETH_PRIO), + wifi_init(WIFI_PRIO), + ppp_init(PPP_PRIO), }; size_t num_of_ifaces = sizeof(ifaces) / sizeof(ifaces[0]); @@ -123,7 +123,7 @@ void app_main(void) 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]); + ifaces[i]->destroy(ifaces[i]); } } } diff --git a/examples/esp_netif/multiple_netifs/main/ppp_connect.c b/examples/esp_netif/multiple_netifs/main/ppp_connect.c index e1f4c1b43..b1f2dcf05 100644 --- a/examples/esp_netif/multiple_netifs/main/ppp_connect.c +++ b/examples/esp_netif/multiple_netifs/main/ppp_connect.c @@ -17,16 +17,10 @@ #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; -}; +#include "ppp_connect.h" static const int CONNECT_BIT = BIT0; static const char *TAG = "pppos_connect"; @@ -79,105 +73,23 @@ static void on_ip_event(void *arg, esp_event_base_t event_base, } -static void teardown_ppp(iface_info_t *info) +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); - 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); + ppp_destroy_context(ppp_info); 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) +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.teardown = teardown_ppp; + ppp_info->parent.destroy = ppp_destroy; ppp_info->parent.name = "Modem"; event_group = xEventGroupCreate(); @@ -187,6 +99,7 @@ iface_info_t *setup_ppp(int prio) 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 }; @@ -205,6 +118,6 @@ iface_info_t *setup_ppp(int prio) err: - teardown_ppp(&ppp_info->parent); + ppp_destroy(&ppp_info->parent); return NULL; } diff --git a/examples/esp_netif/multiple_netifs/main/ppp_connect.h b/examples/esp_netif/multiple_netifs/main/ppp_connect.h new file mode 100644 index 000000000..212e60848 --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/ppp_connect.h @@ -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); diff --git a/examples/esp_netif/multiple_netifs/main/ppp_connect_esp_modem.c b/examples/esp_netif/multiple_netifs/main/ppp_connect_esp_modem.c new file mode 100644 index 000000000..f62bd643d --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/ppp_connect_esp_modem.c @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#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); +} diff --git a/examples/esp_netif/multiple_netifs/main/ppp_connect_simple.c b/examples/esp_netif/multiple_netifs/main/ppp_connect_simple.c new file mode 100644 index 000000000..4e8ebe2bf --- /dev/null +++ b/examples/esp_netif/multiple_netifs/main/ppp_connect_simple.c @@ -0,0 +1,122 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#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); +} diff --git a/examples/esp_netif/multiple_netifs/main/wifi_connect.c b/examples/esp_netif/multiple_netifs/main/wifi_connect.c index 31f3a587d..523c77356 100644 --- a/examples/esp_netif/multiple_netifs/main/wifi_connect.c +++ b/examples/esp_netif/multiple_netifs/main/wifi_connect.c @@ -66,7 +66,7 @@ static void event_handler(void *args, esp_event_base_t event_base, } } -static void teardown_wifi(iface_info_t *info) +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); @@ -75,11 +75,11 @@ static void teardown_wifi(iface_info_t *info) free(info); } -iface_info_t *setup_wifi(int prio) +iface_info_t *wifi_init(int prio) { struct iface_info_t *wifi_info = malloc(sizeof(iface_info_t)); assert(wifi_info); - wifi_info->teardown = teardown_wifi; + wifi_info->destroy = wifi_destroy; wifi_info->name = "WiFi station"; s_wifi_event_group = xEventGroupCreate(); @@ -115,13 +115,13 @@ iface_info_t *setup_wifi(int prio) } 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_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"); - teardown_wifi(wifi_info); + wifi_destroy(wifi_info); wifi_info = NULL; } return wifi_info; From f1eb46580ef37f9976278b51e4c0f4fcd4093407 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 22 Jun 2023 19:37:23 +0200 Subject: [PATCH 3/4] feat(examples): Add build/host tests to examples --- .../workflows/examples_build-host-test.yml | 48 +++++++++++++++++++ ci/build_apps.py | 15 ++++-- examples/.build-test-rules.yml | 3 ++ examples/mqtt/CMakeLists.txt | 2 +- examples/mqtt/sdkconfig.defaults | 2 - examples/mqtt/sdkconfig.defaults.esp32h2 | 3 ++ examples/mqtt/sdkconfig.defaults.linux | 2 + 7 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/examples_build-host-test.yml create mode 100644 examples/.build-test-rules.yml create mode 100644 examples/mqtt/sdkconfig.defaults.esp32h2 create mode 100644 examples/mqtt/sdkconfig.defaults.linux diff --git a/.github/workflows/examples_build-host-test.yml b/.github/workflows/examples_build-host-test.yml new file mode 100644 index 000000000..15d30c7cc --- /dev/null +++ b/.github/workflows/examples_build-host-test.yml @@ -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 diff --git a/ci/build_apps.py b/ci/build_apps.py index d7aa2e0e6..78127f09b 100644 --- a/ci/build_apps.py +++ b/ci/build_apps.py @@ -26,20 +26,25 @@ 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) + ignore_warning = os.environ['EXPECTED_WARNING'] if 'EXPECTED_WARNING' in os.environ else None + 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 +59,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) + ) diff --git a/examples/.build-test-rules.yml b/examples/.build-test-rules.yml new file mode 100644 index 000000000..ffb926571 --- /dev/null +++ b/examples/.build-test-rules.yml @@ -0,0 +1,3 @@ +examples/esp_netif/multiple_netifs: + disable: + - if: IDF_TARGET != "esp32" diff --git a/examples/mqtt/CMakeLists.txt b/examples/mqtt/CMakeLists.txt index 25cc297c6..49dde1536 100644 --- a/examples/mqtt/CMakeLists.txt +++ b/examples/mqtt/CMakeLists.txt @@ -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) diff --git a/examples/mqtt/sdkconfig.defaults b/examples/mqtt/sdkconfig.defaults index 75186ee56..e69de29bb 100644 --- a/examples/mqtt/sdkconfig.defaults +++ b/examples/mqtt/sdkconfig.defaults @@ -1,2 +0,0 @@ -CONFIG_IDF_TARGET="linux" -# CONFIG_ESP_EVENT_POST_FROM_ISR is not set diff --git a/examples/mqtt/sdkconfig.defaults.esp32h2 b/examples/mqtt/sdkconfig.defaults.esp32h2 new file mode 100644 index 000000000..26ce34bdd --- /dev/null +++ b/examples/mqtt/sdkconfig.defaults.esp32h2 @@ -0,0 +1,3 @@ +CONFIG_IDF_TARGET="esp32h2" +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_CONNECT_ETHERNET=y diff --git a/examples/mqtt/sdkconfig.defaults.linux b/examples/mqtt/sdkconfig.defaults.linux new file mode 100644 index 000000000..75186ee56 --- /dev/null +++ b/examples/mqtt/sdkconfig.defaults.linux @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="linux" +# CONFIG_ESP_EVENT_POST_FROM_ISR is not set From 2bd6163ec810788fb4279e0b2cb9acfacb31311b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 28 Jun 2023 16:49:37 +0200 Subject: [PATCH 4/4] ci(common): Introduce global warning list file --- ci/build_apps.py | 6 +++++- ci/ignore_build_warnings.txt | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 ci/ignore_build_warnings.txt diff --git a/ci/build_apps.py b/ci/build_apps.py index 78127f09b..a1fd942e9 100644 --- a/ci/build_apps.py +++ b/ci/build_apps.py @@ -32,7 +32,11 @@ if __name__ == '__main__': IDF_PATH = os.environ['IDF_PATH'] - ignore_warning = os.environ['EXPECTED_WARNING'] if 'EXPECTED_WARNING' in os.environ else None + # 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 diff --git a/ci/ignore_build_warnings.txt b/ci/ignore_build_warnings.txt new file mode 100644 index 000000000..8bd511988 --- /dev/null +++ b/ci/ignore_build_warnings.txt @@ -0,0 +1 @@ +DeprecationWarning: pkg_resources is deprecated as an API