Merge branch 'bugfix/update_get_ip_for_multiple_interfaces' into 'master'

ci: Fix wifi and ethernet test cases

See merge request espressif/esp-idf!18733
This commit is contained in:
Chen Yu Dong
2022-07-15 22:07:48 +08:00
82 changed files with 1872 additions and 1513 deletions

View File

@@ -29,6 +29,7 @@
- "tools/ci/python_packages/idf_iperf_test_util/**/*" - "tools/ci/python_packages/idf_iperf_test_util/**/*"
- "tools/ci/python_packages/tiny_test_fw/**/*" - "tools/ci/python_packages/tiny_test_fw/**/*"
- "tools/ci/python_packages/ttfw_idf/**/*" - "tools/ci/python_packages/ttfw_idf/**/*"
- "tools/ci/python_packages/common_test_methods.py"
- "tools/esp_prov/**/*" - "tools/esp_prov/**/*"
- "examples/**/*" - "examples/**/*"
@@ -56,6 +57,7 @@
- "tools/ci/python_packages/gitlab_api.py" - "tools/ci/python_packages/gitlab_api.py"
- "tools/ci/python_packages/tiny_test_fw/**/*" - "tools/ci/python_packages/tiny_test_fw/**/*"
- "tools/ci/python_packages/ttfw_idf/**/*" - "tools/ci/python_packages/ttfw_idf/**/*"
- "tools/ci/python_packages/common_test_methods.py"
- "tools/test_apps/**/*" - "tools/test_apps/**/*"
- "tools/ldgen/**/*" - "tools/ldgen/**/*"
@@ -73,6 +75,7 @@
- "tools/ci/python_packages/gitlab_api.py" - "tools/ci/python_packages/gitlab_api.py"
- "tools/ci/python_packages/tiny_test_fw/**/*" - "tools/ci/python_packages/tiny_test_fw/**/*"
- "tools/ci/python_packages/ttfw_idf/**/*" - "tools/ci/python_packages/ttfw_idf/**/*"
- "tools/ci/python_packages/common_test_methods.py"
- "components/**/*" - "components/**/*"
@@ -183,6 +186,7 @@
.patterns-example_test-related_changes-wifi: &patterns-example_test-related_changes-wifi .patterns-example_test-related_changes-wifi: &patterns-example_test-related_changes-wifi
- "components/esp_wifi/lib" - "components/esp_wifi/lib"
- "components/lwip/**/*"
- "examples/protocols/**/*" - "examples/protocols/**/*"
- "examples/wifi/**/*" - "examples/wifi/**/*"

View File

@@ -11,8 +11,14 @@
reports: reports:
junit: XUNIT_RESULT.xml junit: XUNIT_RESULT.xml
expire_in: 1 week expire_in: 1 week
variables:
GIT_DEPTH: 1
SUBMODULES_TO_FETCH: "none"
script: script:
- retry_failed git clone $KNOWN_FAILURE_CASES_REPO known_failure_cases - retry_failed git clone $KNOWN_FAILURE_CASES_REPO known_failure_cases
# get runner env config file
- retry_failed git clone $TEST_ENV_CONFIG_REPO
- python $CHECKOUT_REF_SCRIPT ci-test-runner-configs ci-test-runner-configs
# using runner tags as markers to filter the test cases # using runner tags as markers to filter the test cases
# Runner tags are comma separated, replace the comma with " and " for markers # Runner tags are comma separated, replace the comma with " and " for markers
- job_tags=$(python tools/ci/python_packages/gitlab_api.py get_job_tags $CI_PROJECT_ID --job_id $CI_JOB_ID) - job_tags=$(python tools/ci/python_packages/gitlab_api.py get_job_tags $CI_PROJECT_ID --job_id $CI_JOB_ID)
@@ -88,29 +94,29 @@ example_test_pytest_esp32_ethernet_ota:
- build_pytest_examples_esp32 - build_pytest_examples_esp32
tags: [ esp32, ethernet_ota ] tags: [ esp32, ethernet_ota ]
example_test_pytest_esp32_wifi_ota: example_test_pytest_esp32_wifi_high_traffic:
extends:
- .pytest_examples_dir_template
- .rules:test:example_test-esp32
needs:
- build_pytest_examples_esp32
tags: [ esp32, wifi_high_traffic ]
example_test_pytest_esp32_flash_encryption_wifi_high_traffic:
extends: extends:
- .pytest_examples_dir_template - .pytest_examples_dir_template
- .rules:test:example_test-esp32-ota-related_changes-include_nightly_run - .rules:test:example_test-esp32-ota-related_changes-include_nightly_run
needs: needs:
- build_pytest_examples_esp32 - build_pytest_examples_esp32
tags: [ esp32, wifi_ota ] tags: [ esp32, flash_encryption_wifi_high_traffic ]
example_test_pytest_esp32_flash_encryption_ota: example_test_pytest_esp32c3_flash_encryption_wifi_high_traffic:
extends:
- .pytest_examples_dir_template
- .rules:test:example_test-esp32-ota-related_changes
needs:
- build_pytest_examples_esp32
tags: [ esp32, flash_encryption_ota ]
example_test_pytest_esp32c3_flash_encryption_wifi_ota:
extends: extends:
- .pytest_examples_dir_template - .pytest_examples_dir_template
- .rules:test:example_test-esp32c3-ota-related_changes-include_nightly_run - .rules:test:example_test-esp32c3-ota-related_changes-include_nightly_run
needs: needs:
- build_pytest_examples_esp32c3 - build_pytest_examples_esp32c3
tags: [ esp32c3, flash_encryption_wifi_ota ] tags: [ esp32c3, flash_encryption_wifi_high_traffic ]
example_test_pytest_esp32_ethernet: example_test_pytest_esp32_ethernet:
extends: extends:
@@ -128,21 +134,29 @@ example_test_pytest_esp32_8mb_flash:
- build_pytest_examples_esp32 - build_pytest_examples_esp32
tags: [ esp32, ethernet_flash_8m ] tags: [ esp32, ethernet_flash_8m ]
example_test_pytest_esp32_wifi: example_test_pytest_esp32_wifi_ap:
extends:
- .pytest_examples_dir_template
- .rules:test:example_test-esp32-wifi-related_changes
needs:
- build_pytest_examples_esp32
tags: [ esp32, wifi ]
example_test_pytest_esp32_wifi_bt:
extends: extends:
- .pytest_examples_dir_template - .pytest_examples_dir_template
- .rules:test:example_test-esp32 - .rules:test:example_test-esp32
needs: needs:
- build_pytest_examples_esp32 - build_pytest_examples_esp32
tags: [ esp32, wifi_bt ] tags: [ esp32, wifi_ap ]
example_test_pytest_esp32_wifi_router:
extends:
- .pytest_examples_dir_template
- .rules:test:example_test-esp32
needs:
- build_pytest_examples_esp32
tags: [ esp32, wifi_router ]
example_test_pytest_esp32_wifi_wlan:
extends:
- .pytest_examples_dir_template
- .rules:test:example_test-esp32-wifi-related_changes
needs:
- build_pytest_examples_esp32
tags: [ esp32, wifi_wlan ]
example_test_pytest_esp32_ethernet_ip101: example_test_pytest_esp32_ethernet_ip101:
extends: extends:
@@ -340,6 +354,7 @@ test_app_test_pytest_esp32s2_usb_host:
junit: $LOG_PATH/*/XUNIT_RESULT.xml junit: $LOG_PATH/*/XUNIT_RESULT.xml
expire_in: 1 week expire_in: 1 week
variables: variables:
GIT_DEPTH: 1
TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw" TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS" LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS"
ENV_FILE: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/EnvConfig.yml" ENV_FILE: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/EnvConfig.yml"
@@ -379,7 +394,7 @@ test_weekend_mqtt:
- .rules:labels:weekend_test - .rules:labels:weekend_test
tags: tags:
- ESP32 - ESP32
- Example_EthKitV1 - ethernet_router
script: script:
- export MQTT_PUBLISH_TEST=1 - export MQTT_PUBLISH_TEST=1
- export TEST_PATH=$CI_PROJECT_DIR/tools/test_apps/protocols/mqtt/publish_connect_test - export TEST_PATH=$CI_PROJECT_DIR/tools/test_apps/protocols/mqtt/publish_connect_test
@@ -411,12 +426,6 @@ test_weekend_mqtt:
- .example_test_template - .example_test_template
- .rules:test:example_test-esp32s3 - .rules:test:example_test-esp32s3
example_test_001B:
extends: .example_test_esp32_template
tags:
- ESP32
- Example_EthKitV1
example_test_001B_V3: example_test_001B_V3:
extends: .example_test_esp32_template extends: .example_test_esp32_template
tags: tags:
@@ -434,19 +443,21 @@ example_test_protocols:
extends: .example_test_esp32_template extends: .example_test_esp32_template
tags: tags:
- ESP32 - ESP32
- Example_WIFI_Protocols - wifi_router
example_test_002: example_test_002:
extends: .example_test_esp32_template extends:
- .example_test_esp32_template
- .rules:test:example_test-esp32-wifi-related_changes
tags: tags:
- ESP32 - ESP32
- Example_ShieldBox_Basic - Example_ShieldBox_Basic
example_test_ethernet: example_test_ethernet_router:
extends: .example_test_esp32_template extends: .example_test_esp32_template
tags: tags:
- ESP32 - ESP32
- Example_Ethernet - ethernet_router
.example_test_003: .example_test_003:
extends: .example_test_esp32_template extends: .example_test_esp32_template
@@ -559,6 +570,7 @@ example_test_ESP32C3_SDSPI:
needs: needs:
- assign_custom_test - assign_custom_test
variables: variables:
GIT_DEPTH: 1
TEST_CASE_PATH: "$CI_PROJECT_DIR/tools/test_apps" TEST_CASE_PATH: "$CI_PROJECT_DIR/tools/test_apps"
CONFIG_FILE_PATH: "${CI_PROJECT_DIR}/tools/test_apps/test_configs" CONFIG_FILE_PATH: "${CI_PROJECT_DIR}/tools/test_apps/test_configs"
@@ -595,23 +607,11 @@ test_app_test_001:
variables: variables:
SETUP_TOOLS: "1" SETUP_TOOLS: "1"
test_app_test_002:
extends: .test_app_esp32_template
tags:
- ESP32
- Example_WIFI
test_app_test_eth: test_app_test_eth:
extends: .test_app_esp32_template extends: .test_app_esp32_template
tags: tags:
- ESP32 - ESP32
- Example_EthKitV1 - ethernet_router
test_app_test_003:
extends: .test_app_esp32_template
tags:
- ESP32
- Example_PPP
test_app_test_004: test_app_test_004:
extends: .test_app_esp32s2_template extends: .test_app_esp32s2_template
@@ -666,6 +666,7 @@ test_app_test_flash_psram_f8r8:
needs: # the assign already needs all the build jobs needs: # the assign already needs all the build jobs
- assign_unit_test - assign_unit_test
variables: variables:
GIT_DEPTH: 1
TEST_CASE_PATH: "$CI_PROJECT_DIR/tools/unit-test-app" TEST_CASE_PATH: "$CI_PROJECT_DIR/tools/unit-test-app"
CONFIG_FILE_PATH: "${CI_PROJECT_DIR}/components/idf_test/unit_test/test_configs" CONFIG_FILE_PATH: "${CI_PROJECT_DIR}/components/idf_test/unit_test/test_configs"

View File

@@ -33,6 +33,13 @@ from pytest_embedded.plugin import multi_dut_argument, multi_dut_fixture
from pytest_embedded.utils import find_by_suffix from pytest_embedded.utils import find_by_suffix
from pytest_embedded_idf.dut import IdfDut from pytest_embedded_idf.dut import IdfDut
try:
import common_test_methods # noqa: F401
except ImportError:
sys.path.append(os.path.join(os.path.dirname(__file__), 'tools', 'ci', 'python_packages'))
import common_test_methods # noqa: F401
SUPPORTED_TARGETS = ['esp32', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c2'] SUPPORTED_TARGETS = ['esp32', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c2']
PREVIEW_TARGETS = ['linux', 'esp32h2'] PREVIEW_TARGETS = ['linux', 'esp32h2']
DEFAULT_SDKCONFIG = 'default' DEFAULT_SDKCONFIG = 'default'

View File

@@ -1,4 +1,25 @@
idf_component_register(SRCS "connect.c" "stdin_out.c" "addr_from_stdin.c" set(srcs "stdin_out.c"
"addr_from_stdin.c"
"connect.c"
"wifi_connect.c")
if(CONFIG_EXAMPLE_PROVIDE_WIFI_CONSOLE_CMD)
list(APPEND srcs "console_cmd.c")
endif()
if(CONFIG_EXAMPLE_CONNECT_ETHERNET)
list(APPEND srcs "eth_connect.c")
endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "include" INCLUDE_DIRS "include"
PRIV_REQUIRES esp_netif driver esp_eth PRIV_REQUIRES esp_netif driver)
)
if(CONFIG_EXAMPLE_PROVIDE_WIFI_CONSOLE_CMD)
idf_component_optional_requires(PRIVATE console)
endif()
if(CONFIG_EXAMPLE_CONNECT_ETHERNET)
idf_component_optional_requires(PRIVATE esp_eth)
endif()

View File

@@ -10,19 +10,42 @@ menu "Example Connection Configuration"
Choose this option to connect with WiFi Choose this option to connect with WiFi
if EXAMPLE_CONNECT_WIFI if EXAMPLE_CONNECT_WIFI
config EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
bool "Get ssid and password from stdin"
default n
help
Give the WiFi SSID and password from stdin.
config EXAMPLE_PROVIDE_WIFI_CONSOLE_CMD
depends on !EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
bool "Provide wifi connect commands"
default y
help
Provide wifi connect commands for esp_console.
Please use `example_register_wifi_connect_commands` to register them.
config EXAMPLE_WIFI_SSID config EXAMPLE_WIFI_SSID
depends on !EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
string "WiFi SSID" string "WiFi SSID"
default "myssid" default "myssid"
help help
SSID (network name) for the example to connect to. SSID (network name) for the example to connect to.
config EXAMPLE_WIFI_PASSWORD config EXAMPLE_WIFI_PASSWORD
depends on !EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
string "WiFi Password" string "WiFi Password"
default "mypassword" default "mypassword"
help help
WiFi password (WPA or WPA2) for the example to use. WiFi password (WPA or WPA2) for the example to use.
Can be left blank if the network has no security set. Can be left blank if the network has no security set.
config EXAMPLE_WIFI_CONN_MAX_RETRY
int "Maximum retry"
default 6
help
Set the Maximum retry to avoid station reconnecting to the AP unlimited,
in case the AP is really inexistent.
choice EXAMPLE_WIFI_SCAN_METHOD choice EXAMPLE_WIFI_SCAN_METHOD
prompt "WiFi Scan Method" prompt "WiFi Scan Method"
default EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL default EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL
@@ -282,9 +305,9 @@ menu "Example Connection Configuration"
endif # EXAMPLE_CONNECT_ETHERNET endif # EXAMPLE_CONNECT_ETHERNET
config EXAMPLE_CONNECT_IPV6 config EXAMPLE_CONNECT_IPV6
depends on EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET
bool "Obtain IPv6 address" bool "Obtain IPv6 address"
default y default y
depends on EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET
select LWIP_IPV6 select LWIP_IPV6
help help
By default, examples will wait until IPv4 and IPv6 local link addresses are obtained. By default, examples will wait until IPv4 and IPv6 local link addresses are obtained.

View File

@@ -50,7 +50,7 @@ esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *ad
return ESP_OK; return ESP_OK;
} }
#if CONFIG_LWIP_IPV6 #if CONFIG_EXAMPLE_CONNECT_IPV6
else if (cur->ai_family == AF_INET6) { else if (cur->ai_family == AF_INET6) {
*ip_protocol = IPPROTO_IPV6; *ip_protocol = IPPROTO_IPV6;
*addr_family = AF_INET6; *addr_family = AF_INET6;

View File

@@ -1,94 +1,29 @@
/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection. /*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
This example code is in the Public Domain (or CC0 licensed, at your option.) *
* SPDX-License-Identifier: Unlicense OR CC0-1.0
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/ */
#include <string.h> #include <string.h>
#include "protocol_examples_common.h" #include "protocol_examples_common.h"
#include "example_common_private.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_event.h" #include "esp_event.h"
#include "esp_wifi.h" #include "esp_wifi.h"
#include "esp_wifi_default.h" #include "esp_wifi_default.h"
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
#include "esp_eth.h"
#if CONFIG_ETH_USE_SPI_ETHERNET
#include "driver/spi_master.h"
#endif // CONFIG_ETH_USE_SPI_ETHERNET
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
#include "esp_log.h" #include "esp_log.h"
#include "esp_netif.h" #include "esp_netif.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/event_groups.h" #include "freertos/event_groups.h"
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/sys.h" #include "lwip/sys.h"
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 static const char *TAG = "example_common";
#define MAX_IP6_ADDRS_PER_NETIF (5)
#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces*2)
#if defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK)
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_LINK_LOCAL
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_GLOBAL)
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_GLOBAL
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL)
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_SITE_LOCAL
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL)
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_UNIQUE_LOCAL
#endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_...
#else
#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces)
#endif
#define EXAMPLE_DO_CONNECT CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET
#if CONFIG_EXAMPLE_WIFI_SCAN_METHOD_FAST
#define EXAMPLE_WIFI_SCAN_METHOD WIFI_FAST_SCAN
#elif CONFIG_EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL
#define EXAMPLE_WIFI_SCAN_METHOD WIFI_ALL_CHANNEL_SCAN
#endif
#if CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL
#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL
#elif CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SECURITY
#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SECURITY
#endif
#if CONFIG_EXAMPLE_WIFI_AUTH_OPEN
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_EXAMPLE_WIFI_AUTH_WEP
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_WPA2_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_ENTERPRISE
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_ENTERPRISE
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA3_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_WPA3_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_EXAMPLE_WIFI_AUTH_WAPI_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endif
static int s_active_interfaces = 0;
static SemaphoreHandle_t s_semph_get_ip_addrs;
static esp_netif_t *s_example_esp_netif = NULL;
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
static esp_ip6_addr_t s_ipv6_addr;
#if CONFIG_EXAMPLE_CONNECT_IPV6
/* types of ipv6 addresses to be displayed on ipv6 events */ /* types of ipv6 addresses to be displayed on ipv6 events */
static const char *s_ipv6_addr_types[] = { const char *example_ipv6_addr_types_to_str[6] = {
"ESP_IP6_ADDR_IS_UNKNOWN", "ESP_IP6_ADDR_IS_UNKNOWN",
"ESP_IP6_ADDR_IS_GLOBAL", "ESP_IP6_ADDR_IS_GLOBAL",
"ESP_IP6_ADDR_IS_LINK_LOCAL", "ESP_IP6_ADDR_IS_LINK_LOCAL",
@@ -98,406 +33,88 @@ static const char *s_ipv6_addr_types[] = {
}; };
#endif #endif
static const char *TAG = "example_connect";
#if CONFIG_EXAMPLE_CONNECT_WIFI
static esp_netif_t *wifi_start(void);
static void wifi_stop(void);
#endif
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
static esp_netif_t *eth_start(void);
static void eth_stop(void);
#endif
/** /**
* @brief Checks the netif description if it contains specified prefix. * @brief Checks the netif description if it contains specified prefix.
* All netifs created withing common connect component are prefixed with the module TAG, * All netifs created withing common connect component are prefixed with the module TAG,
* so it returns true if the specified netif is owned by this module * so it returns true if the specified netif is owned by this module
*/ */
static bool is_our_netif(const char *prefix, esp_netif_t *netif) bool example_is_our_netif(const char *prefix, esp_netif_t *netif)
{ {
return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0; return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0;
} }
/* set up connection, Wi-Fi and/or Ethernet */
static void start(void)
{
#if CONFIG_EXAMPLE_CONNECT_WIFI
s_example_esp_netif = wifi_start();
s_active_interfaces++;
#endif
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
s_example_esp_netif = eth_start();
s_active_interfaces++;
#endif
#if CONFIG_EXAMPLE_CONNECT_WIFI && CONFIG_EXAMPLE_CONNECT_ETHERNET
/* if both intefaces at once, clear out to indicate that multiple netifs are active */
s_example_esp_netif = NULL;
#endif
#if EXAMPLE_DO_CONNECT
/* create semaphore if at least one interface is active */
s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0);
#endif
}
/* tear down connection, release resources */
static void stop(void)
{
#if CONFIG_EXAMPLE_CONNECT_WIFI
wifi_stop();
s_active_interfaces--;
#endif
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
eth_stop();
s_active_interfaces--;
#endif
}
#if EXAMPLE_DO_CONNECT
static esp_ip4_addr_t s_ip_addr;
static void on_got_ip(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
if (!is_our_netif(TAG, event->esp_netif)) {
ESP_LOGW(TAG, "Got IPv4 from another interface \"%s\": ignored", esp_netif_get_desc(event->esp_netif));
return;
}
ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr));
xSemaphoreGive(s_semph_get_ip_addrs);
}
#endif
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
static void on_got_ipv6(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
if (!is_our_netif(TAG, event->esp_netif)) {
ESP_LOGW(TAG, "Got IPv6 from another netif: ignored");
return;
}
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]);
if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) {
memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr));
xSemaphoreGive(s_semph_get_ip_addrs);
}
}
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
esp_err_t example_connect(void)
{
#if EXAMPLE_DO_CONNECT
if (s_semph_get_ip_addrs != NULL) {
return ESP_ERR_INVALID_STATE;
}
#endif
start();
ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop));
ESP_LOGI(TAG, "Waiting for IP(s)");
for (int i = 0; i < NR_OF_IP_ADDRESSES_TO_WAIT_FOR; ++i) {
xSemaphoreTake(s_semph_get_ip_addrs, portMAX_DELAY);
}
// iterate over active interfaces, and print out IPs of "our" netifs
esp_netif_t *netif = NULL;
esp_netif_ip_info_t ip;
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) {
netif = esp_netif_next(netif);
if (is_our_netif(TAG, netif)) {
ESP_LOGI(TAG, "Connected to %s", esp_netif_get_desc(netif));
ESP_ERROR_CHECK(esp_netif_get_ip_info(netif, &ip));
ESP_LOGI(TAG, "- IPv4 address: " IPSTR, IP2STR(&ip.ip));
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
esp_ip6_addr_t ip6[MAX_IP6_ADDRS_PER_NETIF];
int ip6_addrs = esp_netif_get_all_ip6(netif, ip6);
for (int j = 0; j < ip6_addrs; ++j) {
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&(ip6[j]));
ESP_LOGI(TAG, "- IPv6 address: " IPV6STR ", type: %s", IPV62STR(ip6[j]), s_ipv6_addr_types[ipv6_type]);
}
#endif
}
}
return ESP_OK;
}
esp_err_t example_disconnect(void)
{
if (s_semph_get_ip_addrs == NULL) {
return ESP_ERR_INVALID_STATE;
}
vSemaphoreDelete(s_semph_get_ip_addrs);
s_semph_get_ip_addrs = NULL;
stop();
ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&stop));
return ESP_OK;
}
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI
static void on_wifi_disconnect(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect...");
esp_err_t err = esp_wifi_connect();
if (err == ESP_ERR_WIFI_NOT_STARTED) {
return;
}
ESP_ERROR_CHECK(err);
}
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
static void on_wifi_connect(void *esp_netif, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
esp_netif_create_ip6_linklocal(esp_netif);
}
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
static esp_netif_t *wifi_start(void)
{
char *desc;
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
// Prefix the interface description with the module TAG
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
asprintf(&desc, "%s: %s", TAG, esp_netif_config.if_desc);
esp_netif_config.if_desc = desc;
esp_netif_config.route_prio = 128;
esp_netif_t *netif = esp_netif_create_wifi(WIFI_IF_STA, &esp_netif_config);
free(desc);
esp_wifi_set_default_wifi_sta_handlers();
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL));
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect, netif));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
#endif
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
wifi_config_t wifi_config = {
.sta = {
.ssid = CONFIG_EXAMPLE_WIFI_SSID,
.password = CONFIG_EXAMPLE_WIFI_PASSWORD,
.scan_method = EXAMPLE_WIFI_SCAN_METHOD,
.sort_method = EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD,
.threshold.rssi = CONFIG_EXAMPLE_WIFI_SCAN_RSSI_THRESHOLD,
.threshold.authmode = EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD,
},
};
ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid);
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
esp_wifi_connect();
return netif;
}
static void wifi_stop(void)
{
esp_netif_t *wifi_netif = get_example_netif_from_desc("sta");
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect));
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip));
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6));
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect));
#endif
esp_err_t err = esp_wifi_stop();
if (err == ESP_ERR_WIFI_NOT_INIT) {
return;
}
ESP_ERROR_CHECK(err);
ESP_ERROR_CHECK(esp_wifi_deinit());
ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(wifi_netif));
esp_netif_destroy(wifi_netif);
s_example_esp_netif = NULL;
}
#endif // CONFIG_EXAMPLE_CONNECT_WIFI
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
/** Event handler for Ethernet events */
static void on_eth_event(void *esp_netif, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
ESP_LOGI(TAG, "Ethernet Link Up");
ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif));
break;
default:
break;
}
}
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
static esp_eth_handle_t s_eth_handle = NULL;
static esp_eth_mac_t *s_mac = NULL;
static esp_eth_phy_t *s_phy = NULL;
static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
static esp_netif_t *eth_start(void)
{
char *desc;
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
// Prefix the interface description with the module TAG
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
asprintf(&desc, "%s: %s", TAG, esp_netif_config.if_desc);
esp_netif_config.if_desc = desc;
esp_netif_config.route_prio = 64;
esp_netif_config_t netif_config = {
.base = &esp_netif_config,
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
};
esp_netif_t *netif = esp_netif_new(&netif_config);
assert(netif);
free(desc);
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
mac_config.rx_task_stack_size = CONFIG_EXAMPLE_ETHERNET_EMAC_TASK_STACK_SIZE;
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
#if CONFIG_EXAMPLE_ETH_PHY_IP101
s_phy = esp_eth_phy_new_ip101(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
s_phy = esp_eth_phy_new_rtl8201(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX
s_phy = esp_eth_phy_new_lan87xx(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_DP83848
s_phy = esp_eth_phy_new_dp83848(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX
s_phy = esp_eth_phy_new_ksz80xx(&phy_config);
#endif
#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET
gpio_install_isr_service(0);
spi_bus_config_t buscfg = {
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
.sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
};
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1));
spi_device_interface_config_t spi_devcfg = {
.mode = 0,
.clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
.queue_size = 20
};
#if CONFIG_EXAMPLE_USE_DM9051
/* dm9051 ethernet driver is based on spi driver */
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
s_phy = esp_eth_phy_new_dm9051(&phy_config);
#elif CONFIG_EXAMPLE_USE_W5500
/* w5500 ethernet driver is based on spi driver */
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
s_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
s_phy = esp_eth_phy_new_w5500(&phy_config);
#endif
#elif CONFIG_EXAMPLE_USE_OPENETH
phy_config.autonego_timeout_ms = 100;
s_mac = esp_eth_mac_new_openeth(&mac_config);
s_phy = esp_eth_phy_new_dp83848(&phy_config);
#endif
// Install Ethernet driver
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle));
#if !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
/* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually.
02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.
*/
ESP_ERROR_CHECK(esp_eth_ioctl(s_eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
0x02, 0x00, 0x00, 0x12, 0x34, 0x56
}));
#endif
// combine driver with netif
s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
esp_netif_attach(netif, s_eth_glue);
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL));
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
#endif
esp_eth_start(s_eth_handle);
return netif;
}
static void eth_stop(void)
{
esp_netif_t *eth_netif = get_example_netif_from_desc("eth");
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip));
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6));
ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event));
#endif
ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle));
ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue));
ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle));
s_eth_handle = NULL;
ESP_ERROR_CHECK(s_phy->del(s_phy));
ESP_ERROR_CHECK(s_mac->del(s_mac));
esp_netif_destroy(eth_netif);
s_example_esp_netif = NULL;
}
esp_eth_handle_t get_example_eth_handle(void)
{
return s_eth_handle;
}
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
esp_netif_t *get_example_netif(void)
{
return s_example_esp_netif;
}
esp_netif_t *get_example_netif_from_desc(const char *desc) esp_netif_t *get_example_netif_from_desc(const char *desc)
{ {
esp_netif_t *netif = NULL; esp_netif_t *netif = NULL;
char *expected_desc;
asprintf(&expected_desc, "%s: %s", TAG, desc);
while ((netif = esp_netif_next(netif)) != NULL) { while ((netif = esp_netif_next(netif)) != NULL) {
if (strcmp(esp_netif_get_desc(netif), expected_desc) == 0) { if (strcmp(esp_netif_get_desc(netif), desc) == 0) {
free(expected_desc);
return netif; return netif;
} }
} }
free(expected_desc);
return netif; return netif;
} }
void example_print_all_netif_ips(const char *prefix)
{
// iterate over active interfaces, and print out IPs of "our" netifs
esp_netif_t *netif = NULL;
esp_netif_ip_info_t ip;
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) {
netif = esp_netif_next(netif);
if (example_is_our_netif(prefix, netif)) {
ESP_LOGI(TAG, "Connected to %s", esp_netif_get_desc(netif));
ESP_ERROR_CHECK(esp_netif_get_ip_info(netif, &ip));
ESP_LOGI(TAG, "- IPv4 address: " IPSTR ",", IP2STR(&ip.ip));
#if CONFIG_EXAMPLE_CONNECT_IPV6
esp_ip6_addr_t ip6[MAX_IP6_ADDRS_PER_NETIF];
int ip6_addrs = esp_netif_get_all_ip6(netif, ip6);
for (int j = 0; j < ip6_addrs; ++j) {
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&(ip6[j]));
ESP_LOGI(TAG, "- IPv6 address: " IPV6STR ", type: %s", IPV62STR(ip6[j]), example_ipv6_addr_types_to_str[ipv6_type]);
}
#endif
}
}
}
esp_err_t example_connect(void)
{
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
if (example_ethernet_connect() != ESP_OK) {
return ESP_FAIL;
}
ESP_ERROR_CHECK(esp_register_shutdown_handler(&example_ethernet_shutdown));
#endif
#if CONFIG_EXAMPLE_CONNECT_WIFI
if (example_wifi_connect() != ESP_OK) {
return ESP_FAIL;
}
ESP_ERROR_CHECK(esp_register_shutdown_handler(&example_wifi_shutdown));
#endif
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
example_print_all_netif_ips(EXAMPLE_NETIF_DESC_ETH);
#endif
#if CONFIG_EXAMPLE_CONNECT_WIFI
example_print_all_netif_ips(EXAMPLE_NETIF_DESC_STA);
#endif
return ESP_OK;
}
esp_err_t example_disconnect(void)
{
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
example_ethernet_shutdown();
ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&example_ethernet_shutdown));
#endif
#if CONFIG_EXAMPLE_CONNECT_WIFI
example_wifi_shutdown();
ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&example_wifi_shutdown));
#endif
return ESP_OK;
}

View File

@@ -0,0 +1,87 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include "protocol_examples_common.h"
#include "example_common_private.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_console.h"
#include "argtable3/argtable3.h"
static const char *TAG = "example_console";
typedef struct {
struct arg_str *ssid;
struct arg_str *password;
struct arg_int *channel;
struct arg_end *end;
} wifi_connect_args_t;
static wifi_connect_args_t connect_args;
static int cmd_do_wifi_connect(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &connect_args);
if (nerrors != 0) {
arg_print_errors(stderr, connect_args.end, argv[0]);
return 1;
}
wifi_config_t wifi_config = {
.sta = {
.scan_method = WIFI_ALL_CHANNEL_SCAN,
.sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
},
};
if (connect_args.channel->count > 0) {
wifi_config.sta.channel = (uint8_t)(connect_args.channel->ival[0]);
}
const char *ssid = connect_args.ssid->sval[0];
const char *pass = connect_args.password->sval[0];
strlcpy((char *) wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
if (pass) {
strlcpy((char *) wifi_config.sta.password, pass, sizeof(wifi_config.sta.password));
}
example_wifi_sta_do_connect(wifi_config, false);
return 0;
}
static int cmd_do_wifi_disconnect(int argc, char **argv)
{
example_wifi_sta_do_disconnect();
return 0;
}
void example_register_wifi_connect_commands(void)
{
ESP_LOGI(TAG, "Registering WiFi connect commands.");
example_wifi_start();
connect_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
connect_args.password = arg_str0(NULL, NULL, "<pass>", "password of AP");
connect_args.channel = arg_int0("n", "channel", "<channel>", "channel of AP");
connect_args.end = arg_end(2);
const esp_console_cmd_t wifi_connect_cmd = {
.command = "wifi_connect",
.help = "WiFi is station mode, join specified soft-AP",
.hint = NULL,
.func = &cmd_do_wifi_connect,
.argtable = &connect_args
};
ESP_ERROR_CHECK( esp_console_cmd_register(&wifi_connect_cmd) );
const esp_console_cmd_t wifi_disconnect_cmd = {
.command = "wifi_disconnect",
.help = "Do wifi disconnect",
.hint = NULL,
.func = &cmd_do_wifi_disconnect,
};
ESP_ERROR_CHECK( esp_console_cmd_register(&wifi_disconnect_cmd) );
}

View File

@@ -0,0 +1,219 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include "protocol_examples_common.h"
#include "example_common_private.h"
#include "esp_event.h"
#include "esp_eth.h"
#if CONFIG_ETH_USE_SPI_ETHERNET
#include "driver/spi_master.h"
#endif // CONFIG_ETH_USE_SPI_ETHERNET
#include "esp_log.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
static const char *TAG = "ethernet_connect";
static SemaphoreHandle_t s_semph_get_ip_addrs = NULL;
static esp_netif_t *eth_start(void);
static void eth_stop(void);
/** Event handler for Ethernet events */
static void eth_on_got_ip(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
if (!example_is_our_netif(EXAMPLE_NETIF_DESC_ETH, event->esp_netif)) {
return;
}
ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
if (s_semph_get_ip_addrs) {
xSemaphoreGive(s_semph_get_ip_addrs);
}
}
#if CONFIG_EXAMPLE_CONNECT_IPV6
static void eth_on_got_ipv6(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
if (!example_is_our_netif(EXAMPLE_NETIF_DESC_ETH, event->esp_netif)) {
return;
}
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
IPV62STR(event->ip6_info.ip), example_ipv6_addr_types_to_str[ipv6_type]);
if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) {
xSemaphoreGive(s_semph_get_ip_addrs);
}
}
static void on_eth_event(void *esp_netif, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
ESP_LOGI(TAG, "Ethernet Link Up");
ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif));
break;
default:
break;
}
}
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
static esp_eth_handle_t s_eth_handle = NULL;
static esp_eth_mac_t *s_mac = NULL;
static esp_eth_phy_t *s_phy = NULL;
static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
static esp_netif_t *eth_start(void)
{
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
esp_netif_config.if_desc = EXAMPLE_NETIF_DESC_ETH;
esp_netif_config.route_prio = 64;
esp_netif_config_t netif_config = {
.base = &esp_netif_config,
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
};
esp_netif_t *netif = esp_netif_new(&netif_config);
assert(netif);
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
mac_config.rx_task_stack_size = CONFIG_EXAMPLE_ETHERNET_EMAC_TASK_STACK_SIZE;
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
#if CONFIG_EXAMPLE_ETH_PHY_IP101
s_phy = esp_eth_phy_new_ip101(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
s_phy = esp_eth_phy_new_rtl8201(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX
s_phy = esp_eth_phy_new_lan87xx(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_DP83848
s_phy = esp_eth_phy_new_dp83848(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX
s_phy = esp_eth_phy_new_ksz80xx(&phy_config);
#endif
#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET
gpio_install_isr_service(0);
spi_bus_config_t buscfg = {
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
.sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
};
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1));
spi_device_interface_config_t spi_devcfg = {
.mode = 0,
.clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
.queue_size = 20
};
#if CONFIG_EXAMPLE_USE_DM9051
/* dm9051 ethernet driver is based on spi driver */
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
s_phy = esp_eth_phy_new_dm9051(&phy_config);
#elif CONFIG_EXAMPLE_USE_W5500
/* w5500 ethernet driver is based on spi driver */
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
s_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
s_phy = esp_eth_phy_new_w5500(&phy_config);
#endif
#elif CONFIG_EXAMPLE_USE_OPENETH
phy_config.autonego_timeout_ms = 100;
s_mac = esp_eth_mac_new_openeth(&mac_config);
s_phy = esp_eth_phy_new_dp83848(&phy_config);
#endif
// Install Ethernet driver
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle));
#if !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
/* The SPI Ethernet module might doesn't have a burned factory MAC address, we cat to set it manually.
02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.
*/
ESP_ERROR_CHECK(esp_eth_ioctl(s_eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
0x02, 0x00, 0x00, 0x12, 0x34, 0x56
}));
#endif
// combine driver with netif
s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
esp_netif_attach(netif, s_eth_glue);
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &eth_on_got_ip, NULL));
#ifdef CONFIG_EXAMPLE_CONNECT_IPV6
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &eth_on_got_ipv6, NULL));
#endif
esp_eth_start(s_eth_handle);
return netif;
}
static void eth_stop(void)
{
esp_netif_t *eth_netif = get_example_netif_from_desc(EXAMPLE_NETIF_DESC_ETH);
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, &eth_on_got_ip));
#if CONFIG_EXAMPLE_CONNECT_IPV6
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &eth_on_got_ipv6));
ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event));
#endif
ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle));
ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue));
ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle));
s_eth_handle = NULL;
ESP_ERROR_CHECK(s_phy->del(s_phy));
ESP_ERROR_CHECK(s_mac->del(s_mac));
esp_netif_destroy(eth_netif);
}
esp_eth_handle_t get_example_eth_handle(void)
{
return s_eth_handle;
}
/* tear down connection, release resources */
void example_ethernet_shutdown(void)
{
if (s_semph_get_ip_addrs == NULL) {
return;
}
vSemaphoreDelete(s_semph_get_ip_addrs);
s_semph_get_ip_addrs = NULL;
eth_stop();
}
esp_err_t example_ethernet_connect(void)
{
s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0);
eth_start();
ESP_LOGI(TAG, "Waiting for IP(s).");
for (int i = 0; i < NR_OF_IP_ADDRESSES_TO_WAIT_FOR; ++i) {
xSemaphoreTake(s_semph_get_ip_addrs, portMAX_DELAY);
}
return ESP_OK;
}

View File

@@ -12,14 +12,14 @@
#pragma once #pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "lwip/sys.h" #include "lwip/sys.h"
#include <lwip/netdb.h> #include <lwip/netdb.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#ifdef __cplusplus
extern "C" {
#endif
/** /**
* @brief Read and evaluate IP address from stdin * @brief Read and evaluate IP address from stdin
* *

View File

@@ -0,0 +1,60 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Private Funtions of protocol example common */
#pragma once
#include "esp_err.h"
#include "esp_wifi.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_EXAMPLE_CONNECT_IPV6
#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (2)
#else
#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (1)
#endif
#if CONFIG_EXAMPLE_CONNECT_IPV6
#define MAX_IP6_ADDRS_PER_NETIF (5)
#if defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK)
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_LINK_LOCAL
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_GLOBAL)
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_GLOBAL
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL)
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_SITE_LOCAL
#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL)
#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_UNIQUE_LOCAL
#endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_...
#endif
#if CONFIG_EXAMPLE_CONNECT_IPV6
extern const char *example_ipv6_addr_types_to_str[6];
#endif
void example_wifi_start(void);
void example_wifi_stop(void);
esp_err_t example_wifi_sta_do_connect(wifi_config_t wifi_config, bool wait);
esp_err_t example_wifi_sta_do_disconnect(void);
bool example_is_our_netif(const char *prefix, esp_netif_t *netif);
void example_print_all_netif_ips(const char *prefix);
void example_wifi_shutdown(void);
esp_err_t example_wifi_connect(void);
void example_ethernet_shutdown(void);
esp_err_t example_ethernet_connect(void);
#ifdef __cplusplus
}
#endif

View File

@@ -9,25 +9,32 @@
#pragma once #pragma once
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_netif.h"
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
#include "esp_eth.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "esp_err.h" #if CONFIG_EXAMPLE_CONNECT_WIFI
#include "esp_netif.h" #define EXAMPLE_NETIF_DESC_STA "example_netif_sta"
#include "esp_eth.h"
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
#define EXAMPLE_INTERFACE get_example_netif()
#endif #endif
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI #if CONFIG_EXAMPLE_CONNECT_ETHERNET
#define EXAMPLE_INTERFACE get_example_netif() #define EXAMPLE_NETIF_DESC_ETH "example_netif_eth"
#endif #endif
#if !defined (CONFIG_EXAMPLE_CONNECT_ETHERNET) && !defined (CONFIG_EXAMPLE_CONNECT_WIFI) /* Example default interface, prefer the ethernet one if running in example-test (CI) configuration */
// This is useful for some tests which do not need a network connection #if CONFIG_EXAMPLE_CONNECT_ETHERNET
#define EXAMPLE_INTERFACE NULL #define EXAMPLE_INTERFACE get_example_netif_from_desc(EXAMPLE_NETIF_DESC_ETH)
#define get_example_netif() get_example_netif_from_desc(EXAMPLE_NETIF_DESC_ETH)
#elif CONFIG_EXAMPLE_CONNECT_WIFI
#define EXAMPLE_INTERFACE get_example_netif_from_desc(EXAMPLE_NETIF_DESC_STA)
#define get_example_netif() get_example_netif_from_desc(EXAMPLE_NETIF_DESC_STA)
#endif #endif
/** /**
@@ -60,15 +67,6 @@ esp_err_t example_disconnect(void);
*/ */
esp_err_t example_configure_stdin_stdout(void); esp_err_t example_configure_stdin_stdout(void);
/**
* @brief Returns esp-netif pointer created by example_connect()
*
* @note If multiple interfaces active at once, this API return NULL
* In that case the get_example_netif_from_desc() should be used
* to get esp-netif pointer based on interface description
*/
esp_netif_t *get_example_netif(void);
/** /**
* @brief Returns esp-netif pointer created by example_connect() described by * @brief Returns esp-netif pointer created by example_connect() described by
* the supplied desc field * the supplied desc field
@@ -79,7 +77,17 @@ esp_netif_t *get_example_netif(void);
*/ */
esp_netif_t *get_example_netif_from_desc(const char *desc); esp_netif_t *get_example_netif_from_desc(const char *desc);
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET #if CONFIG_EXAMPLE_PROVIDE_WIFI_CONSOLE_CMD
/**
* @brief Register wifi connect commands
*
* Provide a simple wifi_connect command in esp_console.
* This function can be used after esp_console is initialized.
*/
void example_register_wifi_connect_commands(void);
#endif
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
/** /**
* @brief Get the example Ethernet driver handle * @brief Get the example Ethernet driver handle
* *

View File

@@ -15,6 +15,10 @@
esp_err_t example_configure_stdin_stdout(void) esp_err_t example_configure_stdin_stdout(void)
{ {
static bool configured = false;
if (configured) {
return ESP_OK;
}
// Initialize VFS & UART so we can use std::cout/cin // Initialize VFS & UART so we can use std::cout/cin
setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdin, NULL, _IONBF, 0);
/* Install UART driver for interrupt-driven reads and writes */ /* Install UART driver for interrupt-driven reads and writes */
@@ -25,5 +29,6 @@ esp_err_t example_configure_stdin_stdout(void)
esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR); esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR);
/* Move the caret to the beginning of the next line on '\n' */ /* Move the caret to the beginning of the next line on '\n' */
esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF); esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF);
configured = true;
return ESP_OK; return ESP_OK;
} }

View File

@@ -0,0 +1,254 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection.
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "protocol_examples_common.h"
#include "example_common_private.h"
#include "esp_log.h"
#if CONFIG_EXAMPLE_CONNECT_WIFI
static const char *TAG = "example_connect";
static esp_netif_t *s_example_sta_netif = NULL;
static SemaphoreHandle_t s_semph_get_ip_addrs = NULL;
#if CONFIG_EXAMPLE_WIFI_SCAN_METHOD_FAST
#define EXAMPLE_WIFI_SCAN_METHOD WIFI_FAST_SCAN
#elif CONFIG_EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL
#define EXAMPLE_WIFI_SCAN_METHOD WIFI_ALL_CHANNEL_SCAN
#endif
#if CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL
#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL
#elif CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SECURITY
#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SECURITY
#endif
#if CONFIG_EXAMPLE_WIFI_AUTH_OPEN
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_EXAMPLE_WIFI_AUTH_WEP
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_WPA2_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_ENTERPRISE
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_ENTERPRISE
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA3_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_WPA3_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_EXAMPLE_WIFI_AUTH_WAPI_PSK
#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endif
static int s_retry_num = 0;
static void example_handler_on_wifi_disconnect(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
s_retry_num++;
if (s_retry_num > CONFIG_EXAMPLE_WIFI_CONN_MAX_RETRY) {
ESP_LOGI(TAG, "WiFi Connect failed %d times, stop reconnect.", s_retry_num);
if (s_semph_get_ip_addrs) {
/* let example_wifi_sta_do_connect() return */
xSemaphoreGive(s_semph_get_ip_addrs);
#if CONFIG_EXAMPLE_CONNECT_IPV6
xSemaphoreGive(s_semph_get_ip_addrs);
#endif
}
return;
}
ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect...");
esp_err_t err = esp_wifi_connect();
if (err == ESP_ERR_WIFI_NOT_STARTED) {
return;
}
ESP_ERROR_CHECK(err);
}
static void example_handler_on_wifi_connect(void *esp_netif, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
#if CONFIG_EXAMPLE_CONNECT_IPV6
esp_netif_create_ip6_linklocal(esp_netif);
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
}
static void example_handler_on_sta_got_ip(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
s_retry_num = 0;
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
if (!example_is_our_netif(EXAMPLE_NETIF_DESC_STA, event->esp_netif)) {
return;
}
ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
if (s_semph_get_ip_addrs) {
xSemaphoreGive(s_semph_get_ip_addrs);
} else {
ESP_LOGI(TAG, "- IPv4 address: " IPSTR ",", IP2STR(&event->ip_info.ip));
}
}
#if CONFIG_EXAMPLE_CONNECT_IPV6
static void example_handler_on_sta_got_ipv6(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
if (!example_is_our_netif(EXAMPLE_NETIF_DESC_STA, event->esp_netif)) {
return;
}
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
IPV62STR(event->ip6_info.ip), example_ipv6_addr_types_to_str[ipv6_type]);
if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) {
if (s_semph_get_ip_addrs) {
xSemaphoreGive(s_semph_get_ip_addrs);
} else {
ESP_LOGI(TAG, "- IPv6 address: " IPV6STR ", type: %s", IPV62STR(event->ip6_info.ip), example_ipv6_addr_types_to_str[ipv6_type]);
}
}
}
#endif // CONFIG_EXAMPLE_CONNECT_IPV6
void example_wifi_start(void)
{
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
// Warning: the interface desc is used in tests to capture actual connection details (IP, gw, mask)
esp_netif_config.if_desc = EXAMPLE_NETIF_DESC_STA;
esp_netif_config.route_prio = 128;
s_example_sta_netif = esp_netif_create_wifi(WIFI_IF_STA, &esp_netif_config);
esp_wifi_set_default_wifi_sta_handlers();
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_start());
}
void example_wifi_stop(void)
{
esp_err_t err = esp_wifi_stop();
if (err == ESP_ERR_WIFI_NOT_INIT) {
return;
}
ESP_ERROR_CHECK(err);
ESP_ERROR_CHECK(esp_wifi_deinit());
ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(s_example_sta_netif));
esp_netif_destroy(s_example_sta_netif);
s_example_sta_netif = NULL;
}
esp_err_t example_wifi_sta_do_connect(wifi_config_t wifi_config, bool wait)
{
if (wait) {
s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0);
}
s_retry_num = 0;
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &example_handler_on_wifi_disconnect, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &example_handler_on_sta_got_ip, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &example_handler_on_wifi_connect, s_example_sta_netif));
#if CONFIG_EXAMPLE_CONNECT_IPV6
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &example_handler_on_sta_got_ipv6, NULL));
#endif
ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid);
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
esp_err_t ret = esp_wifi_connect();
if (ret != ESP_OK) {
ESP_LOGE(TAG, "WiFi connect failed! ret:%x", ret);
return ret;
}
if (wait) {
ESP_LOGI(TAG, "Waiting for IP(s)");
for (int i = 0; i < NR_OF_IP_ADDRESSES_TO_WAIT_FOR; ++i) {
xSemaphoreTake(s_semph_get_ip_addrs, portMAX_DELAY);
}
if (s_retry_num > CONFIG_EXAMPLE_WIFI_CONN_MAX_RETRY) {
return ESP_FAIL;
}
}
return ESP_OK;
}
esp_err_t example_wifi_sta_do_disconnect(void)
{
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &example_handler_on_wifi_disconnect));
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &example_handler_on_sta_got_ip));
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &example_handler_on_wifi_connect));
#if CONFIG_EXAMPLE_CONNECT_IPV6
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &example_handler_on_sta_got_ipv6));
#endif
if (s_semph_get_ip_addrs) {
vSemaphoreDelete(s_semph_get_ip_addrs);
}
return esp_wifi_disconnect();
}
void example_wifi_shutdown(void)
{
example_wifi_sta_do_disconnect();
example_wifi_stop();
}
esp_err_t example_wifi_connect(void)
{
ESP_LOGI(TAG, "Start example_connect.");
example_wifi_start();
wifi_config_t wifi_config = {
.sta = {
#if !CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
.ssid = CONFIG_EXAMPLE_WIFI_SSID,
.password = CONFIG_EXAMPLE_WIFI_PASSWORD,
#endif
.scan_method = EXAMPLE_WIFI_SCAN_METHOD,
.sort_method = EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD,
.threshold.rssi = CONFIG_EXAMPLE_WIFI_SCAN_RSSI_THRESHOLD,
.threshold.authmode = EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD,
},
};
#if CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN
example_configure_stdin_stdout();
char buf[sizeof(wifi_config.sta.ssid)+sizeof(wifi_config.sta.password)+2] = {0};
ESP_LOGI(TAG, "Please input ssid password:");
fgets(buf, sizeof(buf), stdin);
int len = strlen(buf);
buf[len-1] = '\0'; /* removes '\n' */
memset(wifi_config.sta.ssid, 0, sizeof(wifi_config.sta.ssid));
char *rest = NULL;
char *temp = strtok_r(buf, " ", &rest);
strncpy((char*)wifi_config.sta.ssid, temp, sizeof(wifi_config.sta.ssid));
memset(wifi_config.sta.password, 0, sizeof(wifi_config.sta.password));
temp = strtok_r(NULL, " ", &rest);
if (temp) {
strncpy((char*)wifi_config.sta.password, temp, sizeof(wifi_config.sta.password));
} else {
wifi_config.sta.threshold.authmode = WIFI_AUTH_OPEN;
}
#endif
return example_wifi_sta_do_connect(wifi_config, true);
}
#endif /* CONFIG_EXAMPLE_CONNECT_WIFI */

View File

@@ -14,7 +14,9 @@ import re
import subprocess import subprocess
import time import time
import netifaces
import ttfw_idf import ttfw_idf
from common_test_methods import get_env_config_variable, get_host_ip_by_interface
from idf_iperf_test_util import IperfUtility from idf_iperf_test_util import IperfUtility
from tiny_test_fw import TinyFW from tiny_test_fw import TinyFW
@@ -53,14 +55,15 @@ class IperfTestUtilityEth(IperfUtility.IperfTestUtility):
return dut_ip, rssi return dut_ip, rssi
@ttfw_idf.idf_example_test(env_tag='Example_Ethernet') @ttfw_idf.idf_example_test(env_tag='ethernet_router')
def test_ethernet_throughput_basic(env, _): # type: (Any, Any) -> None def test_ethernet_throughput_basic(env, _): # type: (Any, Any) -> None
""" """
steps: | steps: |
1. test TCP tx rx and UDP tx rx throughput 1. test TCP tx rx and UDP tx rx throughput
2. compare with the pre-defined pass standard 2. compare with the pre-defined pass standard
""" """
pc_nic_ip = env.get_pc_nic_info('pc_nic', 'ipv4')['addr'] pc_nic = get_env_config_variable('wifi_router', 'pc_nic', default='eth1')
pc_nic_ip = get_host_ip_by_interface(pc_nic, netifaces.AF_INET)
pc_iperf_log_file = os.path.join(env.log_path, 'pc_iperf_log.md') pc_iperf_log_file = os.path.join(env.log_path, 'pc_iperf_log.md')
# 1. get DUT # 1. get DUT

View File

@@ -1,52 +0,0 @@
# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
from __future__ import unicode_literals
import re
from typing import Any
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols')
def test_examples_simple_sniffer(env, _): # type: (Any, Any) -> None
dut = env.get_dut('simple_sniffer', 'examples/network/simple_sniffer', app_config_name='mem')
dut.start_app()
dut.expect('sniffer>')
dut.write('pcap --open -f simple-sniffer')
dut.expect('cmd_pcap: open file successfully')
dut.write('sniffer -i wlan -c 2 -n 10')
dut.expect('cmd_sniffer: 10 packages will be captured')
dut.expect('cmd_sniffer: start WiFi promiscuous ok')
dut.expect('cmd_sniffer: stop promiscuous ok')
dut.write('pcap --summary -f simple-sniffer')
dut.expect('cmd_pcap: Memory is to be parsed')
dut.expect('Pcap packet Head:')
dut.expect('Magic Number: a1b2c3d4')
dut.expect(re.compile(r'Major Version: [0-9]*'))
dut.expect(re.compile(r'Minor Version: [0-9]*'))
dut.expect(re.compile(r'SnapLen: [0-9]*'))
dut.expect(re.compile(r'LinkType: [0-9]*'))
for i in range(0, 10):
dut.expect('Packet ' + str(i) + ':')
dut.expect(re.compile(r'Timestamp \(Seconds\): [0-9]*'))
dut.expect(re.compile(r'Timestamp \(Microseconds\): [0-9]*'))
dut.expect(re.compile(r'Capture Length: [0-9]*'))
dut.expect(re.compile(r'Packet Length: [0-9]*'))
dut.expect(re.compile(r'Frame Type: .*'))
dut.expect(re.compile(r'Frame Subtype: .*'))
dut.expect(re.compile(r'Destination: .*'))
dut.expect(re.compile(r'Source: .*'))
dut.expect('Pcap packet Number: 10')
dut.write('pcap --close -f simple-sniffer')
dut.expect('cmd_pcap: free memory successfully')
dut.expect('cmd_pcap: .pcap file close done')
dut.write('')
dut.expect('sniffer>')
if __name__ == '__main__':
test_examples_simple_sniffer()

View File

@@ -0,0 +1,47 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.wifi_ap
@pytest.mark.parametrize('config', [
'mem',
], indirect=True)
def test_examples_simple_sniffer(dut: Dut) -> None:
sniffer_num = 9
dut.expect('sniffer>')
dut.write('pcap --open -f simple-sniffer')
dut.expect('cmd_pcap: open file successfully')
dut.write(f'sniffer -i wlan -c 2 -n {sniffer_num}')
dut.expect(f'cmd_sniffer: {sniffer_num} packages will be captured')
dut.expect('cmd_sniffer: start WiFi promiscuous ok')
dut.expect('cmd_sniffer: stop promiscuous ok')
dut.write('pcap --summary -f simple-sniffer')
dut.expect('cmd_pcap: Memory is to be parsed')
dut.expect('Pcap packet Head:')
dut.expect('Magic Number: a1b2c3d4')
dut.expect(r'Major Version: [0-9]+')
dut.expect(r'Minor Version: [0-9]+')
dut.expect(r'SnapLen: [0-9]+')
dut.expect(r'LinkType: [0-9]+')
# Allow "save captured packet failed" twice
for i in range(0, sniffer_num - 2):
dut.expect(f'Packet {i}:')
dut.expect(r'Timestamp \(Seconds\): [0-9]+')
dut.expect(r'Timestamp \(Microseconds\): [0-9]+')
dut.expect(r'Capture Length: [0-9]+')
dut.expect(r'Packet Length: [0-9]+')
dut.expect(r'Frame Type:\s+\w+')
dut.expect(r'Frame Subtype:\s+\w+')
dut.expect(r'Destination:\s+\w+')
dut.expect(r'Source:\s+\w+')
dut.expect(r'Pcap packet Number: [7-9]')
dut.write('pcap --close -f simple-sniffer')
dut.expect('cmd_pcap: free memory successfully')
dut.expect('cmd_pcap: .pcap file close done')
dut.write('')
dut.expect('sniffer>')

View File

@@ -108,7 +108,7 @@ examples/protocols/https_x509_bundle:
examples/protocols/icmp_echo: examples/protocols/icmp_echo:
disable_test: disable_test:
- if: IDF_TARGET != "esp32" - if: IDF_TARGET == "esp32c2"
temporary: true temporary: true
reason: lack of runners reason: lack of runners

View File

@@ -8,7 +8,7 @@ See the [README.md](../README.md) file in the upper level [examples](../) direct
### About the `example_connect()` Function ### About the `example_connect()` Function
Protocols examples use a simple helper function, `example_connect()`, to establish Wi-Fi and/or Ethernet connection. This function is implemented in [examples/common_components/protocol_examples/common/connect.c](../common_components/protocol_examples_common/connect.c), and has a very simple behavior: block until connection is established and IP address is obtained, then return. This function is used to reduce the amount of boilerplate and to keep the example code focused on the protocol or library being demonstrated. Protocols examples use a simple helper function, `example_connect()`, to establish Wi-Fi and/or Ethernet connection. This function is implemented in [examples/common_components/protocol_examples_common/include/protocol_examples_common.h](../common_components/protocol_examples_common/include/protocol_examples_common.h), and has a very simple behavior: block until connection is established and IP address is obtained, then return. This function is used to reduce the amount of boilerplate and to keep the example code focused on the protocol or library being demonstrated.
The simple `example_connect()` function does not handle timeouts, does not gracefully handle various error conditions, and is only suited for use in examples. When developing real applications, this helper function needs to be replaced with full Wi-Fi / Ethernet connection handling code. Such code can be found in [examples/wifi/getting_started/](../wifi/getting_started) and [examples/ethernet/basic/](../ethernet/basic) examples. The simple `example_connect()` function does not handle timeouts, does not gracefully handle various error conditions, and is only suited for use in examples. When developing real applications, this helper function needs to be replaced with full Wi-Fi / Ethernet connection handling code. Such code can be found in [examples/wifi/getting_started/](../wifi/getting_started) and [examples/ethernet/basic/](../ethernet/basic) examples.

View File

@@ -9,7 +9,7 @@ from pytest_embedded import Dut
@pytest.mark.supported_targets @pytest.mark.supported_targets
@pytest.mark.wifi @pytest.mark.generic
def test_examples_cbor(dut: Dut) -> None: def test_examples_cbor(dut: Dut) -> None:
dut.expect(r'example: encoded buffer size \d+') dut.expect(r'example: encoded buffer size \d+')

View File

@@ -2,5 +2,9 @@
# in this exact order for cmake to work correctly # in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp_local_ctrl) project(esp_local_ctrl)

View File

@@ -1,20 +0,0 @@
menu "Example Configuration"
config EXAMPLE_WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) for the example to connect to.
config EXAMPLE_WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) for the example to use.
config EXAMPLE_MAXIMUM_RETRY
int "Maximum retry"
default 5
help
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
endmenu

View File

@@ -17,110 +17,13 @@
#include "esp_log.h" #include "esp_log.h"
#include "nvs_flash.h" #include "nvs_flash.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "protocol_examples_common.h"
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/sys.h" #include "lwip/sys.h"
/* The examples use WiFi configuration that you can set via 'idf.py menuconfig'.
If you'd rather not, just change the below entries to strings with
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID CONFIG_EXAMPLE_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_EXAMPLE_WIFI_PASSWORD
#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_EXAMPLE_MAXIMUM_RETRY
/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;
/* The event group allows multiple bits for each event, but we only care about two events:
* - we are connected to the AP with an IP
* - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
static const char *TAG = "local_ctrl_example"; static const char *TAG = "local_ctrl_example";
static int s_retry_num = 0;
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
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) {
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
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;
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
esp_err_t wifi_init_sta(void)
{
esp_err_t ret_value = ESP_OK;
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
assert(sta_netif);
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, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
wifi_config_t wifi_config = {
.sta = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.password = EXAMPLE_ESP_WIFI_PASS
},
};
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 is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
* happened. */
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
} else if (bits & WIFI_FAIL_BIT) {
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
ret_value = ESP_FAIL;
} else {
ESP_LOGE(TAG, "UNEXPECTED EVENT");
ret_value = ESP_ERR_INVALID_STATE;
}
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler));
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler));
vEventGroupDelete(s_wifi_event_group);
return ret_value;
}
/* Function responsible for configuring and starting the esp_local_ctrl service. /* Function responsible for configuring and starting the esp_local_ctrl service.
* See local_ctrl_service.c for implementation */ * See local_ctrl_service.c for implementation */
@@ -135,9 +38,10 @@ void app_main(void)
ret = nvs_flash_init(); ret = nvs_flash_init();
} }
ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(ret);
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); if (example_connect() == ESP_OK) {
if (wifi_init_sta() == ESP_OK) {
start_esp_local_ctrl_service(); start_esp_local_ctrl_service();
} else { } else {
ESP_LOGI(TAG, "Connection failed, not starting esp_local_ctrl service"); ESP_LOGI(TAG, "Connection failed, not starting esp_local_ctrl service");

View File

@@ -9,6 +9,7 @@ import sys
import pexpect import pexpect
import pytest import pytest
from common_test_methods import get_env_config_variable
from pytest_embedded import Dut from pytest_embedded import Dut
@@ -39,13 +40,19 @@ class CustomProcess(object):
@pytest.mark.supported_targets @pytest.mark.supported_targets
@pytest.mark.wifi @pytest.mark.wifi_router
def test_examples_esp_local_ctrl(dut: Dut) -> None: def test_examples_esp_local_ctrl(dut: Dut) -> None:
rel_project_path = os.path.join('examples', 'protocols', 'esp_local_ctrl') rel_project_path = os.path.join('examples', 'protocols', 'esp_local_ctrl')
idf_path = get_sdk_path() idf_path = get_sdk_path()
dut_ip = dut.expect(r'esp_netif_handlers: sta ip: (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')[1].decode() if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
dut_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]')[1].decode()
dut.expect('esp_https_server: Starting server') dut.expect('esp_https_server: Starting server')
dut.expect('esp_https_server: Server listening on port 443') dut.expect('esp_https_server: Server listening on port 443')
dut.expect('control: esp_local_ctrl service started with name : my_esp_ctrl_device') dut.expect('control: esp_local_ctrl service started with name : my_esp_ctrl_device')

View File

@@ -0,0 +1 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y

View File

@@ -17,6 +17,7 @@ except ModuleNotFoundError:
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'tools', 'ci', 'python_packages')) sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'tools', 'ci', 'python_packages'))
from idf_http_server_test import test as client from idf_http_server_test import test as client
from common_test_methods import get_env_config_variable
from pytest_embedded import Dut from pytest_embedded import Dut
# When running on local machine execute the following before running this script # When running on local machine execute the following before running this script
@@ -35,7 +36,7 @@ from pytest_embedded import Dut
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi @pytest.mark.wifi_router
def test_examples_protocol_http_server_advanced(dut: Dut) -> None: def test_examples_protocol_http_server_advanced(dut: Dut) -> None:
# Get binary file # Get binary file
@@ -47,7 +48,13 @@ def test_examples_protocol_http_server_advanced(dut: Dut) -> None:
# Parse IP address of STA # Parse IP address of STA
logging.info('Waiting to connect with AP') logging.info('Waiting to connect with AP')
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode() if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
got_port = dut.expect(r"(?:[\s\S]*)Started HTTP server on port: '(\d+)'", timeout=30)[1].decode() got_port = dut.expect(r"(?:[\s\S]*)Started HTTP server on port: '(\d+)'", timeout=30)[1].decode()

View File

@@ -0,0 +1 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y

View File

@@ -72,7 +72,7 @@ def test_captive_page(ip: str, port: str, uri: str) -> bool:
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi_bt @pytest.mark.wifi_wlan
@pytest.mark.xfail(reason='Runner unable to connect to target over WiFi', run=False) @pytest.mark.xfail(reason='Runner unable to connect to target over WiFi', run=False)
def test_example_captive_portal(dut: Dut) -> None: def test_example_captive_portal(dut: Dut) -> None:

View File

@@ -38,7 +38,7 @@ def test_examples_protocol_http_server_file_serving(dut: Dut) -> None:
dut.expect('Initializing SPIFFS', timeout=30) dut.expect('Initializing SPIFFS', timeout=30)
# Parse IP address of STA # Parse IP address of STA
logging.info('Waiting to connect with AP') logging.info('Waiting to connect with AP')
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode() got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
# Expected logs # Expected logs
got_port = dut.expect(r"Starting HTTP Server on port: '(\d+)'", timeout=30)[1].decode() got_port = dut.expect(r"Starting HTTP Server on port: '(\d+)'", timeout=30)[1].decode()
logging.info('Got IP : {}'.format(got_ip)) logging.info('Got IP : {}'.format(got_ip))

View File

@@ -19,6 +19,7 @@ except ModuleNotFoundError:
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'tools', 'ci', 'python_packages')) sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'tools', 'ci', 'python_packages'))
from idf_http_server_test import adder as client from idf_http_server_test import adder as client
from common_test_methods import get_env_config_variable
from pytest_embedded import Dut from pytest_embedded import Dut
# When running on local machine execute the following before running this script # When running on local machine execute the following before running this script
@@ -30,7 +31,7 @@ from pytest_embedded import Dut
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi @pytest.mark.wifi_router
def test_examples_protocol_http_server_persistence(dut: Dut) -> None: def test_examples_protocol_http_server_persistence(dut: Dut) -> None:
# Get binary file # Get binary file
@@ -43,7 +44,13 @@ def test_examples_protocol_http_server_persistence(dut: Dut) -> None:
# Parse IP address of STA # Parse IP address of STA
logging.info('Waiting to connect with AP') logging.info('Waiting to connect with AP')
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode() if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
got_port = dut.expect(r"(?:[\s\S]*)Starting server on port: '(\d+)'", timeout=30)[1].decode() got_port = dut.expect(r"(?:[\s\S]*)Starting server on port: '(\d+)'", timeout=30)[1].decode()
logging.info('Got IP : {}'.format(got_ip)) logging.info('Got IP : {}'.format(got_ip))

View File

@@ -0,0 +1 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y

View File

@@ -23,6 +23,7 @@ except ModuleNotFoundError:
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'tools', 'ci', 'python_packages')) sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'tools', 'ci', 'python_packages'))
from idf_http_server_test import client from idf_http_server_test import client
from common_test_methods import get_env_config_variable
from pytest_embedded import Dut from pytest_embedded import Dut
@@ -62,7 +63,7 @@ class http_client_thread(threading.Thread):
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi @pytest.mark.wifi_router
def test_examples_protocol_http_server_simple(dut: Dut) -> None: def test_examples_protocol_http_server_simple(dut: Dut) -> None:
# Get binary file # Get binary file
@@ -75,7 +76,13 @@ def test_examples_protocol_http_server_simple(dut: Dut) -> None:
# Parse IP address of STA # Parse IP address of STA
logging.info('Waiting to connect with AP') logging.info('Waiting to connect with AP')
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode() if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(' '.join([ap_ssid, ap_password]))
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
got_port = dut.expect(r"(?:[\s\S]*)Starting server on port: '(\d+)'", timeout=30)[1].decode() got_port = dut.expect(r"(?:[\s\S]*)Starting server on port: '(\d+)'", timeout=30)[1].decode()
logging.info('Got IP : {}'.format(got_ip)) logging.info('Got IP : {}'.format(got_ip))
@@ -130,7 +137,7 @@ def test_examples_protocol_http_server_simple(dut: Dut) -> None:
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi @pytest.mark.wifi_router
def test_examples_protocol_http_server_lru_purge_enable(dut: Dut) -> None: def test_examples_protocol_http_server_lru_purge_enable(dut: Dut) -> None:
# Get binary file # Get binary file
@@ -143,7 +150,13 @@ def test_examples_protocol_http_server_lru_purge_enable(dut: Dut) -> None:
# Parse IP address of STA # Parse IP address of STA
logging.info('Waiting to connect with AP') logging.info('Waiting to connect with AP')
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode() if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
got_port = dut.expect(r"(?:[\s\S]*)Starting server on port: '(\d+)'", timeout=30)[1].decode() got_port = dut.expect(r"(?:[\s\S]*)Starting server on port: '(\d+)'", timeout=30)[1].decode()
logging.info('Got IP : {}'.format(got_ip)) logging.info('Got IP : {}'.format(got_ip))

View File

@@ -1 +1,2 @@
CONFIG_EXAMPLE_BASIC_AUTH=y CONFIG_EXAMPLE_BASIC_AUTH=y
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y

View File

@@ -9,6 +9,7 @@ import logging
import os import os
import pytest import pytest
from common_test_methods import get_env_config_variable
from pytest_embedded import Dut from pytest_embedded import Dut
try: try:
@@ -51,7 +52,7 @@ class WsClient:
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi @pytest.mark.wifi_router
def test_examples_protocol_http_ws_echo_server(dut: Dut) -> None: def test_examples_protocol_http_ws_echo_server(dut: Dut) -> None:
# Get binary file # Get binary file
binary_file = os.path.join(dut.app.binary_path, 'ws_echo_server.bin') binary_file = os.path.join(dut.app.binary_path, 'ws_echo_server.bin')
@@ -62,7 +63,13 @@ def test_examples_protocol_http_ws_echo_server(dut: Dut) -> None:
# Parse IP address of STA # Parse IP address of STA
logging.info('Waiting to connect with AP') logging.info('Waiting to connect with AP')
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode() if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
got_port = dut.expect(r"Starting server on port: '(\d+)'", timeout=30)[1].decode() got_port = dut.expect(r"Starting server on port: '(\d+)'", timeout=30)[1].decode()
logging.info('Got IP : {}'.format(got_ip)) logging.info('Got IP : {}'.format(got_ip))

View File

@@ -1 +1,2 @@
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y

View File

@@ -10,28 +10,11 @@ from typing import Callable
import pexpect import pexpect
import pytest import pytest
from common_test_methods import get_host_ip4_by_dest_ip
from pytest_embedded import Dut from pytest_embedded import Dut
from RangeHTTPServer import RangeRequestHandler from RangeHTTPServer import RangeRequestHandler
def get_my_ip() -> str:
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.connect(('8.8.8.8', 80))
my_ip = ''
my_ip = s1.getsockname()[0]
s1.close()
return my_ip
def get_server_status(host_ip: str, port: int) -> bool:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_status = sock.connect_ex((host_ip, port))
sock.close()
if server_status == 0:
return True
return False
def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]: def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]:
""" """
Returns a request handler class that handles broken pipe exception Returns a request handler class that handles broken pipe exception
@@ -85,28 +68,26 @@ def test_examples_protocol_https_request_cli_session_tickets(dut: Dut) -> None:
binary_file = os.path.join(dut.app.binary_path, 'https_request.bin') binary_file = os.path.join(dut.app.binary_path, 'https_request.bin')
bin_size = os.path.getsize(binary_file) bin_size = os.path.getsize(binary_file)
logging.info('https_request_bin_size : {}KB'.format(bin_size // 1024)) logging.info('https_request_bin_size : {}KB'.format(bin_size // 1024))
# start test # start https server
host_ip = get_my_ip()
server_port = 8070 server_port = 8070
server_file = os.path.join(os.path.dirname(__file__), 'main', 'local_server_cert.pem') server_file = os.path.join(os.path.dirname(__file__), 'main', 'local_server_cert.pem')
key_file = os.path.join(os.path.dirname(__file__), 'main', 'local_server_key.pem') key_file = os.path.join(os.path.dirname(__file__), 'main', 'local_server_key.pem')
if (get_server_status(host_ip, server_port) is False): thread1 = multiprocessing.Process(target=start_https_server, args=(server_file, key_file, '0.0.0.0', server_port))
thread1 = multiprocessing.Process(target=start_https_server, args=(server_file, key_file, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
logging.info('The server started on {}:{}'.format(host_ip, server_port)) logging.info('The server started on localhost:{}'.format(server_port))
try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: (\d+\.\d+\.\d+\.\d+)', timeout=60)[2].decode() ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=60)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Start https_request example', timeout=30) dut.expect('Start https_request example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port))) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port)))
dut.write('https://' + host_ip + ':' + str(server_port)) dut.write('https://' + host_ip + ':' + str(server_port))
logging.info("Testing for \"https_request using saved session\"") logging.info("Testing for \"https_request using saved session\"")
@@ -132,6 +113,7 @@ def test_examples_protocol_https_request_cli_session_tickets(dut: Dut) -> None:
raise raise
logging.info("Passed the test for \"https_request using saved client session\"") logging.info("Passed the test for \"https_request using saved client session\"")
finally:
thread1.terminate() thread1.terminate()
@@ -150,10 +132,10 @@ def test_examples_protocol_https_request_dynamic_buffers(dut: Dut) -> None:
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: (\d+\.\d+\.\d+\.\d+)', timeout=60)[2].decode() ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=60)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
# only check if one connection is established # only check if one connection is established
logging.info("Testing for \"https_request using crt bundle\" with mbedtls dynamic resource enabled") logging.info("Testing for \"https_request using crt bundle\" with mbedtls dynamic resource enabled")
@@ -188,10 +170,10 @@ def test_examples_protocol_https_request(dut: Dut) -> None:
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: (\d+\.\d+\.\d+\.\d+)', timeout=60)[2].decode() ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=60)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
# Check for connection using crt bundle # Check for connection using crt bundle
logging.info("Testing for \"https_request using crt bundle\"") logging.info("Testing for \"https_request using crt bundle\"")

View File

@@ -9,6 +9,7 @@ import os
import ssl import ssl
import pytest import pytest
from common_test_methods import get_env_config_variable
from pytest_embedded import Dut from pytest_embedded import Dut
server_cert_pem = '-----BEGIN CERTIFICATE-----\n'\ server_cert_pem = '-----BEGIN CERTIFICATE-----\n'\
@@ -93,7 +94,7 @@ success_response = '<h1>Hello Secure World!</h1>'
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi @pytest.mark.wifi_router
def test_examples_protocol_https_server_simple(dut: Dut) -> None: def test_examples_protocol_https_server_simple(dut: Dut) -> None:
""" """
steps: | steps: |
@@ -106,12 +107,17 @@ def test_examples_protocol_https_server_simple(dut: Dut) -> None:
bin_size = os.path.getsize(binary_file) bin_size = os.path.getsize(binary_file)
logging.info('https_server_simple_bin_size : {}KB'.format(bin_size // 1024)) logging.info('https_server_simple_bin_size : {}KB'.format(bin_size // 1024))
# start test # start test
logging.info('Waiting to connect with AP')
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
# Parse IP address and port of the server # Parse IP address and port of the server
dut.expect(r'Starting server') dut.expect(r'Starting server')
got_port = int(dut.expect(r'Server listening on port (\d+)', timeout=30)[1].decode()) got_port = int(dut.expect(r'Server listening on port (\d+)', timeout=30)[1].decode())
logging.info('Waiting to connect with AP') got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode()
# Expected logs # Expected logs
@@ -152,8 +158,8 @@ def test_examples_protocol_https_server_simple(dut: Dut) -> None:
logging.info('Checking user callback: Obtaining client certificate...') logging.info('Checking user callback: Obtaining client certificate...')
serial_number = dut.expect(r'serial number(.*)', timeout=5)[0] serial_number = dut.expect(r'serial number\s*:([^\n]*)', timeout=5)[0]
issuer_name = dut.expect(r'issuer name(.*)', timeout=5)[0] issuer_name = dut.expect(r'issuer name\s*:([^\n]*)', timeout=5)[0]
expiry = dut.expect(r'expires on ((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode() expiry = dut.expect(r'expires on ((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode()
logging.info('Serial No. {}'.format(serial_number)) logging.info('Serial No. {}'.format(serial_number))
@@ -168,18 +174,23 @@ def test_examples_protocol_https_server_simple(dut: Dut) -> None:
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi @pytest.mark.wifi_router
@pytest.mark.parametrize('config', ['dynamic_buffer',], indirect=True) @pytest.mark.parametrize('config', ['dynamic_buffer',], indirect=True)
def test_examples_protocol_https_server_simple_dynamic_buffers(dut: Dut) -> None: def test_examples_protocol_https_server_simple_dynamic_buffers(dut: Dut) -> None:
# Test with mbedTLS dynamic buffer feature # Test with mbedTLS dynamic buffer feature
# start test # start test
logging.info('Waiting to connect with AP')
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
# Parse IP address and port of the server # Parse IP address and port of the server
dut.expect(r'Starting server') dut.expect(r'Starting server')
got_port = int(dut.expect(r'Server listening on port (\d+)', timeout=30)[1].decode()) got_port = int(dut.expect(r'Server listening on port (\d+)', timeout=30)[1].decode())
logging.info('Waiting to connect with AP') got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode()
# Expected logs # Expected logs
@@ -219,9 +230,9 @@ def test_examples_protocol_https_server_simple_dynamic_buffers(dut: Dut) -> None
logging.info('Checking user callback: Obtaining client certificate...') logging.info('Checking user callback: Obtaining client certificate...')
serial_number = dut.expect(r'serial number(.*)', timeout=5)[0] serial_number = dut.expect(r'serial number\s*:([^\n]*)', timeout=5)[0]
issuer_name = dut.expect(r'issuer name(.*)', timeout=5)[0] issuer_name = dut.expect(r'issuer name\s*:([^\n]*)', timeout=5)[0]
expiry = dut.expect(r'expires on ((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode() expiry = dut.expect(r'expires on\s*:((.*)\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*)', timeout=5)[1].decode()
logging.info('Serial No. : {}'.format(serial_number)) logging.info('Serial No. : {}'.format(serial_number))
logging.info('Issuer Name : {}'.format(issuer_name)) logging.info('Issuer Name : {}'.format(issuer_name))

View File

@@ -1,2 +1,3 @@
CONFIG_ESP_HTTPS_SERVER_ENABLE=y CONFIG_ESP_HTTPS_SERVER_ENABLE=y
CONFIG_EXAMPLE_ENABLE_HTTPS_USER_CALLBACK=y CONFIG_EXAMPLE_ENABLE_HTTPS_USER_CALLBACK=y
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y

View File

@@ -1,5 +1,6 @@
CONFIG_ESP_HTTPS_SERVER_ENABLE=y CONFIG_ESP_HTTPS_SERVER_ENABLE=y
CONFIG_EXAMPLE_ENABLE_HTTPS_USER_CALLBACK=y CONFIG_EXAMPLE_ENABLE_HTTPS_USER_CALLBACK=y
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT=y CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT=y

View File

@@ -14,6 +14,7 @@ from typing import Any, Optional
import pytest import pytest
import websocket import websocket
from common_test_methods import get_env_config_variable
from pytest_embedded import Dut from pytest_embedded import Dut
OPCODE_TEXT = 0x1 OPCODE_TEXT = 0x1
@@ -109,7 +110,7 @@ def test_multiple_client_keep_alive_and_async_response(ip, port, ca_file): # ty
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi @pytest.mark.wifi_router
def test_examples_protocol_https_wss_server(dut: Dut) -> None: def test_examples_protocol_https_wss_server(dut: Dut) -> None:
# Get binary file # Get binary file
@@ -119,11 +120,16 @@ def test_examples_protocol_https_wss_server(dut: Dut) -> None:
logging.info('Starting wss_server test app') logging.info('Starting wss_server test app')
logging.info('Waiting to connect with AP')
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
# Parse IP address of STA # Parse IP address of STA
got_port = int(dut.expect(r'Server listening on port (\d+)', timeout=30)[1].decode()) got_port = int(dut.expect(r'Server listening on port (\d+)', timeout=30)[1].decode())
logging.info('Waiting to connect with AP') got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30)[1].decode()
logging.info('Got IP : {}'.format(got_ip)) logging.info('Got IP : {}'.format(got_ip))
logging.info('Got Port : {}'.format(got_port)) logging.info('Got Port : {}'.format(got_port))
@@ -140,7 +146,7 @@ def test_examples_protocol_https_wss_server(dut: Dut) -> None:
opcode, data = ws.read() opcode, data = ws.read()
data = data.decode('UTF-8') data = data.decode('UTF-8')
if data != DATA: if data != DATA:
raise RuntimeError('Failed to receive the correct echo response') raise RuntimeError(f'Failed to receive the correct echo response.')
logging.info('Correct echo response obtained from the wss server') logging.info('Correct echo response obtained from the wss server')
# Test for PING # Test for PING

View File

@@ -0,0 +1 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y

View File

@@ -4,6 +4,7 @@ import logging
import os import os
import pytest import pytest
from common_test_methods import get_env_config_variable
from pytest_embedded import Dut from pytest_embedded import Dut
@@ -11,7 +12,7 @@ from pytest_embedded import Dut
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi @pytest.mark.wifi_ap
def test_examples_protocol_https_x509_bundle(dut: Dut) -> None: def test_examples_protocol_https_x509_bundle(dut: Dut) -> None:
""" """
steps: | steps: |
@@ -23,6 +24,14 @@ def test_examples_protocol_https_x509_bundle(dut: Dut) -> None:
binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin') binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin')
bin_size = os.path.getsize(binary_file) bin_size = os.path.getsize(binary_file)
logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024)) logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024))
# Connect to AP
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_ap'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)
# start test # start test
num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode()) num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode())
dut.expect(r'Connection established to ([\s\S]*)', timeout=30) dut.expect(r'Connection established to ([\s\S]*)', timeout=30)
@@ -33,7 +42,7 @@ def test_examples_protocol_https_x509_bundle(dut: Dut) -> None:
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi @pytest.mark.wifi_ap
@pytest.mark.parametrize('config', ['ssldyn',], indirect=True) @pytest.mark.parametrize('config', ['ssldyn',], indirect=True)
def test_examples_protocol_https_x509_bundle_dynamic_buffer(dut: Dut) -> None: def test_examples_protocol_https_x509_bundle_dynamic_buffer(dut: Dut) -> None:
# test mbedtls dynamic resource # test mbedtls dynamic resource
@@ -41,6 +50,14 @@ def test_examples_protocol_https_x509_bundle_dynamic_buffer(dut: Dut) -> None:
binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin') binary_file = os.path.join(dut.app.binary_path, 'https_x509_bundle.bin')
bin_size = os.path.getsize(binary_file) bin_size = os.path.getsize(binary_file)
logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024)) logging.info('https_x509_bundle_bin_size : {}KB'.format(bin_size // 1024))
# Connect to AP
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_ap'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)
# start test # start test
num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode()) num_URLS = int(dut.expect(r'Connecting to (\d+) URLs', timeout=30)[1].decode())
dut.expect(r'Connection established to ([\s\S]*)', timeout=30) dut.expect(r'Connection established to ([\s\S]*)', timeout=30)

View File

@@ -1,3 +1,4 @@
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE=y CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE=y
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs"
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y

View File

@@ -4,3 +4,4 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs"
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
CONFIG_MBEDTLS_DYNAMIC_FREE_PEER_CERT=y CONFIG_MBEDTLS_DYNAMIC_FREE_PEER_CERT=y
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y

View File

@@ -1,33 +0,0 @@
from __future__ import unicode_literals
import os
import re
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols')
def test_examples_icmp_echo(env, extra_data):
dut = env.get_dut('icmp_echo', 'examples/protocols/icmp_echo')
dut.start_app()
dut.expect('example_connect: Connected to')
dut.expect('esp>')
ping_dest = os.getenv('EXAMPLE_ICMP_SERVER', 'www.espressif.com')
dut.write('ping {}'.format(ping_dest))
ip_re = r'\.'.join((r'\d{1,3}',) * 4)
ip = dut.expect(re.compile(r'64 bytes from ({}) icmp_seq=1 ttl=\d+ time=\d+ ms'.format(ip_re)))[0]
# expect at least one more (there could be lost packets)
dut.expect(re.compile(r'64 bytes from {} icmp_seq=[2-5] ttl=\d+ time='.format(ip)))
dut.expect(re.compile(r'5 packets transmitted, [2-5] received, \d{1,3}% packet loss'))
dut.write('')
dut.expect('esp>')
if __name__ == '__main__':
test_examples_icmp_echo()

View File

@@ -199,8 +199,6 @@ void app_main(void)
ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_event_loop_create_default());
/* wait for active network connection */
ESP_ERROR_CHECK(example_connect());
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
// install console REPL environment // install console REPL environment
@@ -215,6 +213,8 @@ void app_main(void)
ESP_ERROR_CHECK(esp_console_new_repl_usb_serial_jtag(&usbjtag_config, &repl_config, &repl)); ESP_ERROR_CHECK(esp_console_new_repl_usb_serial_jtag(&usbjtag_config, &repl_config, &repl));
#endif #endif
/* register wifi connect commands */
example_register_wifi_connect_commands();
/* register command `ping` */ /* register command `ping` */
register_ping(); register_ping();
/* register command `quit` */ /* register command `quit` */

View File

@@ -0,0 +1,38 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import os
import pytest
from common_test_methods import get_env_config_variable
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32c3
@pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.wifi_ap
def test_protocols_icmp_echo(dut: Dut) -> None:
# get env config
sdkconfig_ssid = dut.app.sdkconfig.get('CONFIG_EXAMPLE_WIFI_SSID')
sdkconfig_pwd = dut.app.sdkconfig.get('CONFIG_EXAMPLE_WIFI_SSID')
env_name = 'wifi_ap'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid', default=sdkconfig_ssid)
ap_password = get_env_config_variable(env_name, 'ap_password', default=sdkconfig_pwd)
ap_channel = get_env_config_variable(env_name, 'ap_channel', default=0)
dut.expect('esp>')
dut.write(f'wifi_connect {ap_ssid} {ap_password} -n {ap_channel}')
dut.expect('Got IPv4 event:', timeout=30)
ping_dest = os.getenv('EXAMPLE_ICMP_SERVER', 'ci.espressif.cn')
dut.write('ping {} -c 5'.format(ping_dest))
# expect at least two packets (there could be lost packets)
ip = dut.expect(r'64 bytes from (\d+\.\d+\.\d+\.\d+) icmp_seq=\d ttl=\d+ time=\d+ ms')[1].decode()
dut.expect(fr'64 bytes from {ip} icmp_seq=[2-5] ttl=\d+ time=')
dut.expect(r'5 packets transmitted, [2-5] received, \d{1,3}% packet loss')
dut.write('')
dut.expect('esp>')

View File

@@ -29,8 +29,8 @@ STACK_PAR_OK = 6
STACK_PAR_FAIL = 7 STACK_PAR_FAIL = 7
STACK_DESTROY = 8 STACK_DESTROY = 8
pattern_dict_slave = {STACK_IPV4: (r'.*I \([0-9]+\) example_connect: - IPv4 address: ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*'), pattern_dict_slave = {STACK_IPV4: (r'.*I \([0-9]+\) example_common: - IPv4 address: ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*'),
STACK_IPV6: (r'.*I \([0-9]+\) example_connect: - IPv6 address: (([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}).*'), STACK_IPV6: (r'.*I \([0-9]+\) example_common: - IPv6 address: (([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}).*'),
STACK_INIT: (r'.*I \(([0-9]+)\) MB_TCP_SLAVE_PORT: (Protocol stack initialized).'), STACK_INIT: (r'.*I \(([0-9]+)\) MB_TCP_SLAVE_PORT: (Protocol stack initialized).'),
STACK_CONNECT: (r'.*I\s\(([0-9]+)\) MB_TCP_SLAVE_PORT: Socket \(#[0-9]+\), accept client connection from address: ' STACK_CONNECT: (r'.*I\s\(([0-9]+)\) MB_TCP_SLAVE_PORT: Socket \(#[0-9]+\), accept client connection from address: '
r'([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*'), r'([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*'),
@@ -40,8 +40,8 @@ pattern_dict_slave = {STACK_IPV4: (r'.*I \([0-9]+\) example_connect: - IPv4 addr
STACK_PAR_FAIL: (r'.*E \(([0-9]+)\) SLAVE_TEST: Response time exceeds configured [0-9]+ [ms], ignore packet.*'), STACK_PAR_FAIL: (r'.*E \(([0-9]+)\) SLAVE_TEST: Response time exceeds configured [0-9]+ [ms], ignore packet.*'),
STACK_DESTROY: (r'.*I\s\(([0-9]+)\) SLAVE_TEST: (Modbus controller destroyed).')} STACK_DESTROY: (r'.*I\s\(([0-9]+)\) SLAVE_TEST: (Modbus controller destroyed).')}
pattern_dict_master = {STACK_IPV4: (r'.*I \([0-9]+\) example_connect: - IPv4 address: ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*'), pattern_dict_master = {STACK_IPV4: (r'.*I \([0-9]+\) example_common: - IPv4 address: ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*'),
STACK_IPV6: (r'.*I \([0-9]+\) example_connect: - IPv6 address: (([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}).*'), STACK_IPV6: (r'.*I \([0-9]+\) example_common: - IPv6 address: (([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}).*'),
STACK_INIT: (r'.*I \(([0-9]+)\) MASTER_TEST: (Modbus master stack initialized).*'), STACK_INIT: (r'.*I \(([0-9]+)\) MASTER_TEST: (Modbus master stack initialized).*'),
STACK_CONNECT: (r'.*.*I\s\(([0-9]+)\) MB_TCP_MASTER_PORT: (Connected [0-9]+ slaves), start polling.*'), STACK_CONNECT: (r'.*.*I\s\(([0-9]+)\) MB_TCP_MASTER_PORT: (Connected [0-9]+ slaves), start polling.*'),
STACK_START: (r'.*I \(([0-9]+)\) MASTER_TEST: (Start modbus test).*'), STACK_START: (r'.*I \(([0-9]+)\) MASTER_TEST: (Start modbus test).*'),

View File

@@ -58,7 +58,7 @@ def on_message(client, userdata, msg):
message_log += 'Received data:' + msg.topic + ' ' + payload + '\n' message_log += 'Received data:' + msg.topic + ' ' + payload + '\n'
@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') @ttfw_idf.idf_example_test(env_tag='ethernet_router')
def test_examples_protocol_mqtt_ssl(env, extra_data): def test_examples_protocol_mqtt_ssl(env, extra_data):
broker_url = '' broker_url = ''
broker_port = 0 broker_port = 0
@@ -110,7 +110,7 @@ def test_examples_protocol_mqtt_ssl(env, extra_data):
raise ValueError('ENV_TEST_FAILURE: Test script cannot connect to broker: {}'.format(broker_url)) raise ValueError('ENV_TEST_FAILURE: Test script cannot connect to broker: {}'.format(broker_url))
dut1.start_app() dut1.start_app()
try: try:
ip_address = dut1.expect(re.compile(r' eth ip: ([^,]+),'), timeout=30) ip_address = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]'), timeout=30)[0]
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP with IP: {}'.format(ip_address))
except DUT.ExpectTimeout: except DUT.ExpectTimeout:
print('ENV_TEST_FAILURE: Cannot connect to AP') print('ENV_TEST_FAILURE: Cannot connect to AP')

View File

@@ -7,19 +7,12 @@ import time
from threading import Thread from threading import Thread
import ttfw_idf import ttfw_idf
from common_test_methods import get_host_ip4_by_dest_ip
from tiny_test_fw import DUT from tiny_test_fw import DUT
msgid = -1 msgid = -1
def get_my_ip():
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.connect(('8.8.8.8', 80))
my_ip = s1.getsockname()[0]
s1.close()
return my_ip
def mqqt_server_sketch(my_ip, port): def mqqt_server_sketch(my_ip, port):
global msgid global msgid
print('Starting the server on {}'.format(my_ip)) print('Starting the server on {}'.format(my_ip))
@@ -53,7 +46,7 @@ def mqqt_server_sketch(my_ip, port):
print('server closed') print('server closed')
@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') @ttfw_idf.idf_example_test(env_tag='ethernet_router')
def test_examples_protocol_mqtt_qos1(env, extra_data): def test_examples_protocol_mqtt_qos1(env, extra_data):
global msgid global msgid
""" """
@@ -68,18 +61,19 @@ def test_examples_protocol_mqtt_qos1(env, extra_data):
binary_file = os.path.join(dut1.app.binary_path, 'mqtt_tcp.bin') binary_file = os.path.join(dut1.app.binary_path, 'mqtt_tcp.bin')
bin_size = os.path.getsize(binary_file) bin_size = os.path.getsize(binary_file)
ttfw_idf.log_performance('mqtt_tcp_bin_size', '{}KB'.format(bin_size // 1024)) ttfw_idf.log_performance('mqtt_tcp_bin_size', '{}KB'.format(bin_size // 1024))
# 1. start mqtt broker sketch # 1. start the dut test and wait till client gets IP address
host_ip = get_my_ip()
thread1 = Thread(target=mqqt_server_sketch, args=(host_ip,1883))
thread1.start()
# 2. start the dut test and wait till client gets IP address
dut1.start_app() dut1.start_app()
# waiting for getting the IP address # waiting for getting the IP address
try: try:
ip_address = dut1.expect(re.compile(r' (sta|eth) ip: ([^,]+),'), timeout=30) ip_address = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]'), timeout=30)[0]
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except DUT.ExpectTimeout: except DUT.ExpectTimeout:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
# 2. start mqtt broker sketch
host_ip = get_host_ip4_by_dest_ip(ip_address)
thread1 = Thread(target=mqqt_server_sketch, args=(host_ip,1883))
thread1.start()
print('writing to device: {}'.format('mqtt://' + host_ip + '\n')) print('writing to device: {}'.format('mqtt://' + host_ip + '\n'))
dut1.write('mqtt://' + host_ip + '\n') dut1.write('mqtt://' + host_ip + '\n')

View File

@@ -39,7 +39,7 @@ def on_message(client, userdata, msg):
message_log += 'Received data:' + msg.topic + ' ' + payload + '\n' message_log += 'Received data:' + msg.topic + ' ' + payload + '\n'
@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') @ttfw_idf.idf_example_test(env_tag='ethernet_router')
def test_examples_protocol_mqtt_ws(env, extra_data): def test_examples_protocol_mqtt_ws(env, extra_data):
broker_url = '' broker_url = ''
broker_port = 0 broker_port = 0
@@ -83,7 +83,7 @@ def test_examples_protocol_mqtt_ws(env, extra_data):
raise ValueError('ENV_TEST_FAILURE: Test script cannot connect to broker: {}'.format(broker_url)) raise ValueError('ENV_TEST_FAILURE: Test script cannot connect to broker: {}'.format(broker_url))
dut1.start_app() dut1.start_app()
try: try:
ip_address = dut1.expect(re.compile(r' eth ip: ([^,]+),'), timeout=30) ip_address = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]'), timeout=30)[0]
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP with IP: {}'.format(ip_address))
except DUT.ExpectTimeout: except DUT.ExpectTimeout:
print('ENV_TEST_FAILURE: Cannot connect to AP') print('ENV_TEST_FAILURE: Cannot connect to AP')

View File

@@ -40,7 +40,7 @@ def on_message(client, userdata, msg):
message_log += 'Received data:' + msg.topic + ' ' + payload + '\n' message_log += 'Received data:' + msg.topic + ' ' + payload + '\n'
@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') @ttfw_idf.idf_example_test(env_tag='ethernet_router')
def test_examples_protocol_mqtt_wss(env, extra_data): def test_examples_protocol_mqtt_wss(env, extra_data):
broker_url = '' broker_url = ''
broker_port = 0 broker_port = 0
@@ -87,7 +87,7 @@ def test_examples_protocol_mqtt_wss(env, extra_data):
raise ValueError('ENV_TEST_FAILURE: Test script cannot connect to broker: {}'.format(broker_url)) raise ValueError('ENV_TEST_FAILURE: Test script cannot connect to broker: {}'.format(broker_url))
dut1.start_app() dut1.start_app()
try: try:
ip_address = dut1.expect(re.compile(r' eth ip: ([^,]+),'), timeout=30) ip_address = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]'), timeout=30)[0]
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP with IP: {}'.format(ip_address))
except DUT.ExpectTimeout: except DUT.ExpectTimeout:
print('ENV_TEST_FAILURE: Cannot connect to AP') print('ENV_TEST_FAILURE: Cannot connect to AP')

View File

@@ -1,51 +0,0 @@
from __future__ import unicode_literals
import datetime
import re
import ttfw_idf
from tiny_test_fw import Utility
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols')
def test_examples_sntp(env, extra_data):
dut = env.get_dut('sntp', 'examples/protocols/sntp')
dut.start_app()
dut.expect_all('Time is not set yet. Connecting to WiFi and getting time over NTP.',
'Initializing SNTP',
re.compile(r'Waiting for system time to be set... \(\d+/\d+\)'),
'Notification of a time synchronization event',
timeout=60)
TIME_FORMAT = '%a %b %d %H:%M:%S %Y'
TIME_FORMAT_REGEX = r'\w+\s+\w+\s+\d{1,2}\s+\d{2}:\d{2}:\d{2} \d{4}'
TIME_DIFF = datetime.timedelta(seconds=10 + 2) # cpu spends 10 seconds in deep sleep
NY_time = None
SH_time = None
def check_time(prev_NY_time, prev_SH_time):
NY_str = dut.expect(re.compile(r'The current date/time in New York is: ({})'.format(TIME_FORMAT_REGEX)))[0]
SH_str = dut.expect(re.compile(r'The current date/time in Shanghai is: ({})'.format(TIME_FORMAT_REGEX)))[0]
Utility.console_log('New York: "{}"'.format(NY_str))
Utility.console_log('Shanghai: "{}"'.format(SH_str))
dut.expect('Entering deep sleep for 10 seconds')
Utility.console_log('Sleeping...')
new_NY_time = datetime.datetime.strptime(NY_str, TIME_FORMAT)
new_SH_time = datetime.datetime.strptime(SH_str, TIME_FORMAT)
# The initial time is not checked because datetime has problems with timezones
assert prev_NY_time is None or new_NY_time - prev_NY_time < TIME_DIFF
assert prev_SH_time is None or new_SH_time - prev_SH_time < TIME_DIFF
return (new_NY_time, new_SH_time)
NY_time, SH_time = check_time(NY_time, SH_time)
for i in range(2, 4):
dut.expect('example: Boot count: {}'.format(i), timeout=30)
NY_time, SH_time = check_time(NY_time, SH_time)
if __name__ == '__main__':
test_examples_sntp()

View File

@@ -0,0 +1,54 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import datetime
import logging
from typing import Any, Tuple
import pytest
from common_test_methods import get_env_config_variable
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.wifi_ap
def test_get_time_from_sntp_server(dut: Dut) -> None:
dut.expect('Time is not set yet. Connecting to WiFi and getting time over NTP.')
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
dut.expect('Please input ssid password:')
env_name = 'wifi_ap'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
dut.expect('IPv4 address:')
dut.expect('Initializing SNTP')
dut.expect(r'Waiting for system time to be set... \(\d+/\d+\)')
dut.expect('Notification of a time synchronization event')
TIME_FORMAT = '%a %b %d %H:%M:%S %Y'
TIME_FORMAT_REGEX = r'\w+\s+\w+\s+\d{1,2}\s+\d{2}:\d{2}:\d{2} \d{4}'
TIME_DIFF = datetime.timedelta(seconds=10 + 2) # cpu spends 10 seconds in deep sleep
NY_time = None
SH_time = None
def check_time(prev_NY_time: Any, prev_SH_time: Any) -> Tuple[Any, Any]:
NY_str = dut.expect(r'The current date/time in New York is: ({})'.format(TIME_FORMAT_REGEX))[1].decode()
SH_str = dut.expect(r'The current date/time in Shanghai is: ({})'.format(TIME_FORMAT_REGEX))[1].decode()
logging.info('New York: "{}"'.format(NY_str))
logging.info('Shanghai: "{}"'.format(SH_str))
dut.expect('Entering deep sleep for 10 seconds')
logging.info('Sleeping...')
new_NY_time = datetime.datetime.strptime(NY_str, TIME_FORMAT)
new_SH_time = datetime.datetime.strptime(SH_str, TIME_FORMAT)
# The initial time is not checked because datetime has problems with timezones
assert not prev_NY_time or new_NY_time - prev_NY_time < TIME_DIFF
assert not prev_SH_time or new_SH_time - prev_SH_time < TIME_DIFF
return (new_NY_time, new_SH_time)
NY_time, SH_time = check_time(NY_time, SH_time)
for i in range(2, 4):
dut.expect('example: Boot count: {}'.format(i), timeout=30)
NY_time, SH_time = check_time(NY_time, SH_time)

View File

@@ -1,2 +1,3 @@
CONFIG_SNTP_TIME_SERVER="time.windows.com" CONFIG_SNTP_TIME_SERVER="time.windows.com"
CONFIG_LWIP_SNTP_MAX_SERVERS=2 CONFIG_LWIP_SNTP_MAX_SERVERS=2
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y

View File

@@ -17,18 +17,13 @@ from threading import Event, Thread
import netifaces import netifaces
import ttfw_idf import ttfw_idf
from common_test_methods import get_env_config_variable, get_host_ip_by_interface, get_my_interface_by_dest_ip
# ----------- Config ---------- # ----------- Config ----------
PORT = 3333 PORT = 3333
INTERFACE = 'eth0'
# ------------------------------- # -------------------------------
def get_my_ip(type):
for i in netifaces.ifaddresses(INTERFACE)[type]:
return i['addr'].replace('%{}'.format(INTERFACE), '')
class TcpServer: class TcpServer:
def __init__(self, port, family_addr, persist=False): def __init__(self, port, family_addr, persist=False):
@@ -85,7 +80,7 @@ class TcpServer:
break break
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') @ttfw_idf.idf_example_test(env_tag='wifi_router')
def test_examples_protocol_socket_tcpclient(env, extra_data): def test_examples_protocol_socket_tcpclient(env, extra_data):
""" """
steps: steps:
@@ -101,21 +96,28 @@ def test_examples_protocol_socket_tcpclient(env, extra_data):
# start test # start test
dut1.start_app() dut1.start_app()
if dut1.app.get_sdkconfig_config_value('CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN'):
dut1.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut1.write(f'{ap_ssid} {ap_password}')
ipv4 = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)[0] ipv4 = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]'), timeout=30)[0]
ipv6_r = r':'.join((r'[0-9a-fA-F]{4}',) * 8) # expect all 8 octets from IPv6 (assumes it's printed in the long form) ipv6_r = r':'.join((r'[0-9a-fA-F]{4}',) * 8) # expect all 8 octets from IPv6 (assumes it's printed in the long form)
ipv6 = dut1.expect(re.compile(r' IPv6 address: ({})'.format(ipv6_r)), timeout=30)[0] ipv6 = dut1.expect(re.compile(r' IPv6 address: ({})'.format(ipv6_r)), timeout=30)[0]
print('Connected with IPv4={} and IPv6={}'.format(ipv4, ipv6)) print('Connected with IPv4={} and IPv6={}'.format(ipv4, ipv6))
my_interface = get_my_interface_by_dest_ip(ipv4)
# test IPv4 # test IPv4
with TcpServer(PORT, socket.AF_INET): with TcpServer(PORT, socket.AF_INET):
server_ip = get_my_ip(netifaces.AF_INET) server_ip = get_host_ip_by_interface(my_interface, netifaces.AF_INET)
print('Connect tcp client to server IP={}'.format(server_ip)) print('Connect tcp client to server IP={}'.format(server_ip))
dut1.write(server_ip) dut1.write(server_ip)
dut1.expect(re.compile(r'OK: Message from ESP32')) dut1.expect(re.compile(r'OK: Message from ESP32'))
# test IPv6 # test IPv6
with TcpServer(PORT, socket.AF_INET6): with TcpServer(PORT, socket.AF_INET6):
server_ip = get_my_ip(netifaces.AF_INET6) server_ip = get_host_ip_by_interface(my_interface, netifaces.AF_INET6)
print('Connect tcp client to server IP={}'.format(server_ip)) print('Connect tcp client to server IP={}'.format(server_ip))
dut1.write(server_ip) dut1.write(server_ip)
dut1.expect(re.compile(r'OK: Message from ESP32')) dut1.expect(re.compile(r'OK: Message from ESP32'))

View File

@@ -1 +1,2 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN=y CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN=y

View File

@@ -14,10 +14,10 @@ import socket
import sys import sys
import ttfw_idf import ttfw_idf
from common_test_methods import get_env_config_variable, get_my_interface_by_dest_ip
# ----------- Config ---------- # ----------- Config ----------
PORT = 3333 PORT = 3333
INTERFACE = 'eth0'
# ------------------------------- # -------------------------------
@@ -46,7 +46,7 @@ def tcp_client(address, payload):
return data.decode() return data.decode()
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') @ttfw_idf.idf_example_test(env_tag='wifi_router')
def test_examples_protocol_socket_tcpserver(env, extra_data): def test_examples_protocol_socket_tcpserver(env, extra_data):
MESSAGE = 'Data to ESP' MESSAGE = 'Data to ESP'
""" """
@@ -63,19 +63,26 @@ def test_examples_protocol_socket_tcpserver(env, extra_data):
# start test # start test
dut1.start_app() dut1.start_app()
if dut1.app.get_sdkconfig_config_value('CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN'):
dut1.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut1.write(f'{ap_ssid} {ap_password}')
ipv4 = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)[0] ipv4 = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]'), timeout=30)[0]
ipv6_r = r':'.join((r'[0-9a-fA-F]{4}',) * 8) # expect all 8 octets from IPv6 (assumes it's printed in the long form) ipv6_r = r':'.join((r'[0-9a-fA-F]{4}',) * 8) # expect all 8 octets from IPv6 (assumes it's printed in the long form)
ipv6 = dut1.expect(re.compile(r' IPv6 address: ({})'.format(ipv6_r)), timeout=30)[0] ipv6 = dut1.expect(re.compile(r' IPv6 address: ({})'.format(ipv6_r)), timeout=30)[0]
print('Connected with IPv4={} and IPv6={}'.format(ipv4, ipv6)) print('Connected with IPv4={} and IPv6={}'.format(ipv4, ipv6))
interface = get_my_interface_by_dest_ip(ipv4)
# test IPv4 # test IPv4
received = tcp_client(ipv4, MESSAGE) received = tcp_client(ipv4, MESSAGE)
if not received == MESSAGE: if not received == MESSAGE:
raise raise
dut1.expect(MESSAGE) dut1.expect(MESSAGE)
# test IPv6 # test IPv6
received = tcp_client('{}%{}'.format(ipv6, INTERFACE), MESSAGE) received = tcp_client('{}%{}'.format(ipv6, interface), MESSAGE)
if not received == MESSAGE: if not received == MESSAGE:
raise raise
dut1.expect(MESSAGE) dut1.expect(MESSAGE)

View File

@@ -1,2 +1,3 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
CONFIG_EXAMPLE_IPV4=y CONFIG_EXAMPLE_IPV4=y
CONFIG_EXAMPLE_IPV6=y CONFIG_EXAMPLE_IPV6=y

View File

@@ -1,3 +1,4 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
CONFIG_EXAMPLE_IPV4=y CONFIG_EXAMPLE_IPV4=y
CONFIG_EXAMPLE_IPV6=n CONFIG_EXAMPLE_IPV6=n
CONFIG_EXAMPLE_CONNECT_IPV6=n CONFIG_EXAMPLE_CONNECT_IPV6=n

View File

@@ -17,18 +17,14 @@ from threading import Event, Thread
import netifaces import netifaces
import ttfw_idf import ttfw_idf
from common_test_methods import get_env_config_variable, get_host_ip_by_interface, get_my_interface_by_dest_ip
from tiny_test_fw.DUT import ExpectTimeout
# ----------- Config ---------- # ----------- Config ----------
PORT = 3333 PORT = 3333
INTERFACE = 'eth0'
# ------------------------------- # -------------------------------
def get_my_ip(type):
for i in netifaces.ifaddresses(INTERFACE)[type]:
return i['addr'].replace('%{}'.format(INTERFACE), '')
class UdpServer: class UdpServer:
def __init__(self, port, family_addr, persist=False): def __init__(self, port, family_addr, persist=False):
@@ -65,6 +61,7 @@ class UdpServer:
while not self.shutdown.is_set(): while not self.shutdown.is_set():
try: try:
data, addr = self.socket.recvfrom(1024) data, addr = self.socket.recvfrom(1024)
print(addr)
if not data: if not data:
return return
data = data.decode() data = data.decode()
@@ -78,7 +75,7 @@ class UdpServer:
break break
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') @ttfw_idf.idf_example_test(env_tag='wifi_router')
def test_examples_protocol_socket_udpclient(env, extra_data): def test_examples_protocol_socket_udpclient(env, extra_data):
""" """
steps: steps:
@@ -94,24 +91,45 @@ def test_examples_protocol_socket_udpclient(env, extra_data):
# start test # start test
dut1.start_app() dut1.start_app()
if dut1.app.get_sdkconfig_config_value('CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN'):
dut1.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut1.write(f'{ap_ssid} {ap_password}')
ipv4 = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)[0] ipv4 = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]'), timeout=30)[0]
ipv6_r = r':'.join((r'[0-9a-fA-F]{4}',) * 8) # expect all 8 octets from IPv6 (assumes it's printed in the long form) ipv6_r = r':'.join((r'[0-9a-fA-F]{4}',) * 8) # expect all 8 octets from IPv6 (assumes it's printed in the long form)
ipv6 = dut1.expect(re.compile(r' IPv6 address: ({})'.format(ipv6_r)), timeout=30)[0] ipv6 = dut1.expect(re.compile(r' IPv6 address: ({})'.format(ipv6_r)), timeout=30)[0]
print('Connected with IPv4={} and IPv6={}'.format(ipv4, ipv6)) print('Connected with IPv4={} and IPv6={}'.format(ipv4, ipv6))
my_interface = get_my_interface_by_dest_ip(ipv4)
# test IPv4 # test IPv4
with UdpServer(PORT, socket.AF_INET): with UdpServer(PORT, socket.AF_INET):
server_ip = get_my_ip(netifaces.AF_INET) server_ip = get_host_ip_by_interface(my_interface, netifaces.AF_INET)
print('Connect udp client to server IP={}'.format(server_ip)) print('Connect udp client to server IP={}'.format(server_ip))
for _ in range(3):
try:
dut1.write(server_ip) dut1.write(server_ip)
dut1.expect(re.compile(r'OK: Message from ESP32')) dut1.expect(re.compile(r'OK: Message from ESP32'))
break
except ExpectTimeout:
pass
else:
raise ValueError('Failed to send/recv udp packets.')
# test IPv6 # test IPv6
with UdpServer(PORT, socket.AF_INET6): with UdpServer(PORT, socket.AF_INET6):
server_ip = get_my_ip(netifaces.AF_INET6) server_ip = get_host_ip_by_interface(my_interface, netifaces.AF_INET6)
print('Connect udp client to server IP={}'.format(server_ip)) print('Connect udp client to server IP={}'.format(server_ip))
for _ in range(3):
try:
dut1.write(server_ip) dut1.write(server_ip)
dut1.expect(re.compile(r'OK: Message from ESP32')) dut1.expect(re.compile(r'OK: Message from ESP32'))
break
except ExpectTimeout:
pass
else:
raise ValueError('Failed to send/recv udp packets.')
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -73,6 +73,13 @@ static void udp_client_task(void *pvParameters)
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
break; break;
} }
// Set timeout
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);
ESP_LOGI(TAG, "Socket created, sending to %s:%d", HOST_IP_ADDR, PORT); ESP_LOGI(TAG, "Socket created, sending to %s:%d", HOST_IP_ADDR, PORT);
while (1) { while (1) {

View File

@@ -1 +1,2 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN=y CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN=y

View File

@@ -14,10 +14,10 @@ import socket
import sys import sys
import ttfw_idf import ttfw_idf
from common_test_methods import get_env_config_variable, get_my_interface_by_dest_ip
# ----------- Config ---------- # ----------- Config ----------
PORT = 3333 PORT = 3333
INTERFACE = 'eth0'
# ------------------------------- # -------------------------------
@@ -49,7 +49,7 @@ def udp_client(address, payload):
return reply.decode() return reply.decode()
@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') @ttfw_idf.idf_example_test(env_tag='wifi_router')
def test_examples_protocol_socket_udpserver(env, extra_data): def test_examples_protocol_socket_udpserver(env, extra_data):
MESSAGE = 'Data to ESP' MESSAGE = 'Data to ESP'
MAX_RETRIES = 3 MAX_RETRIES = 3
@@ -67,13 +67,20 @@ def test_examples_protocol_socket_udpserver(env, extra_data):
# start test # start test
dut1.start_app() dut1.start_app()
if dut1.app.get_sdkconfig_config_value('CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN'):
dut1.expect('Please input ssid password:')
env_name = 'wifi_router'
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut1.write(f'{ap_ssid} {ap_password}')
ipv4 = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)[0] ipv4 = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]'), timeout=30)[0]
ipv6_r = r':'.join((r'[0-9a-fA-F]{4}',) * 8) # expect all 8 octets from IPv6 (assumes it's printed in the long form) ipv6_r = r':'.join((r'[0-9a-fA-F]{4}',) * 8) # expect all 8 octets from IPv6 (assumes it's printed in the long form)
ipv6 = dut1.expect(re.compile(r' IPv6 address: ({})'.format(ipv6_r)), timeout=30)[0] ipv6 = dut1.expect(re.compile(r' IPv6 address: ({})'.format(ipv6_r)), timeout=30)[0]
print('Connected with IPv4={} and IPv6={}'.format(ipv4, ipv6)) print('Connected with IPv4={} and IPv6={}'.format(ipv4, ipv6))
dut1.expect(re.compile(r'Waiting for data'), timeout=10) dut1.expect(re.compile(r'Waiting for data'), timeout=10)
interface = get_my_interface_by_dest_ip(ipv4)
# test IPv4 # test IPv4
for _ in range(MAX_RETRIES): for _ in range(MAX_RETRIES):
print('Testing UDP on IPv4...') print('Testing UDP on IPv4...')
@@ -88,7 +95,7 @@ def test_examples_protocol_socket_udpserver(env, extra_data):
# test IPv6 # test IPv6
for _ in range(MAX_RETRIES): for _ in range(MAX_RETRIES):
print('Testing UDP on IPv6...') print('Testing UDP on IPv6...')
received = udp_client('{}%{}'.format(ipv6, INTERFACE), MESSAGE) received = udp_client('{}%{}'.format(ipv6, interface), MESSAGE)
if received == MESSAGE: if received == MESSAGE:
print('OK') print('OK')
break break

View File

@@ -71,6 +71,11 @@ static void udp_server_task(void *pvParameters)
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
} }
#endif #endif
// Set timeout
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);
int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err < 0) { if (err < 0) {

View File

@@ -1,2 +1,3 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
CONFIG_EXAMPLE_IPV4=y CONFIG_EXAMPLE_IPV4=y
CONFIG_EXAMPLE_IPV6=y CONFIG_EXAMPLE_IPV6=y

View File

@@ -86,12 +86,14 @@ cp ca_cert.pem /path/to/ota/example/server_certs/
### Internal workflow of the OTA Example ### Internal workflow of the OTA Example
After booting, the firmware prints "Starting OTA example" to the console and: After booting, the firmware:
1. Connects via Ethernet or to the AP using the provided SSID and password (Wi-Fi case) 1. prints "OTA example app_main start" to the console
2. Connects to the HTTPS server and downloads the new image 2. Connects via Ethernet or to the AP using the provided SSID and password (Wi-Fi case)
3. Writes the image to flash, and instructs the bootloader to boot from this image after the next reset 3. prints "Starting OTA example task" to the console
4. Reboots 4. Connects to the HTTPS server and downloads the new image
5. Writes the image to flash, and instructs the bootloader to boot from this image after the next reset
6. Reboots
If you want to rollback to the `factory` app after the upgrade (or to the first OTA partition in case the `factory` partition does not exist), run the command `idf.py erase_otadata`. This restores the `ota_data` partition to its initial state. If you want to rollback to the `factory` app after the upgrade (or to the first OTA partition in case the `factory` partition does not exist), run the command `idf.py erase_otadata`. This restores the `ota_data` partition to its initial state.

View File

@@ -176,6 +176,7 @@ ota_end:
void app_main(void) void app_main(void)
{ {
ESP_LOGI(TAG, "OTA example app_main start");
// Initialize NVS. // Initialize NVS.
esp_err_t err = nvs_flash_init(); esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {

View File

@@ -8,10 +8,12 @@ import socket
import ssl import ssl
import struct import struct
import subprocess import subprocess
import time
from typing import Callable from typing import Callable
import pexpect import pexpect
import pytest import pytest
from common_test_methods import get_env_config_variable, get_host_ip4_by_dest_ip
from pytest_embedded import Dut from pytest_embedded import Dut
from RangeHTTPServer import RangeRequestHandler from RangeHTTPServer import RangeRequestHandler
@@ -19,15 +21,6 @@ server_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_cer
key_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_certs/server_key.pem') key_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_certs/server_key.pem')
def get_my_ip() -> str:
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.connect(('8.8.8.8', 80))
my_ip = ''
my_ip = s1.getsockname()[0]
s1.close()
return my_ip
def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]: def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]:
""" """
Returns a request handler class that handles broken pipe exception Returns a request handler class that handles broken pipe exception
@@ -110,32 +103,33 @@ def test_examples_protocol_advanced_https_ota_example(dut: Dut) -> None:
This is a positive test case, which downloads complete binary file multiple number of times. This is a positive test case, which downloads complete binary file multiple number of times.
Number of iterations can be specified in variable iterations. Number of iterations can be specified in variable iterations.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
try:
# Number of iterations to validate OTA # Number of iterations to validate OTA
iterations = 3 iterations = 3
server_port = 8001 server_port = 8001
bin_name = 'advanced_https_ota.bin' bin_name = 'advanced_https_ota.bin'
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
for i in range(iterations):
dut.expect('Loaded app from partition at offset', timeout=60)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) # start test
print('Connected to AP with IP: {}'.format(ip_address)) for _ in range(iterations):
dut.expect('Loaded app from partition at offset', timeout=30)
try:
ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
dut.expect('Starting Advanced OTA example', timeout=30) dut.expect('Starting Advanced OTA example', timeout=30)
host_ip = get_host_ip4_by_dest_ip(ip_address)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)
dut.expect('upgrade successful. Rebooting ...', timeout=60)
finally: finally:
thread1.terminate() thread1.terminate()
@@ -150,12 +144,11 @@ def test_examples_protocol_advanced_https_ota_example_truncated_bin(dut: Dut) ->
Working of OTA if binary file is truncated is validated in this test case. Working of OTA if binary file is truncated is validated in this test case.
Application should return with error message in this case. Application should return with error message in this case.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Generate truncated binary file 2. Generate truncated binary file
3. Fetch OTA image over HTTPS 3. Fetch OTA image over HTTPS
4. Check working of code if bin is truncated 4. Check working of code if bin is truncated
""" """
try:
server_port = 8001 server_port = 8001
# Original binary file generated after compilation # Original binary file generated after compilation
bin_name = 'advanced_https_ota.bin' bin_name = 'advanced_https_ota.bin'
@@ -168,21 +161,21 @@ def test_examples_protocol_advanced_https_ota_example_truncated_bin(dut: Dut) ->
with open(binary_file, 'rb+') as f: with open(binary_file, 'rb+') as f:
with open(os.path.join(dut.app.binary_path, truncated_bin_name), 'wb+') as fo: with open(os.path.join(dut.app.binary_path, truncated_bin_name), 'wb+') as fo:
fo.write(f.read(truncated_bin_size)) fo.write(f.read(truncated_bin_size))
binary_file = os.path.join(dut.app.binary_path, truncated_bin_name) binary_file = os.path.join(dut.app.binary_path, truncated_bin_name)
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
dut.expect('Starting Advanced OTA example', timeout=30) dut.expect('Starting Advanced OTA example', timeout=30)
host_ip = get_host_ip4_by_dest_ip(ip_address)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name)
@@ -205,12 +198,11 @@ def test_examples_protocol_advanced_https_ota_example_truncated_header(dut: Dut)
Working of OTA if headers of binary file are truncated is vaildated in this test case. Working of OTA if headers of binary file are truncated is vaildated in this test case.
Application should return with error message in this case. Application should return with error message in this case.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Generate binary file with truncated headers 2. Generate binary file with truncated headers
3. Fetch OTA image over HTTPS 3. Fetch OTA image over HTTPS
4. Check working of code if headers are not sent completely 4. Check working of code if headers are not sent completely
""" """
try:
server_port = 8001 server_port = 8001
# Original binary file generated after compilation # Original binary file generated after compilation
bin_name = 'advanced_https_ota.bin' bin_name = 'advanced_https_ota.bin'
@@ -223,22 +215,22 @@ def test_examples_protocol_advanced_https_ota_example_truncated_header(dut: Dut)
with open(binary_file, 'rb+') as f: with open(binary_file, 'rb+') as f:
with open(os.path.join(dut.app.binary_path, truncated_bin_name), 'wb+') as fo: with open(os.path.join(dut.app.binary_path, truncated_bin_name), 'wb+') as fo:
fo.write(f.read(truncated_bin_size)) fo.write(f.read(truncated_bin_size))
binary_file = os.path.join(dut.app.binary_path, truncated_bin_name) binary_file = os.path.join(dut.app.binary_path, truncated_bin_name)
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting Advanced OTA example', timeout=30)
dut.expect('Starting Advanced OTA example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name)
dut.expect('advanced_https_ota_example: esp_https_ota_read_img_desc failed', timeout=30) dut.expect('advanced_https_ota_example: esp_https_ota_read_img_desc failed', timeout=30)
@@ -260,12 +252,11 @@ def test_examples_protocol_advanced_https_ota_example_random(dut: Dut) -> None:
Working of OTA if random data is added in binary file are validated in this test case. Working of OTA if random data is added in binary file are validated in this test case.
Magic byte verification should fail in this case. Magic byte verification should fail in this case.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Generate random binary image 2. Generate random binary image
3. Fetch OTA image over HTTPS 3. Fetch OTA image over HTTPS
4. Check working of code for random binary file 4. Check working of code for random binary file
""" """
try:
server_port = 8001 server_port = 8001
# Random binary file to be generated # Random binary file to be generated
random_bin_name = 'random.bin' random_bin_name = 'random.bin'
@@ -279,21 +270,21 @@ def test_examples_protocol_advanced_https_ota_example_random(dut: Dut) -> None:
fo.write(struct.pack('B', 0)) fo.write(struct.pack('B', 0))
for i in range(random_bin_size - 1): for i in range(random_bin_size - 1):
fo.write(struct.pack('B', random.randrange(0,255,1))) fo.write(struct.pack('B', random.randrange(0,255,1)))
# Start server
# start test thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
host_ip = get_my_ip()
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting Advanced OTA example', timeout=30)
dut.expect('Starting Advanced OTA example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name)
dut.expect(r'esp_https_ota: Incorrect app descriptor magic', timeout=10) dut.expect(r'esp_https_ota: Incorrect app descriptor magic', timeout=10)
@@ -315,12 +306,11 @@ def test_examples_protocol_advanced_https_ota_example_invalid_chip_id(dut: Dut)
Working of OTA if binary file have invalid chip id is validated in this test case. Working of OTA if binary file have invalid chip id is validated in this test case.
Chip id verification should fail in this case. Chip id verification should fail in this case.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Generate binary image with invalid chip id 2. Generate binary image with invalid chip id
3. Fetch OTA image over HTTPS 3. Fetch OTA image over HTTPS
4. Check working of code for random binary file 4. Check working of code for random binary file
""" """
try:
server_port = 8001 server_port = 8001
bin_name = 'advanced_https_ota.bin' bin_name = 'advanced_https_ota.bin'
# Random binary file to be generated # Random binary file to be generated
@@ -336,21 +326,21 @@ def test_examples_protocol_advanced_https_ota_example_invalid_chip_id(dut: Dut)
data[13] = 0xfe data[13] = 0xfe
with open(random_binary_file, 'wb+') as fo: with open(random_binary_file, 'wb+') as fo:
fo.write(bytearray(data)) fo.write(bytearray(data))
# Start server
# start test thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
host_ip = get_my_ip()
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting Advanced OTA example', timeout=30)
dut.expect('Starting Advanced OTA example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name)
dut.expect(r'esp_https_ota: Mismatch chip id, expected 0, found \d', timeout=10) dut.expect(r'esp_https_ota: Mismatch chip id, expected 0, found \d', timeout=10)
@@ -372,29 +362,31 @@ def test_examples_protocol_advanced_https_ota_example_chunked(dut: Dut) -> None:
This is a positive test case, which downloads complete binary file multiple number of times. This is a positive test case, which downloads complete binary file multiple number of times.
Number of iterations can be specified in variable iterations. Number of iterations can be specified in variable iterations.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
# File to be downloaded. This file is generated after compilation # File to be downloaded. This file is generated after compilation
bin_name = 'advanced_https_ota.bin' bin_name = 'advanced_https_ota.bin'
# start test # Start server
host_ip = get_my_ip()
chunked_server = start_chunked_server(dut.app.binary_path, 8070) chunked_server = start_chunked_server(dut.app.binary_path, 8070)
try: try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting Advanced OTA example', timeout=30) dut.expect('Starting Advanced OTA example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':8070/' + bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':8070/' + bin_name))
dut.write('https://' + host_ip + ':8070/' + bin_name) dut.write('https://' + host_ip + ':8070/' + bin_name)
dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('upgrade successful. Rebooting ...', timeout=60)
dut.expect('Starting Advanced OTA example', timeout=30) # after reboot
dut.expect('Loaded app from partition at offset', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
finally: finally:
chunked_server.kill() chunked_server.kill()
@@ -410,11 +402,10 @@ def test_examples_protocol_advanced_https_ota_example_redirect_url(dut: Dut) ->
Redirection server redirects http_request to different port Redirection server redirects http_request to different port
Number of iterations can be specified in variable iterations. Number of iterations can be specified in variable iterations.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
try:
server_port = 8001 server_port = 8001
# Port to which the request should be redirected # Port to which the request should be redirected
redirection_server_port = 8081 redirection_server_port = 8081
@@ -422,31 +413,34 @@ def test_examples_protocol_advanced_https_ota_example_redirect_url(dut: Dut) ->
# File to be downloaded. This file is generated after compilation # File to be downloaded. This file is generated after compilation
bin_name = 'advanced_https_ota.bin' bin_name = 'advanced_https_ota.bin'
# start test # start test
host_ip = get_my_ip()
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True
thread1.start()
thread2 = multiprocessing.Process(target=start_redirect_server, args=(dut.app.binary_path, host_ip, redirection_server_port, redirection_server_port1))
thread2.daemon = True
thread2.start()
thread3 = multiprocessing.Process(target=start_redirect_server, args=(dut.app.binary_path, host_ip, redirection_server_port1, server_port))
thread3.daemon = True
thread3.start()
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
thread2.terminate()
thread3.terminate()
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
dut.expect('Starting Advanced OTA example', timeout=30) dut.expect('Starting Advanced OTA example', timeout=30)
# Start server
host_ip = get_host_ip4_by_dest_ip(ip_address)
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True
thread2 = multiprocessing.Process(target=start_redirect_server, args=(dut.app.binary_path, host_ip, redirection_server_port, redirection_server_port1))
thread2.daemon = True
thread3 = multiprocessing.Process(target=start_redirect_server, args=(dut.app.binary_path, host_ip, redirection_server_port1, server_port))
thread3.daemon = True
thread1.start()
thread2.start()
thread3.start()
time.sleep(1)
try:
print('writing to device: {}'.format('https://' + host_ip + ':' + str(redirection_server_port) + '/' + bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(redirection_server_port) + '/' + bin_name))
dut.write('https://' + host_ip + ':' + str(redirection_server_port) + '/' + bin_name) dut.write('https://' + host_ip + ':' + str(redirection_server_port) + '/' + bin_name)
dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('upgrade successful. Rebooting ...', timeout=60)
dut.expect('Starting Advanced OTA example', timeout=30) # after reboot
dut.expect('Loaded app from partition at offset', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
finally: finally:
thread1.terminate() thread1.terminate()
thread2.terminate() thread2.terminate()
@@ -465,12 +459,11 @@ def test_examples_protocol_advanced_https_ota_example_anti_rollback(dut: Dut) ->
Working of OTA when anti_rollback is enabled and security version of new image is less than current one. Working of OTA when anti_rollback is enabled and security version of new image is less than current one.
Application should return with error message in this case. Application should return with error message in this case.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Generate binary file with lower security version 2. Generate binary file with lower security version
3. Fetch OTA image over HTTPS 3. Fetch OTA image over HTTPS
4. Check working of anti_rollback feature 4. Check working of anti_rollback feature
""" """
try:
dut.serial.erase_flash() dut.serial.erase_flash()
dut.serial.flash() dut.serial.flash()
server_port = 8001 server_port = 8001
@@ -488,26 +481,27 @@ def test_examples_protocol_advanced_https_ota_example_anti_rollback(dut: Dut) ->
fo.seek(36) fo.seek(36)
fo.write(b'\x00') fo.write(b'\x00')
binary_file = os.path.join(dut.app.binary_path, anti_rollback_bin_name) binary_file = os.path.join(dut.app.binary_path, anti_rollback_bin_name)
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
# Positive Case # Positive Case
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting Advanced OTA example', timeout=30)
dut.expect('Starting Advanced OTA example', timeout=30)
# Use originally generated image with secure_version=1 # Use originally generated image with secure_version=1
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)
dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('Loaded app from partition at offset', timeout=60)
dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
dut.expect(r'App is valid, rollback cancelled successfully', timeout=30) dut.expect(r'App is valid, rollback cancelled successfully', timeout=30)
# Negative Case # Negative Case
@@ -534,40 +528,42 @@ def test_examples_protocol_advanced_https_ota_example_partial_request(dut: Dut)
""" """
This is a positive test case, to test OTA workflow with Range HTTP header. This is a positive test case, to test OTA workflow with Range HTTP header.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
try:
server_port = 8001 server_port = 8001
# Size of partial HTTP request # Size of partial HTTP request
request_size = 16384 request_size = int(dut.app.sdkconfig.get('EXAMPLE_HTTP_REQUEST_SIZE'))
# File to be downloaded. This file is generated after compilation # File to be downloaded. This file is generated after compilation
bin_name = 'advanced_https_ota.bin' bin_name = 'advanced_https_ota.bin'
binary_file = os.path.join(dut.app.binary_path, bin_name) binary_file = os.path.join(dut.app.binary_path, bin_name)
bin_size = os.path.getsize(binary_file) bin_size = os.path.getsize(binary_file)
http_requests = int((bin_size / request_size) - 1) http_requests = int((bin_size / request_size) - 1)
# start test assert http_requests > 1
host_ip = get_my_ip() # Start server
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
print('ENV_TEST_FAILURE: Cannot connect to AP') raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
thread1.terminate() host_ip = get_host_ip4_by_dest_ip(ip_address)
raise
dut.expect('Starting Advanced OTA example', timeout=30)
dut.expect('Starting Advanced OTA example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)
for _ in range(http_requests): for _ in range(http_requests):
dut.expect('Connection closed', timeout=60) dut.expect('Connection closed', timeout=60)
dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('upgrade successful. Rebooting ...', timeout=60)
dut.expect('Starting Advanced OTA example', timeout=30) # after reboot
dut.expect('Loaded app from partition at offset', timeout=30)
dut.expect('OTA example app_main start', timeout=20)
finally: finally:
thread1.terminate() thread1.terminate()
@@ -576,42 +572,51 @@ def test_examples_protocol_advanced_https_ota_example_partial_request(dut: Dut)
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi_ota @pytest.mark.wifi_high_traffic
@pytest.mark.nightly_run @pytest.mark.nightly_run
@pytest.mark.parametrize('config', ['nimble',], indirect=True) @pytest.mark.parametrize('config', ['nimble',], indirect=True)
def test_examples_protocol_advanced_https_ota_example_nimble_gatts(dut: Dut) -> None: def test_examples_protocol_advanced_https_ota_example_nimble_gatts(dut: Dut) -> None:
""" """
Run an OTA image update while a BLE GATT Server is running in background. This GATT server will be using NimBLE Host stack. Run an OTA image update while a BLE GATT Server is running in background. This GATT server will be using NimBLE Host stack.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Run BLE advertise and then GATT server. 2. Run BLE advertise and then GATT server.
3. Fetch OTA image over HTTPS 3. Fetch OTA image over HTTPS
4. Reboot with the new OTA image 4. Reboot with the new OTA image
""" """
try:
server_port = 8001 server_port = 8001
# File to be downloaded. This file is generated after compilation # File to be downloaded. This file is generated after compilation
bin_name = 'advanced_https_ota.bin' bin_name = 'advanced_https_ota.bin'
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' sta ip: ([^,]+),', timeout=30) # start test
dut.expect('Loaded app from partition at offset', timeout=30)
# Parse IP address of STA
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
env_name = 'wifi_high_traffic'
dut.expect('Please input ssid password:')
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
try:
ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate()
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting Advanced OTA example', timeout=30) dut.expect('Starting Advanced OTA example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name))
print('Started GAP advertising.') print('Started GAP advertising.')
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)
dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('upgrade successful. Rebooting ...', timeout=60)
dut.expect('Starting Advanced OTA example', timeout=30) # after reboot
dut.expect('Loaded app from partition at offset', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
finally: finally:
thread1.terminate() thread1.terminate()
@@ -620,34 +625,41 @@ def test_examples_protocol_advanced_https_ota_example_nimble_gatts(dut: Dut) ->
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi_ota @pytest.mark.wifi_high_traffic
@pytest.mark.nightly_run @pytest.mark.nightly_run
@pytest.mark.parametrize('config', ['bluedroid',], indirect=True) @pytest.mark.parametrize('config', ['bluedroid',], indirect=True)
def test_examples_protocol_advanced_https_ota_example_bluedroid_gatts(dut: Dut) -> None: def test_examples_protocol_advanced_https_ota_example_bluedroid_gatts(dut: Dut) -> None:
""" """
Run an OTA image update while a BLE GATT Server is running in background. This GATT server will be using Bluedroid Host stack. Run an OTA image update while a BLE GATT Server is running in background. This GATT server will be using Bluedroid Host stack.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Run BLE advertise and then GATT server. 2. Run BLE advertise and then GATT server.
3. Fetch OTA image over HTTPS 3. Fetch OTA image over HTTPS
4. Reboot with the new OTA image 4. Reboot with the new OTA image
""" """
try:
server_port = 8001 server_port = 8001
# File to be downloaded. This file is generated after compilation # File to be downloaded. This file is generated after compilation
bin_name = 'advanced_https_ota.bin' bin_name = 'advanced_https_ota.bin'
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' sta ip: ([^,]+),', timeout=30) # start test
dut.expect('Loaded app from partition at offset', timeout=30)
# Parse IP address of STA
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
env_name = 'wifi_high_traffic'
dut.expect('Please input ssid password:')
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
try:
ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate()
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting Advanced OTA example', timeout=30) dut.expect('Starting Advanced OTA example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name))
@@ -655,8 +667,10 @@ def test_examples_protocol_advanced_https_ota_example_bluedroid_gatts(dut: Dut)
print('Started GAP advertising.') print('Started GAP advertising.')
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)
dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('upgrade successful. Rebooting ...', timeout=60)
dut.expect('Starting Advanced OTA example', timeout=30) # after reboot
dut.expect('Loaded app from partition at offset', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
finally: finally:
thread1.terminate() thread1.terminate()
@@ -670,7 +684,7 @@ def test_examples_protocol_advanced_https_ota_example_openssl_aligned_bin(dut: D
""" """
This is a test case for esp_http_client_read with binary size multiple of 289 bytes This is a test case for esp_http_client_read with binary size multiple of 289 bytes
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
@@ -689,23 +703,25 @@ def test_examples_protocol_advanced_https_ota_example_openssl_aligned_bin(dut: D
fo.write(f.read(bin_size)) fo.write(f.read(bin_size))
for _ in range(dummy_data_size): for _ in range(dummy_data_size):
fo.write(struct.pack('B', random.randrange(0,255,1))) fo.write(struct.pack('B', random.randrange(0,255,1)))
# start test # Start server
host_ip = get_my_ip()
chunked_server = start_chunked_server(dut.app.binary_path, 8070) chunked_server = start_chunked_server(dut.app.binary_path, 8070)
try: try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting Advanced OTA example', timeout=30) dut.expect('Starting Advanced OTA example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':8070/' + aligned_bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':8070/' + aligned_bin_name))
dut.write('https://' + host_ip + ':8070/' + aligned_bin_name) dut.write('https://' + host_ip + ':8070/' + aligned_bin_name)
dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('upgrade successful. Rebooting ...', timeout=60)
dut.expect('Starting Advanced OTA example', timeout=30) # after reboot
dut.expect('Loaded app from partition at offset', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
try: try:
os.remove(aligned_bin_name) os.remove(aligned_bin_name)
except OSError: except OSError:

View File

@@ -11,6 +11,7 @@ CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example_with_ble.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example_with_ble.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions_example_with_ble.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions_example_with_ble.csv"
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL="FROM_STDIN" CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL="FROM_STDIN"
CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y
CONFIG_EXAMPLE_SKIP_VERSION_CHECK=y CONFIG_EXAMPLE_SKIP_VERSION_CHECK=y

View File

@@ -80,7 +80,7 @@ static void ota_example_task(void *pvParameter)
esp_ota_handle_t update_handle = 0 ; esp_ota_handle_t update_handle = 0 ;
const esp_partition_t *update_partition = NULL; const esp_partition_t *update_partition = NULL;
ESP_LOGI(TAG, "Starting OTA example"); ESP_LOGI(TAG, "Starting OTA example task");
const esp_partition_t *configured = esp_ota_get_boot_partition(); const esp_partition_t *configured = esp_ota_get_boot_partition();
const esp_partition_t *running = esp_ota_get_running_partition(); const esp_partition_t *running = esp_ota_get_running_partition();
@@ -273,6 +273,8 @@ static bool diagnostic(void)
void app_main(void) void app_main(void)
{ {
ESP_LOGI(TAG, "OTA example app_main start");
uint8_t sha_256[HASH_LEN] = { 0 }; uint8_t sha_256[HASH_LEN] = { 0 };
esp_partition_t partition; esp_partition_t partition;

View File

@@ -12,6 +12,7 @@ from typing import Callable, Tuple
import pexpect import pexpect
import pytest import pytest
from common_test_methods import get_host_ip4_by_dest_ip
from pytest_embedded import Dut from pytest_embedded import Dut
server_cert = '-----BEGIN CERTIFICATE-----\n' \ server_cert = '-----BEGIN CERTIFICATE-----\n' \
@@ -65,15 +66,6 @@ server_key = '-----BEGIN PRIVATE KEY-----\n'\
'-----END PRIVATE KEY-----\n' '-----END PRIVATE KEY-----\n'
def get_my_ip() -> str:
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.connect(('8.8.8.8', 80))
my_ip = ''
my_ip = s1.getsockname()[0]
s1.close()
return my_ip
def create_file(server_file: str, file_data: str) -> None: def create_file(server_file: str, file_data: str) -> None:
with open(server_file, 'w+') as file: with open(server_file, 'w+') as file:
file.write(file_data) file.write(file_data)
@@ -136,33 +128,34 @@ def test_examples_protocol_native_ota_example(dut: Dut) -> None:
This is a positive test case, which downloads complete binary file multiple number of times. This is a positive test case, which downloads complete binary file multiple number of times.
Number of iterations can be specified in variable iterations. Number of iterations can be specified in variable iterations.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
try:
server_port = 8002 server_port = 8002
# No. of times working of application to be validated # No. of times working of application to be validated
iterations = 3 iterations = 3
# File to be downloaded. This file is generated after compilation # File to be downloaded. This file is generated after compilation
bin_name = 'native_ota.bin' bin_name = 'native_ota.bin'
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
for i in range(iterations):
dut.expect('Loaded app from partition at offset', timeout=60)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) # start test
print('Connected to AP with IP: {}'.format(ip_address)) for _ in range(iterations):
dut.expect('Loaded app from partition at offset', timeout=30)
try:
ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting OTA example', timeout=30)
dut.expect('Starting OTA example task', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + bin_name)
dut.expect('Prepare to restart system!', timeout=60)
finally: finally:
thread1.terminate() thread1.terminate()
@@ -174,12 +167,11 @@ def test_examples_protocol_native_ota_example_truncated_bin(dut: Dut) -> None:
Working of OTA if binary file is truncated is validated in this test case. Working of OTA if binary file is truncated is validated in this test case.
Application should return with error message in this case. Application should return with error message in this case.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Generate truncated binary file 2. Generate truncated binary file
3. Fetch OTA image over HTTPS 3. Fetch OTA image over HTTPS
4. Check working of code if bin is truncated 4. Check working of code if bin is truncated
""" """
try:
server_port = 8002 server_port = 8002
# Original binary file generated after compilation # Original binary file generated after compilation
bin_name = 'native_ota.bin' bin_name = 'native_ota.bin'
@@ -190,26 +182,26 @@ def test_examples_protocol_native_ota_example_truncated_bin(dut: Dut) -> None:
truncated_bin_size = 64000 truncated_bin_size = 64000
# check and log bin size # check and log bin size
binary_file = os.path.join(dut.app.binary_path, bin_name) binary_file = os.path.join(dut.app.binary_path, bin_name)
f = open(binary_file, 'rb+') with open(binary_file, 'rb+') as fr:
fo = open(os.path.join(dut.app.binary_path, truncated_bin_name), 'wb+') bin_data = fr.read(truncated_bin_size)
fo.write(f.read(truncated_bin_size))
fo.close()
f.close()
binary_file = os.path.join(dut.app.binary_path, truncated_bin_name) binary_file = os.path.join(dut.app.binary_path, truncated_bin_name)
# start test with open(binary_file, 'wb+') as fo:
host_ip = get_my_ip() fo.write(bin_data)
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) # Start server
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting OTA example', timeout=30)
dut.expect('Starting OTA example task', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name)
dut.expect('native_ota_example: Image validation failed, image is corrupted', timeout=20) dut.expect('native_ota_example: Image validation failed, image is corrupted', timeout=20)
@@ -225,12 +217,11 @@ def test_examples_protocol_native_ota_example_truncated_header(dut: Dut) -> None
Working of OTA if headers of binary file are truncated is vaildated in this test case. Working of OTA if headers of binary file are truncated is vaildated in this test case.
Application should return with error message in this case. Application should return with error message in this case.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Generate binary file with truncated headers 2. Generate binary file with truncated headers
3. Fetch OTA image over HTTPS 3. Fetch OTA image over HTTPS
4. Check working of code if headers are not sent completely 4. Check working of code if headers are not sent completely
""" """
try:
server_port = 8002 server_port = 8002
# Original binary file generated after compilation # Original binary file generated after compilation
bin_name = 'native_ota.bin' bin_name = 'native_ota.bin'
@@ -240,26 +231,26 @@ def test_examples_protocol_native_ota_example_truncated_header(dut: Dut) -> None
truncated_bin_size = 180 truncated_bin_size = 180
# check and log bin size # check and log bin size
binary_file = os.path.join(dut.app.binary_path, bin_name) binary_file = os.path.join(dut.app.binary_path, bin_name)
f = open(binary_file, 'rb+') with open(binary_file, 'rb+') as fr:
fo = open(os.path.join(dut.app.binary_path, truncated_bin_name), 'wb+') bin_data = fr.read(truncated_bin_size)
fo.write(f.read(truncated_bin_size))
fo.close()
f.close()
binary_file = os.path.join(dut.app.binary_path, truncated_bin_name) binary_file = os.path.join(dut.app.binary_path, truncated_bin_name)
# start test with open(binary_file, 'wb+') as fo:
host_ip = get_my_ip() fo.write(bin_data)
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port)) # Start server
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting OTA example', timeout=30)
dut.expect('Starting OTA example task', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + truncated_bin_name)
dut.expect('native_ota_example: received package is not fit len', timeout=20) dut.expect('native_ota_example: received package is not fit len', timeout=20)
@@ -275,12 +266,11 @@ def test_examples_protocol_native_ota_example_random(dut: Dut) -> None:
Working of OTA if random data is added in binary file are validated in this test case. Working of OTA if random data is added in binary file are validated in this test case.
Magic byte verification should fail in this case. Magic byte verification should fail in this case.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Generate random binary image 2. Generate random binary image
3. Fetch OTA image over HTTPS 3. Fetch OTA image over HTTPS
4. Check working of code for random binary file 4. Check working of code for random binary file
""" """
try:
server_port = 8002 server_port = 8002
# Random binary file to be generated # Random binary file to be generated
random_bin_name = 'random.bin' random_bin_name = 'random.bin'
@@ -291,24 +281,25 @@ def test_examples_protocol_native_ota_example_random(dut: Dut) -> None:
fo = open(binary_file, 'wb+') fo = open(binary_file, 'wb+')
# First byte of binary file is always set to zero. If first byte is generated randomly, # First byte of binary file is always set to zero. If first byte is generated randomly,
# in some cases it may generate 0xE9 which will result in failure of testcase. # in some cases it may generate 0xE9 which will result in failure of testcase.
with open(binary_file, 'wb+') as fo:
fo.write(struct.pack('B', 0)) fo.write(struct.pack('B', 0))
for i in range(random_bin_size - 1): for _ in range(random_bin_size - 1):
fo.write(struct.pack('B', random.randrange(0,255,1))) fo.write(struct.pack('B', random.randrange(0,255,1)))
fo.close() # Start server
# start test thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
host_ip = get_my_ip()
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting OTA example', timeout=30)
dut.expect('Starting OTA example task', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + random_bin_name)
dut.expect('esp_ota_ops: OTA image has invalid magic byte', timeout=20) dut.expect('esp_ota_ops: OTA image has invalid magic byte', timeout=20)
@@ -324,28 +315,31 @@ def test_examples_protocol_native_ota_example_chunked(dut: Dut) -> None:
This is a positive test case, which downloads complete binary file multiple number of times. This is a positive test case, which downloads complete binary file multiple number of times.
Number of iterations can be specified in variable iterations. Number of iterations can be specified in variable iterations.
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
# File to be downloaded. This file is generated after compilation # File to be downloaded. This file is generated after compilation
bin_name = 'native_ota.bin' bin_name = 'native_ota.bin'
# start test # Start server
host_ip = get_my_ip()
chunked_server = start_chunked_server(dut.app.binary_path, 8070) chunked_server = start_chunked_server(dut.app.binary_path, 8070)
try: try:
# start test
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting OTA example', timeout=30) dut.expect('Starting OTA example task', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':8070/' + bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':8070/' + bin_name))
dut.write('https://' + host_ip + ':8070/' + bin_name) dut.write('https://' + host_ip + ':8070/' + bin_name)
dut.expect('Loaded app from partition at offset', timeout=60) dut.expect('Prepare to restart system!', timeout=60)
dut.expect('Starting OTA example', timeout=30) # after reboot
dut.expect('Loaded app from partition at offset', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
os.remove(os.path.join(dut.app.binary_path, 'server_cert.pem')) os.remove(os.path.join(dut.app.binary_path, 'server_cert.pem'))
os.remove(os.path.join(dut.app.binary_path, 'server_key.pem')) os.remove(os.path.join(dut.app.binary_path, 'server_key.pem'))
finally: finally:

View File

@@ -9,6 +9,7 @@ from typing import Callable
import pexpect import pexpect
import pytest import pytest
from common_test_methods import get_host_ip4_by_dest_ip
from pytest_embedded import Dut from pytest_embedded import Dut
from RangeHTTPServer import RangeRequestHandler from RangeHTTPServer import RangeRequestHandler
@@ -17,15 +18,6 @@ key_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'server_cert
enc_bin_name = 'pre_encrypted_ota_secure.bin' enc_bin_name = 'pre_encrypted_ota_secure.bin'
def get_my_ip() -> str:
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.connect(('8.8.8.8', 80))
my_ip = ''
my_ip = s1.getsockname()[0]
s1.close()
return my_ip
def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]: def https_request_handler() -> Callable[...,http.server.BaseHTTPRequestHandler]:
""" """
Returns a request handler class that handles broken pipe exception Returns a request handler class that handles broken pipe exception
@@ -66,27 +58,27 @@ def start_https_server(ota_image_dir: str, server_ip: str, server_port: int) ->
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.ethernet_ota @pytest.mark.ethernet_ota
def test_examples_protocol_pre_encrypted_ota_example(dut: Dut) -> None: def test_examples_protocol_pre_encrypted_ota_example(dut: Dut) -> None:
try:
server_port = 8001 server_port = 8001
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', server_port))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, server_port))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
dut.expect('Loaded app from partition at offset', timeout=30) dut.expect('Loaded app from partition at offset', timeout=30)
try: try:
ip_address = dut.expect(r' (sta|eth) ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting Pre Encrypted OTA example', timeout=30)
dut.expect('Starting Pre Encrypted OTA example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + enc_bin_name)) print('writing to device: {}'.format('https://' + host_ip + ':' + str(server_port) + '/' + enc_bin_name))
dut.write('https://' + host_ip + ':' + str(server_port) + '/' + enc_bin_name) dut.write('https://' + host_ip + ':' + str(server_port) + '/' + enc_bin_name)
dut.expect('Magic Verified', timeout=30) dut.expect('Magic Verified', timeout=30)
dut.expect('Reading RSA private key', timeout=30) dut.expect('Reading RSA private key', timeout=30)
dut.expect('upgrade successful. Rebooting', timeout=30) dut.expect('upgrade successful. Rebooting', timeout=30)
# after reboot
dut.expect('Loaded app from partition at offset', timeout=30)
finally: finally:
thread1.terminate() thread1.terminate()

View File

@@ -33,9 +33,9 @@
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF #ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
/* The interface name value can refer to if_desc in esp_netif_defaults.h */ /* The interface name value can refer to if_desc in esp_netif_defaults.h */
#if CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_ETH #if CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_ETH
static const char *bind_interface_name = "eth"; static const char *bind_interface_name = EXAMPLE_NETIF_DESC_ETH;
#elif CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_STA #elif CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_STA
static const char *bind_interface_name = "sta"; static const char *bind_interface_name = EXAMPLE_NETIF_DESC_STA;
#endif #endif
#endif #endif
@@ -78,7 +78,7 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
void simple_ota_example_task(void *pvParameter) void simple_ota_example_task(void *pvParameter)
{ {
ESP_LOGI(TAG, "Starting OTA example"); ESP_LOGI(TAG, "Starting OTA example task");
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF #ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
esp_netif_t *netif = get_example_netif_from_desc(bind_interface_name); esp_netif_t *netif = get_example_netif_from_desc(bind_interface_name);
if (netif == NULL) { if (netif == NULL) {
@@ -127,6 +127,7 @@ void simple_ota_example_task(void *pvParameter)
ESP_LOGI(TAG, "Attempting to download update from %s", config.url); ESP_LOGI(TAG, "Attempting to download update from %s", config.url);
esp_err_t ret = esp_https_ota(&ota_config); esp_err_t ret = esp_https_ota(&ota_config);
if (ret == ESP_OK) { if (ret == ESP_OK) {
ESP_LOGI(TAG, "OTA Succeed, Rebooting...");
esp_restart(); esp_restart();
} else { } else {
ESP_LOGE(TAG, "Firmware upgrade failed"); ESP_LOGE(TAG, "Firmware upgrade failed");
@@ -165,6 +166,7 @@ static void get_sha256_of_partitions(void)
void app_main(void) void app_main(void)
{ {
ESP_LOGI(TAG, "OTA example app_main start");
// Initialize NVS. // Initialize NVS.
esp_err_t err = nvs_flash_init(); esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {

View File

@@ -3,13 +3,13 @@
import http.server import http.server
import multiprocessing import multiprocessing
import os import os
import socket
import ssl import ssl
import sys import sys
from typing import Tuple from typing import Tuple
import pexpect import pexpect
import pytest import pytest
from common_test_methods import get_env_config_variable, get_host_ip4_by_dest_ip
from pytest_embedded import Dut from pytest_embedded import Dut
server_cert = '-----BEGIN CERTIFICATE-----\n' \ server_cert = '-----BEGIN CERTIFICATE-----\n' \
@@ -63,15 +63,6 @@ server_key = '-----BEGIN PRIVATE KEY-----\n'\
'-----END PRIVATE KEY-----\n' '-----END PRIVATE KEY-----\n'
def get_my_ip() -> str:
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.connect(('8.8.8.8', 80))
my_ip = ''
my_ip = s1.getsockname()[0]
s1.close()
return my_ip
def start_https_server(ota_image_dir: str, server_ip: str, server_port: int, server_file: str = None, key_file: str = None) -> None: def start_https_server(ota_image_dir: str, server_ip: str, server_port: int, server_file: str = None, key_file: str = None) -> None:
os.chdir(ota_image_dir) os.chdir(ota_image_dir)
@@ -118,37 +109,45 @@ def calc_all_sha256(dut: Dut) -> Tuple[str, str]:
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.wifi_ota @pytest.mark.wifi_high_traffic
@pytest.mark.nightly_run
def test_examples_protocol_simple_ota_example(dut: Dut) -> None: def test_examples_protocol_simple_ota_example(dut: Dut) -> None:
""" """
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
try:
sha256_bootloader, sha256_app = calc_all_sha256(dut) sha256_bootloader, sha256_app = calc_all_sha256(dut)
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8000))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, 8000))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset 0x10000', timeout=30) dut.expect('Loaded app from partition at offset 0x10000', timeout=30)
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0])) check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0])) check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
# Parse IP address of STA
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
env_name = 'wifi_high_traffic'
dut.expect('Please input ssid password:')
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
try: try:
ip_address = dut.expect(r' sta ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting OTA example', timeout=30)
dut.expect('Starting OTA example task', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin')) print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin'))
dut.write('https://' + host_ip + ':8000/simple_ota.bin') dut.write('https://' + host_ip + ':8000/simple_ota.bin')
dut.expect('Loaded app from partition at offset 0x110000', timeout=60) dut.expect('OTA Succeed, Rebooting...', timeout=60)
dut.expect('Starting OTA example', timeout=30) # after reboot
dut.expect('Loaded app from partition at offset 0x110000', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
finally: finally:
thread1.terminate() thread1.terminate()
@@ -162,111 +161,81 @@ def test_examples_protocol_simple_ota_example(dut: Dut) -> None:
def test_examples_protocol_simple_ota_example_ethernet_with_spiram_config(dut: Dut) -> None: def test_examples_protocol_simple_ota_example_ethernet_with_spiram_config(dut: Dut) -> None:
""" """
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
try: # Start server
# start test thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8000))
host_ip = get_my_ip()
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, 8000))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset 0x10000', timeout=30) dut.expect('Loaded app from partition at offset 0x10000', timeout=30)
try: try:
ip_address = dut.expect(r' eth ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting OTA example', timeout=30)
dut.expect('Starting OTA example task', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin')) print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin'))
dut.write('https://' + host_ip + ':8000/simple_ota.bin') dut.write('https://' + host_ip + ':8000/simple_ota.bin')
dut.expect('Loaded app from partition at offset 0x110000', timeout=60) dut.expect('OTA Succeed, Rebooting...', timeout=60)
dut.expect('Starting OTA example', timeout=30) # after reboot
dut.expect('Loaded app from partition at offset 0x110000', timeout=30)
dut.expect('OTA example app_main start', timeout=10)
finally: finally:
thread1.terminate() thread1.terminate()
@pytest.mark.esp32 @pytest.mark.esp32
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.flash_encryption_wifi_high_traffic
@pytest.mark.esp32s3
@pytest.mark.flash_encryption_ota
@pytest.mark.parametrize('config', ['flash_enc',], indirect=True)
@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True)
def test_examples_protocol_simple_ota_example_with_flash_encryption(dut: Dut) -> None:
"""
steps: |
1. join AP
2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image
"""
try:
# Erase flash
dut.serial.erase_flash()
dut.serial.flash()
# start test
host_ip = get_my_ip()
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, 8000))
thread1.daemon = True
thread1.start()
dut.expect('Loaded app from partition at offset 0x20000', timeout=30)
dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10)
try:
ip_address = dut.expect(r' eth ip: ([^,]+),', timeout=30)
print('Connected to AP with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT:
thread1.terminate()
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
dut.expect('Starting OTA example', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin'))
dut.write('https://' + host_ip + ':8000/simple_ota.bin')
dut.expect('Loaded app from partition at offset 0x120000', timeout=60)
dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10)
dut.expect('Starting OTA example', timeout=30)
finally:
thread1.terminate()
@pytest.mark.esp32c3
@pytest.mark.flash_encryption_wifi_ota
@pytest.mark.nightly_run @pytest.mark.nightly_run
@pytest.mark.parametrize('config', ['flash_enc_wifi',], indirect=True) @pytest.mark.parametrize('config', ['flash_enc_wifi',], indirect=True)
@pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True) @pytest.mark.parametrize('skip_autoflash', ['y'], indirect=True)
def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Dut) -> None: def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Dut) -> None:
""" """
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
try:
# start test # start test
# Erase flash # Erase flash
dut.serial.erase_flash() dut.serial.erase_flash()
dut.serial.flash() dut.serial.flash()
host_ip = get_my_ip() # Start server
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, 8000)) thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8000))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
dut.expect('Loaded app from partition at offset 0x20000', timeout=30) dut.expect('Loaded app from partition at offset 0x20000', timeout=30)
dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10) dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10)
# Parse IP address of STA
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
env_name = 'flash_encryption_wifi_high_traffic'
dut.expect('Please input ssid password:')
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
ap_password = get_env_config_variable(env_name, 'ap_password')
dut.write(f'{ap_ssid} {ap_password}')
try: try:
ip_address = dut.expect(r' sta ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting OTA example', timeout=30)
dut.expect('Starting OTA example task', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin')) print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin'))
dut.write('https://' + host_ip + ':8000/simple_ota.bin') dut.write('https://' + host_ip + ':8000/simple_ota.bin')
dut.expect('Loaded app from partition at offset 0x120000', timeout=60) dut.expect('OTA Succeed, Rebooting...', timeout=60)
# after reboot
dut.expect('Loaded app from partition at offset 0x120000', timeout=30)
dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10) dut.expect('Flash encryption mode is DEVELOPMENT', timeout=10)
dut.expect('Starting OTA example', timeout=30) dut.expect('OTA example app_main start', timeout=10)
finally: finally:
thread1.terminate() thread1.terminate()
@@ -280,36 +249,36 @@ def test_examples_protocol_simple_ota_example_with_flash_encryption_wifi(dut: Du
def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_update_no_secure_boot_ecdsa(dut: Dut) -> None: def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_update_no_secure_boot_ecdsa(dut: Dut) -> None:
""" """
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
try:
sha256_bootloader, sha256_app = calc_all_sha256(dut) sha256_bootloader, sha256_app = calc_all_sha256(dut)
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8000))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, 8000))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset 0x20000', timeout=30) dut.expect('Loaded app from partition at offset 0x20000', timeout=30)
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0])) check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0])) check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
try: try:
ip_address = dut.expect(r' eth ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting OTA example', timeout=30)
dut.expect('Starting OTA example task', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin')) print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin'))
dut.write('https://' + host_ip + ':8000/simple_ota.bin') dut.write('https://' + host_ip + ':8000/simple_ota.bin')
dut.expect('Writing to partition subtype 16 at offset 0x120000', timeout=20) dut.expect('Writing to partition subtype 16 at offset 0x120000', timeout=20)
dut.expect('Verifying image signature...', timeout=60) dut.expect('Verifying image signature...', timeout=60)
dut.expect('OTA Succeed, Rebooting...', timeout=60)
# after reboot
dut.expect('Loaded app from partition at offset 0x120000', timeout=20) dut.expect('Loaded app from partition at offset 0x120000', timeout=20)
dut.expect('Starting OTA example', timeout=30) dut.expect('OTA example app_main start', timeout=10)
finally: finally:
thread1.terminate() thread1.terminate()
@@ -318,44 +287,44 @@ def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_updat
@pytest.mark.esp32c3 @pytest.mark.esp32c3
@pytest.mark.esp32s2 @pytest.mark.esp32s2
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@pytest.mark.ethernet @pytest.mark.ethernet_ota
@pytest.mark.parametrize('config', ['on_update_no_sb_rsa',], indirect=True) @pytest.mark.parametrize('config', ['on_update_no_sb_rsa',], indirect=True)
def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_update_no_secure_boot_rsa(dut: Dut) -> None: def test_examples_protocol_simple_ota_example_with_verify_app_signature_on_update_no_secure_boot_rsa(dut: Dut) -> None:
""" """
steps: | steps: |
1. join AP 1. join AP/Ethernet
2. Fetch OTA image over HTTPS 2. Fetch OTA image over HTTPS
3. Reboot with the new OTA image 3. Reboot with the new OTA image
""" """
try:
sha256_bootloader, sha256_app = calc_all_sha256(dut) sha256_bootloader, sha256_app = calc_all_sha256(dut)
# start test # Start server
host_ip = get_my_ip() thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8000))
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, host_ip, 8000))
thread1.daemon = True thread1.daemon = True
thread1.start() thread1.start()
try:
# start test
dut.expect('Loaded app from partition at offset 0x20000', timeout=30) dut.expect('Loaded app from partition at offset 0x20000', timeout=30)
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0])) check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0])) check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
try: try:
ip_address = dut.expect(r' eth ip: ([^,]+),', timeout=30) ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
print('Connected to AP with IP: {}'.format(ip_address)) print('Connected to AP/Ethernet with IP: {}'.format(ip_address))
except pexpect.exceptions.TIMEOUT: except pexpect.exceptions.TIMEOUT:
thread1.terminate() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') host_ip = get_host_ip4_by_dest_ip(ip_address)
dut.expect('Starting OTA example', timeout=30)
dut.expect('Starting OTA example task', timeout=30)
print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin')) print('writing to device: {}'.format('https://' + host_ip + ':8000/simple_ota.bin'))
dut.write('https://' + host_ip + ':8000/simple_ota.bin') dut.write('https://' + host_ip + ':8000/simple_ota.bin')
dut.expect('Writing to partition subtype 16 at offset 0x120000', timeout=20) dut.expect('Writing to partition subtype 16 at offset 0x120000', timeout=20)
dut.expect('Verifying image signature...', timeout=60) dut.expect('Verifying image signature...', timeout=60)
dut.expect('#0 app key digest == #0 trusted key digest', timeout=10) dut.expect('#0 app key digest == #0 trusted key digest', timeout=10)
dut.expect('Verifying with RSA-PSS...', timeout=10) dut.expect('Verifying with RSA-PSS...', timeout=10)
dut.expect('Signature verified successfully!', timeout=10) dut.expect('Signature verified successfully!', timeout=10)
dut.expect('OTA Succeed, Rebooting...', timeout=60)
# after reboot
dut.expect('Loaded app from partition at offset 0x120000', timeout=20) dut.expect('Loaded app from partition at offset 0x120000', timeout=20)
dut.expect('Starting OTA example', timeout=30) dut.expect('OTA example app_main start', timeout=10)
finally: finally:
thread1.terminate() thread1.terminate()

View File

@@ -1,3 +1,4 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL="FROM_STDIN" CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL="FROM_STDIN"
CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y
CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF=y CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF=y

View File

@@ -1,25 +0,0 @@
CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL="FROM_STDIN"
CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y
CONFIG_SECURE_FLASH_ENC_ENABLED=y
CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=y
CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=y
CONFIG_SECURE_BOOT_ALLOW_JTAG=y
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=y
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=y
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=y
CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED=y
CONFIG_PARTITION_TABLE_OFFSET=0x9000
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
CONFIG_EXAMPLE_CONNECT_WIFI=n
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
CONFIG_EXAMPLE_ETH_PHY_IP101=y
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
# This is required for nvs encryption (which is enabled by default with flash encryption)
CONFIG_PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS=y
CONFIG_MBEDTLS_TLS_CLIENT_ONLY=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_EXAMPLE_CONNECT_IPV6=n

View File

@@ -11,5 +11,10 @@ CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED=y
CONFIG_PARTITION_TABLE_OFFSET=0x9000 CONFIG_PARTITION_TABLE_OFFSET=0x9000
CONFIG_EXAMPLE_CONNECT_ETHERNET=n CONFIG_EXAMPLE_CONNECT_ETHERNET=n
CONFIG_EXAMPLE_CONNECT_WIFI=y CONFIG_EXAMPLE_CONNECT_WIFI=y
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
# This is required for nvs encryption (which is enabled by default with flash encryption) # This is required for nvs encryption (which is enabled by default with flash encryption)
CONFIG_PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS=y CONFIG_PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS=y
CONFIG_MBEDTLS_TLS_CLIENT_ONLY=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_EXAMPLE_CONNECT_IPV6=n

View File

@@ -39,20 +39,21 @@ markers =
ethernet_ota: ethernet OTA runners ethernet_ota: ethernet OTA runners
flash_encryption: Flash Encryption runners flash_encryption: Flash Encryption runners
ir_transceiver: runners with a pair of IR transmitter and receiver ir_transceiver: runners with a pair of IR transmitter and receiver
wifi_ota: wifi OTA runners flash_encryption_wifi_high_traffic: Flash Encryption runners with wifi high traffic support
flash_encryption_ota: flash encryprion ota ethernet runner
flash_encryption_wifi_ota: flash encryprion ota wifi runner
ethernet: ethernet runner ethernet: ethernet runner
ethernet_flash_8m: ethernet runner with 8mb flash ethernet_flash_8m: ethernet runner with 8mb flash
wifi: wifi runner ethernet_router: both the runner and dut connect to the same router through ethernet NIC
wifi_bt: wifi runner with bluetooth wifi_ap: a wifi AP in the environment
wifi_router: both the runner and dut connect to the same wifi router
wifi_high_traffic: wifi high traffic runners
wifi_wlan: wifi runner with a wireless NIC
deepsleep_temp_tag: temporary env for running potentially harmfull deepsleep related tests deepsleep_temp_tag: temporary env for running potentially harmfull deepsleep related tests
# multi-dut markers # multi-dut markers
multi_dut_generic: tests should be run on generic runners, at least have two duts connected. multi_dut_generic: tests should be run on generic runners, at least have two duts connected.
# host_test markers # host_test markers
host_test: tests which shouldn't be built at the build stage, and instead built in host_test stage. host_test: tests which shouldn not be built at the build stage, and instead built in host_test stage.
qemu: build and test using qemu-system-xtensa, not real target. qemu: build and test using qemu-system-xtensa, not real target.
# log related # log related

View File

@@ -1744,7 +1744,6 @@ examples/build_system/cmake/multi_config/main/multi_config_example_main.c
examples/common_components/iperf/include/iperf.h examples/common_components/iperf/include/iperf.h
examples/common_components/iperf/iperf.c examples/common_components/iperf/iperf.c
examples/common_components/protocol_examples_common/addr_from_stdin.c examples/common_components/protocol_examples_common/addr_from_stdin.c
examples/common_components/protocol_examples_common/connect.c
examples/common_components/protocol_examples_common/include/addr_from_stdin.h examples/common_components/protocol_examples_common/include/addr_from_stdin.h
examples/common_components/protocol_examples_common/include/protocol_examples_common.h examples/common_components/protocol_examples_common/include/protocol_examples_common.h
examples/common_components/protocol_examples_common/stdin_out.c examples/common_components/protocol_examples_common/stdin_out.c

View File

@@ -0,0 +1,98 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import logging
import os
import socket
from typing import Any
import netifaces
import yaml
ENV_CONFIG_FILE_SEARCH = [
os.path.join(os.environ['IDF_PATH'], 'EnvConfig.yml'),
os.path.join(os.environ['IDF_PATH'], 'ci-test-runner-configs', os.environ.get('CI_RUNNER_DESCRIPTION', ''), 'EnvConfig.yml'),
]
ENV_CONFIG_TEMPLATE = '''
$IDF_PATH/EnvConfig.yml:
```yaml
<env_name>:
key: var
key2: var2
<another_env>:
key: var
```
'''
def get_host_ip_by_interface(interface_name: str, ip_type: int = netifaces.AF_INET) -> str:
for _addr in netifaces.ifaddresses(interface_name)[ip_type]:
host_ip = _addr['addr'].replace('%{}'.format(interface_name), '')
assert isinstance(host_ip, str)
return host_ip
return ''
def get_host_ip4_by_dest_ip(dest_ip: str = '') -> str:
if not dest_ip:
dest_ip = '8.8.8.8'
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.connect((dest_ip, 80))
host_ip = s1.getsockname()[0]
s1.close()
assert isinstance(host_ip, str)
print(f'Using host ip: {host_ip}')
return host_ip
def get_my_interface_by_dest_ip(dest_ip: str = '') -> str:
my_ip = get_host_ip4_by_dest_ip(dest_ip)
interfaces = netifaces.interfaces()
for interface in interfaces:
try:
addresses = netifaces.ifaddresses(interface)[netifaces.AF_INET]
except KeyError:
continue
if my_ip in [a['addr'] for a in addresses]:
assert isinstance(interface, str)
return interface
logging.error('Can not get interface, dest ip is {}'.format(dest_ip))
return ''
def get_env_config_variable(env_name: str, key: str, default: Any = None) -> Any:
"""
Get test environment related variable
config file format: $IDF_PATH/EnvConfig.yml
```
<env_name>:
key: var
key2: var2
<env_name2>:
key: var
```
"""
config = dict()
for _file in ENV_CONFIG_FILE_SEARCH:
try:
with open(_file, 'r') as f:
data = yaml.load(f.read(), Loader=yaml.SafeLoader)
config = data[env_name]
break
except (FileNotFoundError, KeyError):
pass
else:
pass
var = config.get(key, default)
if var is None:
logging.warning(f'Failed to get env variable {env_name}/{key}.')
logging.info(f'Env config file template: {ENV_CONFIG_TEMPLATE}')
if not os.environ.get('CI_JOB_ID'):
# Try to get variable from stdin
var = input(f'You can input the variable now:')
else:
raise ValueError(f'Env variable not found: {env_name}/{key}')
logging.debug(f'Got env variable {env_name}/{key}: {var}')
return var

View File

@@ -15,6 +15,7 @@ from threading import Event, Lock, Thread
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
import ttfw_idf import ttfw_idf
from common_test_methods import get_host_ip4_by_dest_ip
DEFAULT_MSG_SIZE = 16 DEFAULT_MSG_SIZE = 16
@@ -33,19 +34,6 @@ def set_server_cert_cn(ip):
raise('openssl command {} failed'.format(args)) raise('openssl command {} failed'.format(args))
def get_my_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't even have to be reachable
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
# Publisher class creating a python client to send/receive published data from esp-mqtt client # Publisher class creating a python client to send/receive published data from esp-mqtt client
class MqttPublisher: class MqttPublisher:
@@ -247,8 +235,8 @@ class TlsServer:
self.shutdown.set() self.shutdown.set()
def connection_tests(dut, cases): def connection_tests(dut, cases, dut_ip):
ip = get_my_ip() ip = get_host_ip4_by_dest_ip(dut_ip)
set_server_cert_cn(ip) set_server_cert_cn(ip)
server_port = 2222 server_port = 2222
@@ -314,7 +302,7 @@ def connection_tests(dut, cases):
teardown_connection_suite() teardown_connection_suite()
@ttfw_idf.idf_custom_test(env_tag='Example_EthKitV1', group='test-apps') @ttfw_idf.idf_custom_test(env_tag='ethernet_router', group='test-apps')
def test_app_protocol_mqtt_publish_connect(env, extra_data): def test_app_protocol_mqtt_publish_connect(env, extra_data):
""" """
steps: steps:
@@ -348,11 +336,11 @@ def test_app_protocol_mqtt_publish_connect(env, extra_data):
raise raise
dut1.start_app() dut1.start_app()
esp_ip = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) esp_ip = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]'), timeout=30)[0]
print('Got IP={}'.format(esp_ip[0])) print('Got IP={}'.format(esp_ip))
if not os.getenv('MQTT_SKIP_CONNECT_TEST'): if not os.getenv('MQTT_SKIP_CONNECT_TEST'):
connection_tests(dut1,cases) connection_tests(dut1,cases,esp_ip)
# #
# start publish tests only if enabled in the environment (for weekend tests only) # start publish tests only if enabled in the environment (for weekend tests only)