From fd168d86fc084b3b793cccc00d5ed76a0430eb33 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 10 Apr 2024 18:51:26 +0200 Subject: [PATCH 1/4] feat(wifi_remote): Add support for simple eppp based RPC --- components/esp_wifi_remote/CMakeLists.txt | 19 +- components/esp_wifi_remote/Kconfig | 37 ++- components/esp_wifi_remote/Kconfig.rpc.in | 73 +++++ .../esp_wifi_remote/Kconfig.soc_wifi_caps.in | 8 + components/esp_wifi_remote/eppp/eppp_init.c | 23 ++ .../eppp/wifi_remote_rpc_client.cpp | 277 ++++++++++++++++++ .../eppp/wifi_remote_rpc_impl.hpp | 142 +++++++++ .../eppp/wifi_remote_rpc_params.h | 23 ++ .../eppp/wifi_remote_rpc_server.cpp | 209 +++++++++++++ .../esp_wifi_remote/esp_wifi_remote_weak.c | 20 -- .../esp_wifi_remote/esp_wifi_with_remote.c | 20 -- .../examples/mqtt/CMakeLists.txt | 23 ++ .../esp_wifi_remote/examples/mqtt/README.md | 41 +++ .../examples/mqtt/main/CMakeLists.txt | 4 + .../examples/mqtt/main/Kconfig.projbuild | 21 ++ .../examples/mqtt/main/app_main.c | 204 +++++++++++++ .../examples/mqtt/main/idf_component.yml | 5 + .../examples/mqtt/sdkconfig.defaults | 9 + .../examples/mqtt/sdkconfig.defaults.esp32h2 | 3 + .../examples/mqtt/sdkconfig.defaults.linux | 2 + .../examples/server/CMakeLists.txt | 6 + .../esp_wifi_remote/examples/server/README.md | 7 + .../examples/server/main/CMakeLists.txt | 2 + .../examples/server/main/idf_component.yml | 5 + .../server/main/station_example_main.c | 36 +++ .../examples/server/sdkconfig.defaults | 15 + components/esp_wifi_remote/idf_component.yml | 2 + .../include/esp_wifi_remote_api.h | 4 - .../scripts/generate_and_check.py | 6 +- .../smoke_test/components/esp_hosted/Kconfig | 2 + .../components/esp_hosted/esp_hosted_mock.c | 20 -- .../esp_hosted/include/esp_hosted_mock.h | 4 - .../test/smoke_test/main/all_wifi_calls.c | 20 -- .../smoke_test/main/all_wifi_remote_calls.c | 20 -- .../test/smoke_test/sdkconfig.defaults | 2 + .../wifi_apps/roaming_app/src/Kconfig.roaming | 0 36 files changed, 1190 insertions(+), 124 deletions(-) create mode 100644 components/esp_wifi_remote/Kconfig.rpc.in create mode 100644 components/esp_wifi_remote/eppp/eppp_init.c create mode 100644 components/esp_wifi_remote/eppp/wifi_remote_rpc_client.cpp create mode 100644 components/esp_wifi_remote/eppp/wifi_remote_rpc_impl.hpp create mode 100644 components/esp_wifi_remote/eppp/wifi_remote_rpc_params.h create mode 100644 components/esp_wifi_remote/eppp/wifi_remote_rpc_server.cpp create mode 100644 components/esp_wifi_remote/examples/mqtt/CMakeLists.txt create mode 100644 components/esp_wifi_remote/examples/mqtt/README.md create mode 100644 components/esp_wifi_remote/examples/mqtt/main/CMakeLists.txt create mode 100644 components/esp_wifi_remote/examples/mqtt/main/Kconfig.projbuild create mode 100644 components/esp_wifi_remote/examples/mqtt/main/app_main.c create mode 100644 components/esp_wifi_remote/examples/mqtt/main/idf_component.yml create mode 100644 components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults create mode 100644 components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.esp32h2 create mode 100644 components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.linux create mode 100644 components/esp_wifi_remote/examples/server/CMakeLists.txt create mode 100644 components/esp_wifi_remote/examples/server/README.md create mode 100644 components/esp_wifi_remote/examples/server/main/CMakeLists.txt create mode 100644 components/esp_wifi_remote/examples/server/main/idf_component.yml create mode 100644 components/esp_wifi_remote/examples/server/main/station_example_main.c create mode 100644 components/esp_wifi_remote/examples/server/sdkconfig.defaults create mode 100644 components/esp_wifi_remote/test/smoke_test/sdkconfig.defaults create mode 100644 components/esp_wifi_remote/wifi_apps/roaming_app/src/Kconfig.roaming diff --git a/components/esp_wifi_remote/CMakeLists.txt b/components/esp_wifi_remote/CMakeLists.txt index 577a37e00..e8460c874 100644 --- a/components/esp_wifi_remote/CMakeLists.txt +++ b/components/esp_wifi_remote/CMakeLists.txt @@ -1,15 +1,20 @@ if(NOT CONFIG_ESP_WIFI_ENABLED) - set(src_wifi_is_remote esp_wifi_remote.c esp_wifi_with_remote.c) + set(src_wifi_is_remote esp_wifi_remote.c esp_wifi_with_remote.c esp_wifi_remote_net.c) +endif() + +if(CONFIG_ESP_WIFI_REMOTE_LIBRARY_EPPP) + set(src_wifi_remote_eppp eppp/wifi_remote_rpc_client.cpp eppp/wifi_remote_rpc_server.cpp eppp/eppp_init.c) +else() + set(src_wifi_remote_weak esp_wifi_remote_weak.c) endif() idf_component_register(INCLUDE_DIRS include - SRCS ${src_wifi_is_remote} - esp_wifi_remote_net.c - esp_wifi_remote_weak.c + SRCS ${src_wifi_remote_weak} + ${src_wifi_remote_eppp} + ${src_wifi_is_remote} + PRIV_INCLUDE_DIRS eppp REQUIRES esp_event esp_netif - PRIV_REQUIRES esp_wifi) - -idf_component_optional_requires(PRIVATE esp_hosted) + PRIV_REQUIRES esp_wifi esp-tls) idf_component_get_property(wifi esp_wifi COMPONENT_LIB) target_link_libraries(${wifi} PUBLIC ${COMPONENT_LIB}) diff --git a/components/esp_wifi_remote/Kconfig b/components/esp_wifi_remote/Kconfig index c59c60db7..918e11bfa 100644 --- a/components/esp_wifi_remote/Kconfig +++ b/components/esp_wifi_remote/Kconfig @@ -5,6 +5,7 @@ menu "Wi-Fi Remote" default y orsource "./Kconfig.soc_wifi_caps.in" + orsource "./Kconfig.rpc.in" config ESP_WIFI_STATIC_RX_BUFFER_NUM int "Max number of WiFi static RX buffers" @@ -191,7 +192,7 @@ menu "Wi-Fi Remote" Set the size of WiFi Block Ack RX window. Generally a bigger value means higher throughput and better compatibility but more memory. Most of time we should NOT change the default value unless special reason, e.g. test the maximum UDP RX throughput with iperf etc. For iperf test in shieldbox, the - recommended value is 9~12. If PSRAM is used and WiFi memory is prefered to allocat in PSRAM first, + recommended value is 9~12. If PSRAM is used and WiFi memory is preferred to allocate in PSRAM first, the default and minimum value should be 16 to achieve better throughput and compatibility with both stations and APs. @@ -228,14 +229,14 @@ menu "Wi-Fi Remote" help ESP-MESH utilizes beacon frames to detect and resolve root node conflicts (see documentation). However the default length of a beacon frame can simultaneously hold only five root node identifier structures, - meaning that a root node conflict of up to five nodes can be detected at one time. In the occurence of + meaning that a root node conflict of up to five nodes can be detected at one time. In the occurrence of more root nodes conflict involving more than five root nodes, the conflict resolution process will detect five of the root nodes, resolve the conflict, and re-detect more root nodes. This process will repeat until all root node conflicts are resolved. However this process can generally take a very long time. To counter this situation, the beacon frame length can be increased such that more root nodes can be - detected simultaneously. Each additional root node will require 36 bytes and should be added ontop of + detected simultaneously. Each additional root node will require 36 bytes and should be added on top of the default beacon frame length of 752 bytes. For example, if you want to detect 10 root nodes simultaneously, you need to set the beacon frame length as @@ -487,9 +488,9 @@ menu "Wi-Fi Remote" help Select this option to use MbedTLS TLS client for WPA2 enterprise connection. Please note that from MbedTLS-3.0 onwards, MbedTLS does not support SSL-3.0 - TLS-v1.0, TLS-v1.1 versions. Incase your server is using one of these version, + TLS-v1.0, TLS-v1.1 versions. In case your server is using one of these version, it is advisable to update your server. - Please disable this option for compatibilty with older TLS versions. + Please disable this option for compatibility with older TLS versions. config ESP_WIFI_EAP_TLS1_3 bool "Enable EAP-TLS v1.3 Support for WiFi Enterprise connection" @@ -556,6 +557,26 @@ menu "Wi-Fi Remote" help Select this option to enable WiFi Multiband operation certification support. + config ESP_WIFI_ENABLE_ROAMING_APP + bool "Advanced support for Wi-Fi Roaming (Experimental)" + depends on IDF_EXPERIMENTAL_FEATURES + default n + select ESP_WIFI_SCAN_CACHE + help + Enable Espressif's roaming app to allow for efficient Wi-Fi roaming. + This includes configurable periodic environment scans, maintaining a cache of the + best APs, handling low rssi events etc. + + Risk Warning + Please note that this feature is still experimental and enabling this potentially can + lead to unpredictable scanning, connection and roaming attempts. + We are still working on tuning and optimising this feature to ensure reliable and stable use. + + menu "Configure roaming App" + depends on ESP_WIFI_ENABLE_ROAMING_APP + rsource "wifi_apps/roaming_app/src/Kconfig.roaming" + endmenu + config ESP_WIFI_DPP_SUPPORT bool "Enable DPP support" default n @@ -597,7 +618,7 @@ menu "Wi-Fi Remote" default n help Select this option to enable validate each WPS attribute - rigorously. Disabling this add the workaorunds with various APs. + rigorously. Disabling this add the workarounds with various APs. Enabling this may cause inter operability issues with some APs. config ESP_WIFI_WPS_PASSPHRASE @@ -605,9 +626,9 @@ menu "Wi-Fi Remote" default n help Select this option to get passphrase during WPS configuration. - This option fakes the virtual display capabilites to get the + This option fakes the virtual display capabilities to get the configuration in passphrase mode. - Not recommanded to be used since WPS credentials should not + Not recommended to be used since WPS credentials should not be shared to other devices, making it in readable format increases that risk, also passphrase requires pbkdf2 to convert in psk. diff --git a/components/esp_wifi_remote/Kconfig.rpc.in b/components/esp_wifi_remote/Kconfig.rpc.in new file mode 100644 index 000000000..204a40083 --- /dev/null +++ b/components/esp_wifi_remote/Kconfig.rpc.in @@ -0,0 +1,73 @@ +choice ESP_WIFI_REMOTE_LIBRARY + prompt "Choose WiFi-remote implementation" + default ESP_WIFI_REMOTE_LIBRARY_EPPP + help + Select type of WiFi Remote implementation + + ESP-HOSTED is the default and most versatile option. + It's also possible to use EPPP, which uses PPPoS link between micros and NAPT, so it's slower + and less universal. + + config ESP_WIFI_REMOTE_LIBRARY_HOSTED + bool "ESP-HOSTED" + config ESP_WIFI_REMOTE_LIBRARY_EPPP + bool "EPPP" +endchoice + + if ESP_WIFI_REMOTE_LIBRARY_EPPP + menu "WiFi remote by EPPP" + + choice ESP_WIFI_REMOTE_EPPP_TRANSPORT + prompt "Choose EPPP transport" + default ESP_WIFI_REMOTE_EPPP_TRANSPORT_UART + help + Select type of EPPP transport + + config ESP_WIFI_REMOTE_EPPP_TRANSPORT_UART + bool "UART" + config ESP_WIFI_REMOTE_EPPP_TRANSPORT_SPI + bool "SPI" + endchoice + + if ESP_WIFI_REMOTE_EPPP_TRANSPORT_UART + config ESP_WIFI_REMOTE_EPPP_UART_TX_PIN + int "TXD Pin Number" + default 10 + range 0 31 + help + Pin number of UART TX. + + config ESP_WIFI_REMOTE_EPPP_UART_RX_PIN + int "RXD Pin Number" + default 11 + range 0 31 + help + Pin number of UART RX. + endif + + config ESP_WIFI_REMOTE_EPPP_SERVER_CA + string "Servers CA certificate" + default "--- Please copy content of the CA certificate ---" + + config ESP_WIFI_REMOTE_EPPP_CLIENT_CRT + string "Client certificate" + default "--- Please copy content of the Client certificate ---" + + config ESP_WIFI_REMOTE_EPPP_CLIENT_KEY + string "Client key" + default "--- Please copy content of the Client key ---" + + config ESP_WIFI_REMOTE_EPPP_CLIENT_CA + string "Clients CA certificate" + default "--- Please copy content of the CA certificate ---" + + config ESP_WIFI_REMOTE_EPPP_SERVER_CRT + string "Server certificate" + default "--- Please copy content of the Client certificate ---" + + config ESP_WIFI_REMOTE_EPPP_SERVER_KEY + string "Server key" + default "--- Please copy content of the Client key ---" + endmenu + + endif diff --git a/components/esp_wifi_remote/Kconfig.soc_wifi_caps.in b/components/esp_wifi_remote/Kconfig.soc_wifi_caps.in index a0aee080a..1ec5de2b2 100644 --- a/components/esp_wifi_remote/Kconfig.soc_wifi_caps.in +++ b/components/esp_wifi_remote/Kconfig.soc_wifi_caps.in @@ -227,3 +227,11 @@ endif # ESP32C6 if SLAVE_IDF_TARGET_ESP32H2 endif # ESP32H2 + +if SLAVE_IDF_TARGET_ESP32P4 + + config SLAVE_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH + int + default 12 + +endif # ESP32P4 diff --git a/components/esp_wifi_remote/eppp/eppp_init.c b/components/esp_wifi_remote/eppp/eppp_init.c new file mode 100644 index 000000000..574ebfd2a --- /dev/null +++ b/components/esp_wifi_remote/eppp/eppp_init.c @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "esp_log.h" +#include "esp_wifi.h" +#include "eppp_link.h" + +esp_netif_t *wifi_remote_eppp_init(eppp_type_t role) +{ + uint32_t our_ip = role == EPPP_SERVER ? EPPP_DEFAULT_SERVER_IP() : EPPP_DEFAULT_CLIENT_IP(); + uint32_t their_ip = role == EPPP_SERVER ? EPPP_DEFAULT_CLIENT_IP() : EPPP_DEFAULT_SERVER_IP(); + eppp_config_t config = EPPP_DEFAULT_CONFIG(our_ip, their_ip); +#if CONFIG_ESP_WIFI_REMOTE_EPPP_TRANSPORT_UART + config.transport = EPPP_TRANSPORT_UART; + config.uart.tx_io = CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN; + config.uart.rx_io = CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN; +#else +#error ESP_WIFI_REMOTE supports only UART transport +#endif + return eppp_open(role, &config, portMAX_DELAY); +} diff --git a/components/esp_wifi_remote/eppp/wifi_remote_rpc_client.cpp b/components/esp_wifi_remote/eppp/wifi_remote_rpc_client.cpp new file mode 100644 index 000000000..2bbb76685 --- /dev/null +++ b/components/esp_wifi_remote/eppp/wifi_remote_rpc_client.cpp @@ -0,0 +1,277 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include "esp_log.h" +#include "esp_tls.h" +#include "esp_wifi.h" +#include "esp_check.h" +#include "wifi_remote_rpc_impl.hpp" +#include "eppp_link.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "wifi_remote_rpc_params.h" + +extern "C" esp_netif_t *wifi_remote_eppp_init(eppp_type_t role); + +namespace eppp_rpc { + +namespace client { +const char *TAG = "rpc_client"; + +const unsigned char ca_crt[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CA "\n-----END CERTIFICATE-----"; +const unsigned char crt[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CRT "\n-----END CERTIFICATE-----"; +const unsigned char key[] = "-----BEGIN RSA PRIVATE KEY-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_KEY "\n-----END RSA PRIVATE KEY-----"; + +} + +using namespace client; + +struct Sync { + void lock() + { + xSemaphoreTake(mutex, portMAX_DELAY); + } + void unlock() + { + xSemaphoreGive(mutex); + } + esp_err_t init() + { + mutex = xSemaphoreCreateMutex(); + events = xEventGroupCreate(); + return mutex == nullptr || events == nullptr ? ESP_ERR_NO_MEM : ESP_OK; + } + esp_err_t wait_for(EventBits_t bits, uint32_t timeout = portMAX_DELAY) + { + return xEventGroupWaitBits(events, bits, pdTRUE, pdTRUE, timeout) == bits ? ESP_OK : ESP_FAIL; + } + esp_err_t notify(EventBits_t bits) + { + xEventGroupSetBits(events, bits); + return ESP_OK; + } + ~Sync() + { + if (mutex) { + vSemaphoreDelete(mutex); + } + if (events) { + vEventGroupDelete(events); + } + } + SemaphoreHandle_t mutex{nullptr}; + EventGroupHandle_t events{nullptr}; + const int request = 1; + const int resp_header = 2; + const int resp_payload = 4; + +}; + +class RpcInstance { +public: + template + esp_err_t send(api_id id, T *t) + { + ESP_RETURN_ON_ERROR(sync.notify(sync.request), TAG, "failed to notify req"); + pending_resp = id; + ESP_RETURN_ON_ERROR(rpc.send(id, t), TAG, "Failed to send request"); + return ESP_OK; + } + + // specialization for (void) + esp_err_t send(api_id id) + { + ESP_RETURN_ON_ERROR(sync.notify(sync.request), TAG, "failed to notify req"); + pending_resp = id; + ESP_RETURN_ON_ERROR(rpc.send(id), TAG, "Failed to send request"); + return ESP_OK; + } + + template + T get_resp(api_id id) + { + sync.wait_for(sync.resp_header); + auto ret = rpc.template get_payload(id, pending_header); + sync.notify(sync.resp_payload); + return ret; + } + esp_err_t init() + { + ESP_RETURN_ON_FALSE(netif = wifi_remote_eppp_init(EPPP_CLIENT), ESP_FAIL, TAG, "Failed to connect to EPPP server"); + ESP_RETURN_ON_ERROR(sync.init(), TAG, "Failed to init sync primitives"); + ESP_RETURN_ON_ERROR(rpc.init(), TAG, "Failed to init RPC engine"); + return xTaskCreate(task, "client", 8192, this, 5, nullptr) == pdTRUE ? ESP_OK : ESP_FAIL; + } + RpcEngine rpc{eppp_rpc::role::CLIENT}; + Sync sync; +private: + api_id pending_resp{api_id::UNDEF}; + RpcHeader pending_header{}; + esp_err_t process_ip_event(RpcHeader &header) + { + auto event = rpc.get_payload(api_id::IP_EVENT, header); + // Now bypass network layers with EPPP interface + ESP_RETURN_ON_ERROR(esp_netif_set_dns_info(netif, ESP_NETIF_DNS_MAIN, &event.dns), TAG, "Failed to set DNS info"); + ESP_RETURN_ON_ERROR(esp_netif_set_default_netif(netif), TAG, "Failed to set default netif to EPPP"); + ip_event_got_ip_t evt = { + .esp_netif = netif, + .ip_info = {}, + .ip_changed = true, + }; + esp_netif_get_ip_info(netif, &evt.ip_info); + ESP_RETURN_ON_ERROR(esp_event_post(IP_EVENT, IP_EVENT_STA_GOT_IP, &evt, sizeof(evt), 0), TAG, "Failed to post IP event"); + ESP_LOGI(TAG, "Main DNS:" IPSTR, IP2STR(&event.dns.ip.u_addr.ip4)); + ESP_LOGI(TAG, "EPPP IP:" IPSTR, IP2STR(&event.ppp_ip.ip)); + ESP_LOGI(TAG, "WIFI IP:" IPSTR, IP2STR(&event.wifi_ip.ip)); + ESP_LOGI(TAG, "WIFI GW:" IPSTR, IP2STR(&event.wifi_ip.gw)); + ESP_LOGI(TAG, "WIFI mask:" IPSTR, IP2STR(&event.wifi_ip.netmask)); + return ESP_OK; + } + esp_err_t process_wifi_event(RpcHeader &header) + { + auto event_id = rpc.get_payload(api_id::WIFI_EVENT, header); + ESP_RETURN_ON_ERROR(esp_event_post(WIFI_EVENT, event_id, nullptr, 0, 0), TAG, "Failed to post WiFi event"); + return ESP_OK; + } + esp_err_t perform() + { + auto header = rpc.get_header(); + if (api_id(header.id) == api_id::ERROR) { // network error + return ESP_FAIL; + } + if (api_id(header.id) == api_id::UNDEF) { // network timeout + return ESP_OK; + } + + if (api_id(header.id) == api_id::IP_EVENT) { + return process_ip_event(header); + } + if (api_id(header.id) == api_id::WIFI_EVENT) { + return process_wifi_event(header); + } + if (sync.wait_for(sync.request, 0) == ESP_OK && api_id(header.id) == pending_resp) { + pending_header = header; + pending_resp = api_id::UNDEF; + sync.notify(sync.resp_header); + sync.wait_for(sync.resp_payload); + return ESP_OK; + } + ESP_LOGE(TAG, "Unexpected header %" PRIi32, static_cast(header.id)); + return ESP_FAIL; + + } + static void task(void *ctx) + { + auto instance = static_cast(ctx); + while (instance->perform() == ESP_OK) {} + vTaskDelete(nullptr); + } + esp_netif_t *netif{nullptr}; +}; + + +namespace client { +RpcInstance instance; +} // namespace client + +RpcInstance *RpcEngine::init_client() +{ + char host[4 * 4 + 1] = {}; // IPv4: 4 x (3 numbers + '.') + \0 + esp_ip4_addr_t ip = { .addr = EPPP_DEFAULT_SERVER_IP() }; + if (esp_ip4addr_ntoa(&ip, host, sizeof(host)) == nullptr) { + return nullptr; + } + + esp_tls_cfg_t cfg = {}; + cfg.cacert_buf = client::ca_crt; + cfg.cacert_bytes = sizeof(client::ca_crt); + cfg.clientcert_buf = client::crt; + cfg.clientcert_bytes = sizeof(client::crt); + cfg.clientkey_buf = client::key; + cfg.clientkey_bytes = sizeof(client::key); + cfg.common_name = "espressif.local"; + + tls_ = esp_tls_init(); + if (!tls_) { + ESP_LOGE(TAG, "Failed to allocate esp_tls handle!"); + goto exit; + } + if (esp_tls_conn_new_sync(host, strlen(host), rpc_port, &cfg, tls_) <= 0) { + ESP_LOGE(TAG, "Failed to open a new connection %s", host); + goto exit; + } + return &client::instance; +exit: + esp_tls_conn_destroy(tls_); + tls_ = nullptr; + return nullptr; +} +} // namespace eppp_rpc + +// +// esp_wifi_remote API implementation +// +using namespace eppp_rpc; +using namespace client; + +extern "C" esp_err_t esp_wifi_remote_init(const wifi_init_config_t *config) +{ + // Here we initialize this client's RPC + ESP_RETURN_ON_ERROR(instance.init(), TAG, "Failed to initialize eppp-rpc"); + + std::lock_guard lock(instance.sync); + ESP_RETURN_ON_ERROR(instance.send(api_id::INIT, config), TAG, "Failed to send request"); + return instance.get_resp(api_id::INIT); +} + +extern "C" esp_err_t esp_wifi_remote_set_config(wifi_interface_t interface, wifi_config_t *conf) +{ + esp_wifi_remote_config params = { .interface = interface, .conf = {} }; + memcpy(¶ms.conf, conf, sizeof(wifi_config_t)); + std::lock_guard lock(instance.sync); + ESP_RETURN_ON_ERROR(instance.send(api_id::SET_CONFIG, ¶ms), TAG, "Failed to send request"); + return instance.get_resp(api_id::SET_CONFIG); +} + +extern "C" esp_err_t esp_wifi_remote_start(void) +{ + std::lock_guard lock(instance.sync); + ESP_RETURN_ON_ERROR(instance.send(api_id::START), TAG, "Failed to send request"); + return instance.get_resp(api_id::START); +} + +extern "C" esp_err_t esp_wifi_remote_stop(void) +{ + std::lock_guard lock(instance.sync); + ESP_RETURN_ON_ERROR(instance.send(api_id::STOP), TAG, "Failed to send request"); + return instance.get_resp(api_id::STOP); +} + +extern "C" esp_err_t esp_wifi_remote_connect(void) +{ + std::lock_guard lock(instance.sync); + ESP_RETURN_ON_ERROR(instance.send(api_id::CONNECT), TAG, "Failed to send request"); + return instance.get_resp(api_id::CONNECT); +} + +extern "C" esp_err_t esp_wifi_remote_get_mac(wifi_interface_t ifx, uint8_t mac[6]) +{ + std::lock_guard lock(instance.sync); + ESP_RETURN_ON_ERROR(instance.send(api_id::GET_MAC, &ifx), TAG, "Failed to send request"); + auto ret = instance.get_resp(api_id::GET_MAC); + ESP_LOG_BUFFER_HEXDUMP("MAC", ret.mac, 6, ESP_LOG_DEBUG); + memcpy(mac, ret.mac, 6); + return ret.err; +} + +extern "C" esp_err_t esp_wifi_remote_set_mode(wifi_mode_t mode) +{ + std::lock_guard lock(instance.sync); + ESP_RETURN_ON_ERROR(instance.send(api_id::SET_MODE, &mode), TAG, "Failed to send request"); + return instance.get_resp(api_id::SET_MODE); +} diff --git a/components/esp_wifi_remote/eppp/wifi_remote_rpc_impl.hpp b/components/esp_wifi_remote/eppp/wifi_remote_rpc_impl.hpp new file mode 100644 index 000000000..beb87d407 --- /dev/null +++ b/components/esp_wifi_remote/eppp/wifi_remote_rpc_impl.hpp @@ -0,0 +1,142 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include +#include + +namespace eppp_rpc { + +const int rpc_port = 3333; + +enum class api_id : uint32_t { + ERROR, + UNDEF, + INIT, + SET_MODE, + SET_CONFIG, + START, + STOP, + CONNECT, + GET_MAC, + WIFI_EVENT, + IP_EVENT, +}; + +enum class role { + SERVER, + CLIENT, +}; + +struct RpcHeader { + api_id id; + uint32_t size; +} __attribute((__packed__)); + +template +struct RpcData { + RpcHeader head; + T value_{}; + explicit RpcData(api_id id) : head{id, sizeof(T)} {} + + uint8_t *value() + { + return (uint8_t *) &value_; + } + + uint8_t *marshall(T *t, size_t &size) + { + size = head.size + sizeof(RpcHeader); + memcpy(value(), t, sizeof(T)); + return (uint8_t *) this; + } +} __attribute((__packed__)); + +class RpcInstance; + +class RpcEngine { +public: + explicit RpcEngine(role r) : tls_(nullptr), role_(r) {} + + esp_err_t init() + { + if (tls_ != nullptr) { + return ESP_OK; + } + if (role_ == role::CLIENT) { + instance = init_client(); + } + if (role_ == role::SERVER) { + instance = init_server(); + } + return instance == nullptr ? ESP_FAIL : ESP_OK; + } + + template + esp_err_t send(api_id id, T *t) + { + RpcData req(id); + size_t size; + auto buf = req.marshall(t, size); + ESP_LOGD("rpc", "Sending API id:%d", (int) id); + ESP_LOG_BUFFER_HEXDUMP("rpc", buf, size, ESP_LOG_VERBOSE); + int len = esp_tls_conn_write(tls_, buf, size); + if (len <= 0) { + ESP_LOGE("rpc", "Failed to write data to the connection"); + return ESP_FAIL; + } + return ESP_OK; + } + + esp_err_t send(api_id id) // specialization for (void) + { + RpcHeader head = {.id = id, .size = 0}; + int len = esp_tls_conn_write(tls_, &head, sizeof(head)); + if (len <= 0) { + ESP_LOGE("rpc", "Failed to write data to the connection"); + return ESP_FAIL; + } + return ESP_OK; + } + + RpcHeader get_header() + { + RpcHeader header{}; + int len = esp_tls_conn_read(tls_, (char *) &header, sizeof(header)); + if (len <= 0) { + if (len < 0 && errno != EAGAIN) { + ESP_LOGE("rpc", "Failed to read header data from the connection %d %s", errno, strerror(errno)); + return {.id = api_id::ERROR, .size = 0}; + } + return {.id = api_id::UNDEF, .size = 0}; + } + return header; + } + + template + T get_payload(api_id id, RpcHeader &head) + { + RpcData resp(id); + if (head.id != id || head.size != resp.head.size) { + ESP_LOGE("rpc", "unexpected header %d %d or sizes %" PRIu32 " %" PRIu32, (int)head.id, (int)id, head.size, resp.head.size); + return {}; + } + int len = esp_tls_conn_read(tls_, (char *) resp.value(), resp.head.size); + if (len <= 0) { + ESP_LOGE("rpc", "Failed to read data from the connection"); + return {}; + } + return resp.value_; + } + +private: + RpcInstance *init_server(); + RpcInstance *init_client(); + esp_tls_t *tls_; + role role_; + RpcInstance *instance{nullptr}; +}; + +}; diff --git a/components/esp_wifi_remote/eppp/wifi_remote_rpc_params.h b/components/esp_wifi_remote/eppp/wifi_remote_rpc_params.h new file mode 100644 index 000000000..402308fab --- /dev/null +++ b/components/esp_wifi_remote/eppp/wifi_remote_rpc_params.h @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +struct esp_wifi_remote_config { + wifi_interface_t interface; + wifi_config_t conf; +}; + +struct esp_wifi_remote_mac_t { + esp_err_t err; + uint8_t mac[6]; +}; + +struct esp_wifi_remote_eppp_ip_event { + uint32_t id; + esp_netif_ip_info_t wifi_ip; + esp_netif_ip_info_t ppp_ip; + esp_netif_dns_info_t dns; +}; diff --git a/components/esp_wifi_remote/eppp/wifi_remote_rpc_server.cpp b/components/esp_wifi_remote/eppp/wifi_remote_rpc_server.cpp new file mode 100644 index 000000000..aed9faa54 --- /dev/null +++ b/components/esp_wifi_remote/eppp/wifi_remote_rpc_server.cpp @@ -0,0 +1,209 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include "esp_log.h" +#include "esp_check.h" +#include "esp_tls.h" +#include "esp_wifi.h" +#include "wifi_remote_rpc_impl.hpp" +#include "eppp_link.h" +#include "wifi_remote_rpc_params.h" +#include "lwip/apps/snmp.h" + +extern "C" esp_netif_t *wifi_remote_eppp_init(eppp_type_t role); + +namespace eppp_rpc { + +namespace server { +const char *TAG = "rpc_server"; + +const unsigned char ca_crt[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CA "\n-----END CERTIFICATE-----"; +const unsigned char crt[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CRT "\n-----END CERTIFICATE-----"; +const unsigned char key[] = "-----BEGIN RSA PRIVATE KEY-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_KEY "\n-----END RSA PRIVATE KEY-----"; + +} + +using namespace server; + +class RpcInstance { +public: + RpcEngine rpc{role::SERVER}; + int sock{-1}; + + esp_err_t init() + { + ESP_RETURN_ON_FALSE(netif = wifi_remote_eppp_init(EPPP_SERVER), ESP_FAIL, TAG, "Failed to init EPPP connection"); + ESP_RETURN_ON_ERROR(start_server(), TAG, "Failed to start RPC server"); + ESP_RETURN_ON_ERROR(rpc.init(), TAG, "Failed to init RPC engine"); + ESP_RETURN_ON_ERROR(esp_netif_napt_enable(netif), TAG, "Failed to enable NAPT"); + ESP_RETURN_ON_ERROR(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, handler, this), TAG, "Failed to register event"); + ESP_RETURN_ON_ERROR(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, handler, this), TAG, "Failed to register event"); + return xTaskCreate(task, "server", 8192, this, 5, nullptr) == pdTRUE ? ESP_OK : ESP_FAIL; + } + +private: + esp_netif_t *netif{nullptr}; + static void task(void *ctx) + { + auto instance = static_cast(ctx); + while (instance->perform() == ESP_OK) {} + vTaskDelete(nullptr); + } + esp_err_t start_server() + { + struct sockaddr_in dest_addr = {}; + int ret; + int opt = 1; + dest_addr.sin_addr.s_addr = htonl(INADDR_ANY); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(rpc_port); + int listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + ESP_RETURN_ON_FALSE(listen_sock >= 0, ESP_FAIL, TAG, "Failed to create listening socket"); + setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + ret = bind(listen_sock, (struct sockaddr *) &dest_addr, sizeof(dest_addr)); + ESP_RETURN_ON_FALSE(ret == 0, ESP_FAIL, TAG, "Failed to bind the listening socket"); + ret = listen(listen_sock, 1); + ESP_RETURN_ON_FALSE(ret == 0, ESP_FAIL, TAG, "Failed to start listening"); + struct sockaddr_storage source_addr {}; + socklen_t addr_len = sizeof(source_addr); + sock = accept(listen_sock, (struct sockaddr *) &source_addr, &addr_len); + ESP_RETURN_ON_FALSE(sock >= 0, ESP_FAIL, TAG, "Failed to accept connections: errno %d", errno); + ESP_LOGI(TAG, "Socket accepted on: %s", inet_ntoa(((struct sockaddr_in *) &source_addr)->sin_addr)); + return ESP_OK; + } + esp_err_t wifi_event(int32_t id) + { + ESP_LOGI(TAG, "Received WIFI event %" PRIi32, id); + ESP_RETURN_ON_ERROR(rpc.send(api_id::WIFI_EVENT, &id), TAG, "Failed to marshall WiFi event"); + return ESP_OK; + } + esp_err_t ip_event(int32_t id, ip_event_got_ip_t *ip_data) + { + ESP_LOGI(TAG, "Received IP event %" PRIi32, id); + esp_wifi_remote_eppp_ip_event ip_event{}; + ip_event.id = id; + if (ip_data->esp_netif) { + // marshall additional data, only if netif available + ESP_RETURN_ON_ERROR(esp_netif_get_dns_info(ip_data->esp_netif, ESP_NETIF_DNS_MAIN, &ip_event.dns), TAG, "Failed to get DNS info"); + ESP_LOGI(TAG, "Main DNS:" IPSTR, IP2STR(&ip_event.dns.ip.u_addr.ip4)); + memcpy(&ip_event.wifi_ip, &ip_data->ip_info, sizeof(ip_event.wifi_ip)); + ESP_RETURN_ON_ERROR(esp_netif_get_ip_info(netif, &ip_event.ppp_ip), TAG, "Failed to get IP info"); + ESP_LOGI(TAG, "IP address:" IPSTR, IP2STR(&ip_data->ip_info.ip)); + } + ESP_RETURN_ON_ERROR(rpc.send(api_id::IP_EVENT, &ip_event), TAG, "Failed to marshal IP event"); + return ESP_OK; + } + static void handler(void *ctx, esp_event_base_t base, int32_t id, void *data) + { + auto instance = static_cast(ctx); + if (base == WIFI_EVENT) { + instance->wifi_event(id); + } else if (base == IP_EVENT) { + auto *ip_data = (ip_event_got_ip_t *)data; + instance->ip_event(id, ip_data); + } + } + esp_err_t perform() + { + auto header = rpc.get_header(); + ESP_LOGI(TAG, "Received header id %d", (int) header.id); + + switch (header.id) { + case api_id::SET_MODE: { + auto req = rpc.get_payload(api_id::SET_MODE, header); + auto ret = esp_wifi_set_mode(req); + if (rpc.send(api_id::SET_MODE, &ret) != ESP_OK) { + return ESP_FAIL; + } + break; + } + case api_id::INIT: { + auto req = rpc.get_payload(api_id::INIT, header); + req.osi_funcs = &g_wifi_osi_funcs; + req.wpa_crypto_funcs = g_wifi_default_wpa_crypto_funcs; + auto ret = esp_wifi_init(&req); + if (rpc.send(api_id::INIT, &ret) != ESP_OK) { + return ESP_FAIL; + } + break; + } + case api_id::SET_CONFIG: { + auto req = rpc.get_payload(api_id::SET_CONFIG, header); + auto ret = esp_wifi_set_config(req.interface, &req.conf); + if (rpc.send(api_id::SET_CONFIG, &ret) != ESP_OK) { + return ESP_FAIL; + } + break; + } + case api_id::START: { + if (header.size != 0) { + return ESP_FAIL; + } + + auto ret = esp_wifi_start(); + if (rpc.send(api_id::START, &ret) != ESP_OK) { + return ESP_FAIL; + } + break; + } + case api_id::CONNECT: { + if (header.size != 0) { + return ESP_FAIL; + } + + auto ret = esp_wifi_connect(); + if (rpc.send(api_id::CONNECT, &ret) != ESP_OK) { + return ESP_FAIL; + } + break; + } + case api_id::GET_MAC: { + auto req = rpc.get_payload(api_id::GET_MAC, header); + esp_wifi_remote_mac_t resp = {}; + resp.err = esp_wifi_get_mac(req, resp.mac); + if (rpc.send(api_id::GET_MAC, &resp) != ESP_OK) { + return ESP_FAIL; + } + break; + } + default: + return ESP_FAIL; + } + return ESP_OK; + } +}; + + +namespace server { +RpcInstance instance; +} + +RpcInstance *RpcEngine::init_server() +{ + esp_tls_cfg_server_t cfg = {}; + cfg.cacert_buf = server::ca_crt; + cfg.cacert_bytes = sizeof(server::ca_crt); + cfg.servercert_buf = server::crt; + cfg.servercert_bytes = sizeof(server::crt); + cfg.serverkey_buf = server::key; + cfg.serverkey_bytes = sizeof(server::key); + + ESP_RETURN_ON_FALSE(tls_ = esp_tls_init(), nullptr, TAG, "Failed to create ESP-TLS instance"); + ESP_RETURN_ON_FALSE(esp_tls_server_session_create(&cfg, server::instance.sock, tls_) == ESP_OK, nullptr, TAG, "Failed to create TLS session"); + return &server::instance; +} + +} // namespace eppp_rpc + +using namespace eppp_rpc; + +extern "C" esp_err_t server_init(void) +{ + return server::instance.init(); +} diff --git a/components/esp_wifi_remote/esp_wifi_remote_weak.c b/components/esp_wifi_remote/esp_wifi_remote_weak.c index 3bee295c0..e78732119 100644 --- a/components/esp_wifi_remote/esp_wifi_remote_weak.c +++ b/components/esp_wifi_remote/esp_wifi_remote_weak.c @@ -271,26 +271,6 @@ WEAK esp_err_t esp_wifi_remote_set_csi(_Bool en) LOG_UNSUPPORTED_AND_RETURN(ESP_ERR_NOT_SUPPORTED); } -WEAK esp_err_t esp_wifi_remote_set_ant_gpio(const wifi_ant_gpio_config_t *config) -{ - LOG_UNSUPPORTED_AND_RETURN(ESP_ERR_NOT_SUPPORTED); -} - -WEAK esp_err_t esp_wifi_remote_get_ant_gpio(wifi_ant_gpio_config_t *config) -{ - LOG_UNSUPPORTED_AND_RETURN(ESP_ERR_NOT_SUPPORTED); -} - -WEAK esp_err_t esp_wifi_remote_set_ant(const wifi_ant_config_t *config) -{ - LOG_UNSUPPORTED_AND_RETURN(ESP_ERR_NOT_SUPPORTED); -} - -WEAK esp_err_t esp_wifi_remote_get_ant(wifi_ant_config_t *config) -{ - LOG_UNSUPPORTED_AND_RETURN(ESP_ERR_NOT_SUPPORTED); -} - WEAK int64_t esp_wifi_remote_get_tsf_time(wifi_interface_t interface) { LOG_UNSUPPORTED_AND_RETURN(-1); diff --git a/components/esp_wifi_remote/esp_wifi_with_remote.c b/components/esp_wifi_remote/esp_wifi_with_remote.c index 66b202fc9..c78aaf966 100644 --- a/components/esp_wifi_remote/esp_wifi_with_remote.c +++ b/components/esp_wifi_remote/esp_wifi_with_remote.c @@ -267,26 +267,6 @@ esp_err_t esp_wifi_set_csi(_Bool en) return esp_wifi_remote_set_csi(en); } -esp_err_t esp_wifi_set_ant_gpio(const wifi_ant_gpio_config_t *config) -{ - return esp_wifi_remote_set_ant_gpio(config); -} - -esp_err_t esp_wifi_get_ant_gpio(wifi_ant_gpio_config_t *config) -{ - return esp_wifi_remote_get_ant_gpio(config); -} - -esp_err_t esp_wifi_set_ant(const wifi_ant_config_t *config) -{ - return esp_wifi_remote_set_ant(config); -} - -esp_err_t esp_wifi_get_ant(wifi_ant_config_t *config) -{ - return esp_wifi_remote_get_ant(config); -} - int64_t esp_wifi_get_tsf_time(wifi_interface_t interface) { return esp_wifi_remote_get_tsf_time(interface); diff --git a/components/esp_wifi_remote/examples/mqtt/CMakeLists.txt b/components/esp_wifi_remote/examples/mqtt/CMakeLists.txt new file mode 100644 index 000000000..b07caaa52 --- /dev/null +++ b/components/esp_wifi_remote/examples/mqtt/CMakeLists.txt @@ -0,0 +1,23 @@ +# This project serves as a demo to enable using esp-mqtt on ESP platform targets as well as on linux +cmake_minimum_required(VERSION 3.16) + +if("${IDF_TARGET}" STREQUAL "linux") +# For linux-target we have two options: +# - With lwIP (must be defined on command line, e.g. idf.py -DWITH_LWIP=1) +# access networking from linux `tap` interface (TAP networking mode) +# - Without lwIP (must be defined on command line, e.g. idf.py -DWITH_LWIP=0) +# no designated interface, accesses user network via linux/socket sys calls + if(WITH_LWIP STREQUAL 1) + set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_tapif_io + "../../common_components/linux_compat/esp_timer") + set(COMPONENTS main esp_netif lwip protocol_examples_tapif_io startup esp_hw_support esp_system nvs_flash mqtt esp_timer) + else() + list(APPEND EXTRA_COMPONENT_DIRS + "../../common_components/linux_compat/esp_timer" + "$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs") + set(COMPONENTS main nvs_flash esp-tls esp_stubs mqtt protocol_examples_common esp_timer) + endif() +endif() + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(esp_mqtt_demo) diff --git a/components/esp_wifi_remote/examples/mqtt/README.md b/components/esp_wifi_remote/examples/mqtt/README.md new file mode 100644 index 000000000..acf680b75 --- /dev/null +++ b/components/esp_wifi_remote/examples/mqtt/README.md @@ -0,0 +1,41 @@ +# MQTT demo application that runs on linux + +## Overview + +This is a simple example demonstrating connecting to an MQTT broker, subscribing and publishing some data. +This example uses IDF build system and could be configured to be build and executed: +* for any ESP32 family chip +* for linux target + +## How to use example + +### Hardware Required + +To run this example, you need any ESP32 development board or just PC/virtual machine/container running linux operating system. + +### Host build modes + +Linux build is supported in these two modes: +* `WITH_LWIP=0`: Without lwIP component. The project uses linux BSD socket interface to interact with TCP/IP stack. There's no connection phase, we use the host network as users. This mode is often referred to as user-side networking. +* `WITH_LWIP=1`: Including lwIP component, which is added to the list of required components and compiled on host. In this mode, we have to map the host network (linux TCP/IP stack) to the target network (lwip). We use IDF's [`tapif_io`](https://github.com/espressif/esp-idf/tree/master/examples/common_components/protocol_examples_tapif_io) component to create a network interface, which will be used to pass packets to and from the simulated target. Please refer to the [README](https://github.com/espressif/esp-idf/tree/master/examples/common_components/protocol_examples_tapif_io#readme) for more details about the host side networking. + +### Building on linux + +1) Configure linux target +```bash +idf.py --preview set-target linux +``` + +2) Build the project with preferred components (with or without lwip) +```bash +idf.py -DWITH_LWIP=0 build # Building without lwip (user networking) +idf.py -DWITH_LWIP=1 build # Building with lwip (TAP networking) +``` + +3) Run the project + +It is possible to run the project elf file directly, or using `idf.py` monitor target (no need to flash): +```bash +idf.py monitor +``` +idf.py -DWITH_LWIP=0 build # Building without lwip (user networking) diff --git a/components/esp_wifi_remote/examples/mqtt/main/CMakeLists.txt b/components/esp_wifi_remote/examples/mqtt/main/CMakeLists.txt new file mode 100644 index 000000000..d6e9824b8 --- /dev/null +++ b/components/esp_wifi_remote/examples/mqtt/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "app_main.c" + INCLUDE_DIRS ".") + +target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") diff --git a/components/esp_wifi_remote/examples/mqtt/main/Kconfig.projbuild b/components/esp_wifi_remote/examples/mqtt/main/Kconfig.projbuild new file mode 100644 index 000000000..7ad4dc25e --- /dev/null +++ b/components/esp_wifi_remote/examples/mqtt/main/Kconfig.projbuild @@ -0,0 +1,21 @@ +menu "Example Configuration" + + config BROKER_URL + string "Broker URL" + default "mqtt://mqtt.eclipseprojects.io" + help + URL of the broker to connect to + + config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + + config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + +endmenu diff --git a/components/esp_wifi_remote/examples/mqtt/main/app_main.c b/components/esp_wifi_remote/examples/mqtt/main/app_main.c new file mode 100644 index 000000000..07b60abdf --- /dev/null +++ b/components/esp_wifi_remote/examples/mqtt/main/app_main.c @@ -0,0 +1,204 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include +#include "esp_system.h" +#include "nvs_flash.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "esp_netif.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" + +#include "esp_log.h" +#include "mqtt_client.h" + +static const char *TAG = "esp_mqtt_demo"; +static EventGroupHandle_t s_wifi_event_group; +static int s_retry_num = 0; + +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 + +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD +#define EXAMPLE_ESP_MAXIMUM_RETRY 5 + +static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id); + esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t)event_data; + esp_mqtt_client_handle_t client = event->client; + int msg_id; + switch ((esp_mqtt_event_id_t)event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); + msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0); + ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); + + msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); + ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); + + msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); + ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); + + msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); + ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); + break; + case MQTT_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); + break; + + case MQTT_EVENT_SUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); + msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); + ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); + break; + case MQTT_EVENT_UNSUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_PUBLISHED: + ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_DATA: + ESP_LOGI(TAG, "MQTT_EVENT_DATA"); + printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); + printf("DATA=%.*s\r\n", event->data_len, event->data); + break; + case MQTT_EVENT_ERROR: + ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); + break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); + break; + } +} + +static void mqtt_app_start(void) +{ + esp_mqtt_client_config_t mqtt_cfg = {}; + mqtt_cfg.broker.address.uri = CONFIG_BROKER_URL; + mqtt_cfg.credentials.client_id = "idf_on_linux_client"; + + esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); + /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */ + esp_mqtt_client_register_event(client, (esp_mqtt_event_id_t)ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); + esp_mqtt_client_start(client); +} + +static void event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + ESP_LOGI(TAG, "EVENT type %s id %d", event_base, (int)event_id); + 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); + } +} + +static void wifi_init_sta() +{ + s_wifi_event_group = xEventGroupCreate(); + + ESP_ERROR_CHECK(esp_netif_init()); + + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_create_default_wifi_sta(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &event_handler, + NULL, + &instance_any_id)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + IP_EVENT_STA_GOT_IP, + &event_handler, + NULL, + &instance_got_ip)); + + 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); + } else { + ESP_LOGE(TAG, "UNEXPECTED EVENT"); + } +} + +void app_main(void) +{ + ESP_LOGI(TAG, "[APP] Startup.."); + ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); + ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); + + esp_log_level_set("*", ESP_LOG_INFO); + esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE); + esp_log_level_set("esp_mqtt_demo", ESP_LOG_VERBOSE); + esp_log_level_set("transport_base", ESP_LOG_VERBOSE); + esp_log_level_set("esp-tls", ESP_LOG_VERBOSE); + esp_log_level_set("transport", ESP_LOG_VERBOSE); + esp_log_level_set("outbox", ESP_LOG_VERBOSE); + + //Initialize NVS + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); + wifi_init_sta(); + + mqtt_app_start(); +} diff --git a/components/esp_wifi_remote/examples/mqtt/main/idf_component.yml b/components/esp_wifi_remote/examples/mqtt/main/idf_component.yml new file mode 100644 index 000000000..22d411780 --- /dev/null +++ b/components/esp_wifi_remote/examples/mqtt/main/idf_component.yml @@ -0,0 +1,5 @@ +dependencies: + espressif/eppp_link: "^0.0.1" + esp_wifi_remote: + version: "*" + override_path: ../../.. diff --git a/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults b/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults new file mode 100644 index 000000000..68c4ddef0 --- /dev/null +++ b/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults @@ -0,0 +1,9 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) 5.3.0 Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32p4" +CONFIG_LWIP_PPP_SUPPORT=y +CONFIG_LWIP_PPP_SERVER_SUPPORT=y +CONFIG_LWIP_PPP_VJ_HEADER_COMPRESSION=n +CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN=17 +CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN=16 diff --git a/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.esp32h2 b/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.esp32h2 new file mode 100644 index 000000000..26ce34bdd --- /dev/null +++ b/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.esp32h2 @@ -0,0 +1,3 @@ +CONFIG_IDF_TARGET="esp32h2" +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_CONNECT_ETHERNET=y diff --git a/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.linux b/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.linux new file mode 100644 index 000000000..75186ee56 --- /dev/null +++ b/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.linux @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="linux" +# CONFIG_ESP_EVENT_POST_FROM_ISR is not set diff --git a/components/esp_wifi_remote/examples/server/CMakeLists.txt b/components/esp_wifi_remote/examples/server/CMakeLists.txt new file mode 100644 index 000000000..144b9e1a2 --- /dev/null +++ b/components/esp_wifi_remote/examples/server/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(pppos_slave) diff --git a/components/esp_wifi_remote/examples/server/README.md b/components/esp_wifi_remote/examples/server/README.md new file mode 100644 index 000000000..a8ff85f9f --- /dev/null +++ b/components/esp_wifi_remote/examples/server/README.md @@ -0,0 +1,7 @@ + +# Wi-Fi station to PPPoS server + +This example demonstrate using NAPT to bring connectivity from WiFi station to PPPoS server. + +This example expect a PPPoS client to connect to the server and use the connectivity. +The client could be a Linux computer with `pppd` service or another microcontroller with PPP client (or another ESP32 with not WiFi interface) diff --git a/components/esp_wifi_remote/examples/server/main/CMakeLists.txt b/components/esp_wifi_remote/examples/server/main/CMakeLists.txt new file mode 100644 index 000000000..2ba044442 --- /dev/null +++ b/components/esp_wifi_remote/examples/server/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "station_example_main.c" + INCLUDE_DIRS ".") diff --git a/components/esp_wifi_remote/examples/server/main/idf_component.yml b/components/esp_wifi_remote/examples/server/main/idf_component.yml new file mode 100644 index 000000000..22d411780 --- /dev/null +++ b/components/esp_wifi_remote/examples/server/main/idf_component.yml @@ -0,0 +1,5 @@ +dependencies: + espressif/eppp_link: "^0.0.1" + esp_wifi_remote: + version: "*" + override_path: ../../.. diff --git a/components/esp_wifi_remote/examples/server/main/station_example_main.c b/components/esp_wifi_remote/examples/server/main/station_example_main.c new file mode 100644 index 000000000..93516d3ca --- /dev/null +++ b/components/esp_wifi_remote/examples/server/main/station_example_main.c @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "eppp_link.h" +#include "esp_wifi_remote.h" + +esp_err_t server_init(void); + +void app_main(void) +{ + //Initialize NVS + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_create_default_wifi_sta(); + + server_init(); +} diff --git a/components/esp_wifi_remote/examples/server/sdkconfig.defaults b/components/esp_wifi_remote/examples/server/sdkconfig.defaults new file mode 100644 index 000000000..5aafc155a --- /dev/null +++ b/components/esp_wifi_remote/examples/server/sdkconfig.defaults @@ -0,0 +1,15 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) 5.3.0 Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32c6" +CONFIG_LWIP_IP_FORWARD=y +CONFIG_LWIP_IPV4_NAPT=y +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 +CONFIG_LWIP_PPP_SUPPORT=y +CONFIG_LWIP_PPP_SERVER_SUPPORT=y +CONFIG_LWIP_PPP_VJ_HEADER_COMPRESSION=n +CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN=22 +CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN=23 +CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CA="MIIDIzCCAgugAwIBAgIUTWOEAhITHAm2ixn5i2XlSeL01mowDQYJKoZIhvcNAQELBQAwITELMAkGA1UEBhMCQ1oxEjAQBgNVBAMMCUVzcHJlc3NpZjAeFw0yNDA0MTAxNTEzNTdaFw0yNTA0MTAxNTEzNTdaMCExCzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlFc3ByZXNzaWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCSewupiSiyZNfLdVW0/smQB0yJ0Ua0KNU423ZZ7HMSrBPhfHtnQQ6SJqTdfqGCl1lvSsJZN9aT4iaEtyAm6N9trmSbSWVlkn0D8MQuBHwHCT7jRsLnyRYURRPUs11TkQdqvxtsIFqFVFB/8nJqy4IuU6JFTobCbUappQMdHKCyidXJUVHZ5y+KK2kEYFiv26rHlry+D0O/VO5/xl97uFIzP0JVdnGNu5sy9uoRYp+ua0moD3tx12tYe83XIuHKbKHMpIayjPIoaZzhCwomZMh0NETEQ5t7RXYneRGZvXXyIb/O8jPCmbfSqJ6umhPhf757xBXHaC0iG/xlND0dnRIvAgMBAAGjUzBRMB0GA1UdDgQWBBTgqejeFi/5UAgNhNv4aH7UniqmQjAfBgNVHSMEGDAWgBTgqejeFi/5UAgNhNv4aH7UniqmQjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCQnqIue6KLXkjOXGtO5Bl4TkZpYAPkQuGiM6RgaBhdt3P5J1mF4T6aav8qGXSHShy1E3XkMR5OC3hkhG+FKBVKSaQLsRipuo+CeHp5RfOCNEzNI0RZwKJI92RcdWlhOA+pOTruXSoYuZvj0xnaePEghTrr7PLdgirpzIffLjvgh8BcQAz5QzP0U1XHkAVzbQjUBChiEiXVAlKChk7kKB/wEzwX3cvYKlTc89RB6I3+a+KhYJt3LIAOIDeyVp+Bhmb1JSo3H7zMpJAksG2RMnZCwlHeR6cMbb/OtJYeUKpNUxj0SaeNyHo3y8Q21G8TXcc9suU6sYJi780ArulC3cbQ" +CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CRT="MIICvzCCAacCFCanehvaDq0bhjZA/3W/h4b0p1VHMA0GCSqGSIb3DQEBCwUAMCExCzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlFc3ByZXNzaWYwHhcNMjQwNDEwMTUxMzU3WhcNMjUwNDEwMTUxMzU3WjAXMRUwEwYDVQQDDAwxOTIuMTY4LjExLjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsyR1FqBhBT3mr9AH/6iYoo1VCHbzB+V/StfCokv6LnMm6t7yiu1GgzqVk1aiHrUJGor5tBfpXywLnfVjFByZSBhhEkI26xQVdK5pZUsU1hMCJ6CWd105CD+0e5tTbGzF0PNH2KzFdg2YUqOSWBsfmgSNtnp3az8XmZN5i4958Sxe1kMN3f6EQwvkxZHGVgXCrUsdsHAEyV5NVfYq7P2nBxz3HJSGkTScFd+PRp3nfVFbBbCQDmqwoPZ7E/gUXjoLIFf7zjIMzCXTsZd/dKgXWWEFHq8SPWmLtAEvPCProT5QUaZ3gJSHup9Wmh+ok9W8wrwMj1sHlfiZWo3tatFmvAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAeWiWyTTyNbZRHq8X9qbr7oG6SYWOqDR3lPfs8wB8B+1Hez/JCrI/8quNqVAjhoTtebtp/2mcEseQDj5BOx8NBCDAmUOwB+ZKPzUoGiALy5XFGqUXzTv9tBMotC6dAMTIbT2Ql1mPJgtg2+Qv7vg6hsk4rlPMoICqN3lW6zXo2GOuJ56Tj5NkvVxv6MOVN2e3p67c92rRBysAxP6MaV8S9s2+VvnENuxpU5cq8sfzaxFkTn4UD9PoQSYGPNL9kv7Y/h7H5wlKiFY24KowPTHjulaH/DC9Fk4F1gNWjnkFcOgepzhiw/ibLrivMptUFtplFFbxGuwY5PaA26yhliBv8=" +CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_KEY="MIIEowIBAAKCAQEArMkdRagYQU95q/QB/+omKKNVQh28wflf0rXwqJL+i5zJure8ortRoM6lZNWoh61CRqK+bQX6V8sC531YxQcmUgYYRJCNusUFXSuaWVLFNYTAieglnddOQg/tHubU2xsxdDzR9isxXYNmFKjklgbH5oEjbZ6d2s/F5mTeYuPefEsXtZDDd3+hEML5MWRxlYFwq1LHbBwBMleTVX2Kuz9pwcc9xyUhpE0nBXfj0ad531RWwWwkA5qsKD2exP4FF46CyBX+84yDMwl07GXf3SoF1lhBR6vEj1pi7QBLzwj66E+UFGmd4CUh7qfVpofqJPVvMK8DI9bB5X4mVqN7WrRZrwIDAQABAoIBAHDh833OlAoXIiZ1A9lt4AAstUa8ptUTVscSlmeLoUEU7bZO0659MpccanG2JKR/TQ1YxY/0l9lDiGI0Qgp24VI1KSWiSvX6Qcbc9bnlmXGdiSyPvgOg5j/Cp+fIZse+vFB0a7eoAFhXwBk/PhfF1lOBiuPS/M43b9NVkvSIapJIaS4pvmkBvKSzHEvSArDHcr+1vFuFssZyHTnXmVgB4WiYPX4ACE8S18cnjXIQDfx8zpBbF/itnqeHDC5echnto63UDB7qHZa+DVvakhEtv50rzAuhq3/uspBClucuQUhlAAimd4OeKuwB1UC0K9AamDZRCnsf0O/Bo8/W4SWYAgECgYEA5LpRmcQ9ghW8V6bzwYvK8XGWyeNy94qOpZysFeOjxqe2sUTHVY2Ty1s44RbDd/bm0n3xcxMtLof/6Oz4TX+JseskQWBQlRiwuqc46CcHHjUQ8qokfWtASwWYgb6AzLa4B/D+H91wP/AzRfYNdRB9xhSCr7AOk9Vo5KmEPRLN/VMCgYEAwWM3oDaCkMicoMgngz/9dZ2/1yohfYdrupC0pGPhtBFNKghP+9S+e6cwWKzwQJbbRjGgt1OA3e4UEuTHJjp1tw+BRkNQ/1FI0psJGwmOtveAE7yiHf7Tw7mNDk+j32vpAPWnL7I3222Kv4G8xi2vSbn3IaI2sl7M0RHLJc/JCrUCgYBh4dI16aMg3khhglLiSv6oYKHU9/8lLChreyaxn19hDjjCl9puJE5RQlKPEPzJg+G3xqnjQxucxBqiBXclQyUb/LLhP2R8ybonxpQ11S3YoYEFOAaxnYpAEL75Fxtrf+41h85YuJzm39YxZGDR7iLE99YNdVxnq3ZeFKVAtaFtfQKBgEalPRvc7eOANZ+SnsSWqru9regnLubRgqw70pG/HyONsnepY7amaBN55vJt8rJVqbLBzGlMKuZn45NnWc0ATCJcmqgVTVCH3Cd7lV74Jdd3IKWVIk/82FVGwl25AC9NF2hPVQzaeQdCxA3jkhd/dupi8gGqZXrRoNa7PlAI0POFAoGBAJDlvddpEYcKhT3pncXIorVfYR67TlXVcKZHvL9XljwgDuf1j52ZhAs8UuoWW+NSgOdWVxocAshrLbu5fjSIN92oDAq6YVeXvxis6e8l79xd6A5iFH9Po+dEuQSaOR8XgW56n39oVR2hfaFwqijawIEzDNlYpiXAD3qNyW5e0MKA" diff --git a/components/esp_wifi_remote/idf_component.yml b/components/esp_wifi_remote/idf_component.yml index 8ef35fc4a..9acde64a7 100644 --- a/components/esp_wifi_remote/idf_component.yml +++ b/components/esp_wifi_remote/idf_component.yml @@ -2,6 +2,8 @@ version: 0.1.12 url: https://github.com/espressif/esp-protocols/tree/master/components/esp_wifi_remote description: Utility wrapper for esp_wifi functionality on remote targets dependencies: + espressif/eppp_link: + version: '0.0.1' idf: version: '5.3' # espressif/esp_hosted: diff --git a/components/esp_wifi_remote/include/esp_wifi_remote_api.h b/components/esp_wifi_remote/include/esp_wifi_remote_api.h index 420aa5e7e..2ddcd7ee2 100644 --- a/components/esp_wifi_remote/include/esp_wifi_remote_api.h +++ b/components/esp_wifi_remote/include/esp_wifi_remote_api.h @@ -57,10 +57,6 @@ esp_err_t esp_wifi_remote_80211_tx(wifi_interface_t ifx, const void *buffer, int esp_err_t esp_wifi_remote_set_csi_rx_cb(wifi_csi_cb_t cb, void *ctx); esp_err_t esp_wifi_remote_set_csi_config(const wifi_csi_config_t *config); esp_err_t esp_wifi_remote_set_csi(_Bool en); -esp_err_t esp_wifi_remote_set_ant_gpio(const wifi_ant_gpio_config_t *config); -esp_err_t esp_wifi_remote_get_ant_gpio(wifi_ant_gpio_config_t *config); -esp_err_t esp_wifi_remote_set_ant(const wifi_ant_config_t *config); -esp_err_t esp_wifi_remote_get_ant(wifi_ant_config_t *config); int64_t esp_wifi_remote_get_tsf_time(wifi_interface_t interface); esp_err_t esp_wifi_remote_set_inactive_time(wifi_interface_t ifx, uint16_t sec); esp_err_t esp_wifi_remote_get_inactive_time(wifi_interface_t ifx, uint16_t *sec); diff --git a/components/esp_wifi_remote/scripts/generate_and_check.py b/components/esp_wifi_remote/scripts/generate_and_check.py index c8df5b31a..37ac30762 100644 --- a/components/esp_wifi_remote/scripts/generate_and_check.py +++ b/components/esp_wifi_remote/scripts/generate_and_check.py @@ -15,6 +15,7 @@ Param = namedtuple('Param', ['ptr', 'array', 'qual', 'type', 'name']) AUTO_GENERATED = 'This file is auto-generated' COPYRIGHT_HEADER = open('copyright_header.h', 'r').read() NAMESPACE = re.compile(r'^esp_wifi') +DEPRECATED_API = ['esp_wifi_set_ant_gpio', 'esp_wifi_get_ant', 'esp_wifi_get_ant_gpio', 'esp_wifi_set_ant'] class FunctionVisitor(c_ast.NodeVisitor): @@ -51,6 +52,8 @@ class FunctionVisitor(c_ast.NodeVisitor): if isinstance(node.type, c_ast.TypeDecl): func_name = node.type.declname if func_name.startswith('esp_wifi') and func_name in self.content: + if func_name in DEPRECATED_API: + return ret = node.type.type.names[0] args = [] for param in node.args.params: @@ -309,6 +312,7 @@ def generate_kconfig(idf_path, component_path): f.write(' bool\n') f.write(' default y\n\n') f.write(' orsource "./Kconfig.soc_wifi_caps.in"\n') + f.write(' orsource "./Kconfig.rpc.in"\n') for line1 in lines: line = line1.strip() if re.match(r'^if\s+[A-Z_0-9]+\s*$', line): @@ -322,7 +326,7 @@ def generate_kconfig(idf_path, component_path): line1 = re.compile(config).sub('SLAVE_' + config, line1) f.write(line1) - if line.startswith('if ESP_WIFI_ENABLED'): + if re.match(r'^if\s+\(?ESP_WIFI_ENABLED', line): copy = nested_if f.write('endmenu # Wi-Fi Remote\n') return [remote_kconfig] diff --git a/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/Kconfig b/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/Kconfig index 48b4ed62e..e3e075afd 100644 --- a/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/Kconfig +++ b/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/Kconfig @@ -17,5 +17,7 @@ menu "ESP Hosted Mock" bool "esp32c6" config SLAVE_IDF_TARGET_ESP32H2 bool "esp32h2" + config SLAVE_IDF_TARGET_ESP32P4 + bool "esp32p4" endchoice endmenu diff --git a/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/esp_hosted_mock.c b/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/esp_hosted_mock.c index 6ae190a66..117d4a0da 100644 --- a/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/esp_hosted_mock.c +++ b/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/esp_hosted_mock.c @@ -267,26 +267,6 @@ esp_err_t esp_wifi_remote_set_csi(_Bool en) return ESP_OK; } -esp_err_t esp_wifi_remote_set_ant_gpio(const wifi_ant_gpio_config_t *config) -{ - return ESP_OK; -} - -esp_err_t esp_wifi_remote_get_ant_gpio(wifi_ant_gpio_config_t *config) -{ - return ESP_OK; -} - -esp_err_t esp_wifi_remote_set_ant(const wifi_ant_config_t *config) -{ - return ESP_OK; -} - -esp_err_t esp_wifi_remote_get_ant(wifi_ant_config_t *config) -{ - return ESP_OK; -} - int64_t esp_wifi_remote_get_tsf_time(wifi_interface_t interface) { return 0; diff --git a/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/include/esp_hosted_mock.h b/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/include/esp_hosted_mock.h index 420aa5e7e..2ddcd7ee2 100644 --- a/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/include/esp_hosted_mock.h +++ b/components/esp_wifi_remote/test/smoke_test/components/esp_hosted/include/esp_hosted_mock.h @@ -57,10 +57,6 @@ esp_err_t esp_wifi_remote_80211_tx(wifi_interface_t ifx, const void *buffer, int esp_err_t esp_wifi_remote_set_csi_rx_cb(wifi_csi_cb_t cb, void *ctx); esp_err_t esp_wifi_remote_set_csi_config(const wifi_csi_config_t *config); esp_err_t esp_wifi_remote_set_csi(_Bool en); -esp_err_t esp_wifi_remote_set_ant_gpio(const wifi_ant_gpio_config_t *config); -esp_err_t esp_wifi_remote_get_ant_gpio(wifi_ant_gpio_config_t *config); -esp_err_t esp_wifi_remote_set_ant(const wifi_ant_config_t *config); -esp_err_t esp_wifi_remote_get_ant(wifi_ant_config_t *config); int64_t esp_wifi_remote_get_tsf_time(wifi_interface_t interface); esp_err_t esp_wifi_remote_set_inactive_time(wifi_interface_t ifx, uint16_t sec); esp_err_t esp_wifi_remote_get_inactive_time(wifi_interface_t ifx, uint16_t *sec); diff --git a/components/esp_wifi_remote/test/smoke_test/main/all_wifi_calls.c b/components/esp_wifi_remote/test/smoke_test/main/all_wifi_calls.c index 196c4df3e..78ce3f592 100644 --- a/components/esp_wifi_remote/test/smoke_test/main/all_wifi_calls.c +++ b/components/esp_wifi_remote/test/smoke_test/main/all_wifi_calls.c @@ -280,26 +280,6 @@ void run_all_wifi_apis(void) esp_wifi_set_csi(en); } - { - const wifi_ant_gpio_config_t *config = NULL; - esp_wifi_set_ant_gpio(config); - } - - { - wifi_ant_gpio_config_t *config = NULL; - esp_wifi_get_ant_gpio(config); - } - - { - const wifi_ant_config_t *config = NULL; - esp_wifi_set_ant(config); - } - - { - wifi_ant_config_t *config = NULL; - esp_wifi_get_ant(config); - } - { wifi_interface_t interface = 0; esp_wifi_get_tsf_time(interface); diff --git a/components/esp_wifi_remote/test/smoke_test/main/all_wifi_remote_calls.c b/components/esp_wifi_remote/test/smoke_test/main/all_wifi_remote_calls.c index 9b49393da..fd2bea18f 100644 --- a/components/esp_wifi_remote/test/smoke_test/main/all_wifi_remote_calls.c +++ b/components/esp_wifi_remote/test/smoke_test/main/all_wifi_remote_calls.c @@ -280,26 +280,6 @@ void run_all_wifi_remote_apis(void) esp_wifi_remote_set_csi(en); } - { - const wifi_ant_gpio_config_t *config = NULL; - esp_wifi_remote_set_ant_gpio(config); - } - - { - wifi_ant_gpio_config_t *config = NULL; - esp_wifi_remote_get_ant_gpio(config); - } - - { - const wifi_ant_config_t *config = NULL; - esp_wifi_remote_set_ant(config); - } - - { - wifi_ant_config_t *config = NULL; - esp_wifi_remote_get_ant(config); - } - { wifi_interface_t interface = 0; esp_wifi_remote_get_tsf_time(interface); diff --git a/components/esp_wifi_remote/test/smoke_test/sdkconfig.defaults b/components/esp_wifi_remote/test/smoke_test/sdkconfig.defaults new file mode 100644 index 000000000..1f717cf36 --- /dev/null +++ b/components/esp_wifi_remote/test/smoke_test/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_LWIP_PPP_SUPPORT=y +CONFIG_LWIP_PPP_SERVER_SUPPORT=y diff --git a/components/esp_wifi_remote/wifi_apps/roaming_app/src/Kconfig.roaming b/components/esp_wifi_remote/wifi_apps/roaming_app/src/Kconfig.roaming new file mode 100644 index 000000000..e69de29bb From d2b7c55b89bab1aa8498f2f0047adbbcaf62b5c2 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 11 Apr 2024 15:00:48 +0200 Subject: [PATCH 2/4] fix(wifi_remote): Add examples to CI --- .github/workflows/wifi_remote__build.yml | 30 +++++++++++++- .../esp_wifi_remote/examples/mqtt/README.md | 4 +- .../examples/mqtt/sdkconfig.ci.p4 | 5 +++ .../examples/mqtt/sdkconfig.defaults | 6 --- .../examples/mqtt/sdkconfig.defaults.esp32h2 | 3 -- .../examples/mqtt/sdkconfig.defaults.linux | 2 - .../examples/server/sdkconfig.ci.c6 | 6 +++ .../examples/server/sdkconfig.defaults | 9 ---- .../test_certs/generate_test_certs.sh | 41 +++++++++++++++++++ 9 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 components/esp_wifi_remote/examples/mqtt/sdkconfig.ci.p4 delete mode 100644 components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.esp32h2 delete mode 100644 components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.linux create mode 100644 components/esp_wifi_remote/examples/server/sdkconfig.ci.c6 create mode 100755 components/esp_wifi_remote/examples/test_certs/generate_test_certs.sh diff --git a/.github/workflows/wifi_remote__build.yml b/.github/workflows/wifi_remote__build.yml index 0309273db..e607787cf 100644 --- a/.github/workflows/wifi_remote__build.yml +++ b/.github/workflows/wifi_remote__build.yml @@ -29,7 +29,7 @@ jobs: build_wifi_remote: if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push' - name: Build WiFi Remote + name: Build WiFi Remote Test strategy: matrix: idf_ver: ["latest"] @@ -48,4 +48,30 @@ jobs: run: | ${IDF_PATH}/install.sh --enable-pytest . ${IDF_PATH}/export.sh - python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.test.path}} -vv --preserve-all + echo "python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.test.path}} -vv --preserve-all" + + build_wifi_remote_example: + if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push' + name: Build WiFi Remote Example + strategy: + matrix: + idf_ver: ["latest"] + example: [ { app: host, path: "examples/mqtt" }, { app: slave, path: "examples/server" }] + include: + - idf_ver: "latest" + example: { app: slave, path: "examples/server" } + warning: "Warning: The smallest app partition is nearly full" + + runs-on: ubuntu-20.04 + container: espressif/idf:${{ matrix.idf_ver }} + steps: + - name: Checkout esp-protocols + uses: actions/checkout@v3 + - name: Build ${{ matrix.example.app }} with IDF-${{ matrix.idf_ver }} + env: + EXPECTED_WARNING: ${{ matrix.warning }} + shell: bash + run: | + ${IDF_PATH}/install.sh --enable-pytest + . ${IDF_PATH}/export.sh + python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.example.path}} -vv --preserve-all diff --git a/components/esp_wifi_remote/examples/mqtt/README.md b/components/esp_wifi_remote/examples/mqtt/README.md index acf680b75..3277edb00 100644 --- a/components/esp_wifi_remote/examples/mqtt/README.md +++ b/components/esp_wifi_remote/examples/mqtt/README.md @@ -1,4 +1,6 @@ -# MQTT demo application that runs on linux +# MQTT application running on WiFi station + +This is a simple mqtt demo, that connects to WiFi AP first. This application has a dependency to `esp_wifi_remote`, so that if it's build and executed on a chipset without WiFI capabilities it redirects all wifi calls the remote target. ## Overview diff --git a/components/esp_wifi_remote/examples/mqtt/sdkconfig.ci.p4 b/components/esp_wifi_remote/examples/mqtt/sdkconfig.ci.p4 new file mode 100644 index 000000000..8ca2fb7ae --- /dev/null +++ b/components/esp_wifi_remote/examples/mqtt/sdkconfig.ci.p4 @@ -0,0 +1,5 @@ +CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN=17 +CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN=16 +CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CA="MIIDIzCCAgugAwIBAgIULOncUeRLKxgrihIh1kHGGlPV7ecwDQYJKoZIhvcNAQELBQAwITELMAkGA1UEBhMCQ1oxEjAQBgNVBAMMCUVzcHJlc3NpZjAeFw0yNDA0MDMwOTE0MjNaFw0zNDA0MDEwOTE0MjNaMCExCzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlFc3ByZXNzaWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbayaZAuzQWrwRj3oiFP9AZK0ECaDvVlJec4M6yokded1pqNY+bNmA7VsHSQkf3d1rO1G5GwEXoMPli15m7rJodq9iYp1J2LhLhpKDNapm19reyH9A4rAfjSyk/WyvT+3Y5sNHVFdE2t1EetOyzy90CfOHT9JfWG9PiV6b1W65CqgjJVCHMWioppVAGQCoN+mDBf1VhD4am6onei+ijHdALJDfp74mSIOJGulm/IR7504s+yy7068PQ05V/wHkmd9O1Iww5fnJdRh2KvTFZVOB5u9y54MTJb0sGZj+JfxIbcFiIWAykLFVWBk5PO6yj8fNMmk/Ogb2K4wo7AZnJ3qBAgMBAAGjUzBRMB0GA1UdDgQWBBT3j77hJHm/hI34fEn3tocHqB4INzAfBgNVHSMEGDAWgBT3j77hJHm/hI34fEn3tocHqB4INzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBstXfBIRvqZp4OBQ2kCJig/CErcfdB4qQOS2LzQmpIOUQ4d/zvZOQD2WIw/x2Rd1/hto/+f57pOZNHsi8vfX2Z7kPOlD9ZG1wTznl1v8wOMP01AFJuVtmJQV0C4lVupb2/Mmu42xqP9pr/uL5pJ2rFb8ujl2xakhSvYVdMONtZL0mh9+hdnUb7Fj7KI3qWxzc7+uXGjCzh6LkOmcMBOB6+0V6xW2NVpUUPtuXytK0t2oyWpDvwFIrl0J6qBNRlH1ON1iz33HOo73IjprMNx3hIo5y/N8+TTxY6KEegbP67hSnJJhQ7tezoOu4OE0xmJp0XmGPMNewYARqL2UvHnZyf" +CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CRT="MIICwjCCAaoCFAWE4aJdYWbMJAaBTMxVpoXMrhzvMA0GCSqGSIb3DQEBCwUAMCExCzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlFc3ByZXNzaWYwHhcNMjQwNDAzMDkxNjE4WhcNMzQwNDAxMDkxNjE4WjAaMRgwFgYDVQQDDA9lc3ByZXNzaWYubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDcjdBQ3sHbfuWRo2LlqZF37Dfuymz5/fq+szcOLUUWCccxku9qNNEdZAcZHMsINurezpHXa6ZNKGqmbmqZPVrEKzMUIolpnQmcerRt/yKqxCZ/kgsJE3IZyqi1T+xDwaBEhgdB6+wxyrL0/uBlLCbEdZAA7MPcauIKz8ykfIwo7Ht/vcHNxGaFFu+DcNoJI/Pw6hERlC9DHuUftK0/Lap1K2o+6kFQKqhVrvNQmaiqnz3Dr9psPO90AvbRqeODmfpi7rtU4MKOprQhUrMS9s9d5yVdJILp74pt6nzu3EnFiixRD5XD9PtK5NvP1sgDAgbWgTttwM9X7N6mzEe/gVUZAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAJVsbAamDRuZ1J2ogHLo/UmjmcmIATmqO7Ebaoid7+FYme/2NFzofOFtJNaCumdhwxSyf7ER6m2DUO6bDseblqNCTyRDNNXzTHEFQiYh2PThKSDdH0fbEf4IpcbOCnpSEpIg9C/ywEhq/wzYiOlxPhNWxBKHLhEkM7aWBerAhInCRRXymfus2HUf6aTWZ0wigMoUVKwOu16Zh04D2d6qb314cEMgKvANPiTTdgEae7Ot+rP1s2Zp75zUbWuz4uWd4wJDOHWR25mkD3ZELfbrpmEymbOTQ26zOpIUiPNfYZ1t9KwEjkKN+jBTXKu7QhB/u+g5yBHjRL++LEli4YGGGiA=" +CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_KEY="MIIEpQIBAAKCAQEA3I3QUN7B237lkaNi5amRd+w37sps+f36vrM3Di1FFgnHMZLvajTRHWQHGRzLCDbq3s6R12umTShqpm5qmT1axCszFCKJaZ0JnHq0bf8iqsQmf5ILCRNyGcqotU/sQ8GgRIYHQevsMcqy9P7gZSwmxHWQAOzD3GriCs/MpHyMKOx7f73BzcRmhRbvg3DaCSPz8OoREZQvQx7lH7StPy2qdStqPupBUCqoVa7zUJmoqp89w6/abDzvdAL20anjg5n6Yu67VODCjqa0IVKzEvbPXeclXSSC6e+Kbep87txJxYosUQ+Vw/T7SuTbz9bIAwIG1oE7bcDPV+zepsxHv4FVGQIDAQABAoIBAQDPzzc224yg+iHoZaArcOhFrGbPMiAYNLxrroTzcKglqbTr+txmn7lhDfy6Jq0O4l/O66fy59Vb4fcLNgJuvKanK2UHVbtPrc1+iQc0lS7e4866aKrJNG9P6emoXNPqy6fsqLRx4o88IxcXTIe2DDHC7lpu5KdvKa4uLblOSqPtcZTHXPD9olVe8ZYF5CttMUTc4SkF4HSkY2jb0j+6kASN4eQ2CqEt+IW4IxI5NiEzrlzZSOdyqIOeyGUZz+QcfILOProWZHYzH3jOHQe4PJSXO57f2dojY1GqRcjnr3guQMpw1s7wmDYO1QekiBYwRERNzjEY7VhgDq8T0rwJPHP5AoGBAPO13QpJVSj1NfQ/H0AgZlsJIIlIwIC2YwuwjA7b36A3JOFolkHjtq4eNntThNRQbTL9OficbxJSHXQcOsQeo7dvwEhJjuVwEajL4/6cjc9b4oyGJxLlTKTshUPmeKPfGWUjRZKGbVWbT3m4BXqGiv4laCZ0LDHiCt4DvEzQ1Bo3AoGBAOetBClbcbUJhxkAme5HHI9A5VcqyOi2CrRh+HjKd/2IJlDA+Vmbl2iEB+9cMRGRubazbrk1yAzgtW29GX8kngr8yxDtIM8M7lPR2NhXx7XbmCKwKosZ7l6hHNdnD12TFyLCjuuJlUA37sWXw8r33623mLFQlNVjnL0onUa1XSMvAoGACw47+cR73YDKMstOQp11pzmRxUiMmworEhOvNtlYmq8FuEgDUPfgiKOMOyn9w5fmbEK6h4GpND6PYX4KWG0/ZgnmwiC8H8Jmuq6NKDa35Ck57MAFM8E9Kdok7YCeBmkPgNwJwuzgNtr1zwK/FODXm1HdGKl6e8TSU2H9/8oVZR8CgYEAoHSWI0awNCCLLufZtMwPna/mpz58s6ARPel0u8QO4st/LgLZMBSxArQfAsqpOW/iXgVcNG5pRXIEdiK4G/TyeM2onup9BKoCDo+SThRNv0h9z9iPPpQRIf0YCp/YZojPR0XU0pERi86xUqzP8C1I//neiUA0NK6vCdutQiGuhgUCgYEAp89EFcM1WvtPRJE+md8N8BUef5MJ+JJ0nb+BW1kkLY50Q1MVmsVXdUowYupWLBgEfMn8fy8Q+xD9EeiISTF9MtT1X4iQSI/pzKW5LLd0OJYnqPMWzyggASzSNWdYBIGNkqsQGmGCtF9+i6V4acfTTbMD9LiB7u5/enQa8N0Qg+s=" diff --git a/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults b/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults index 68c4ddef0..2e93e03bb 100644 --- a/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults +++ b/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults @@ -1,9 +1,3 @@ -# This file was generated using idf.py save-defconfig. It can be edited manually. -# Espressif IoT Development Framework (ESP-IDF) 5.3.0 Project Minimal Configuration -# -CONFIG_IDF_TARGET="esp32p4" CONFIG_LWIP_PPP_SUPPORT=y CONFIG_LWIP_PPP_SERVER_SUPPORT=y CONFIG_LWIP_PPP_VJ_HEADER_COMPRESSION=n -CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN=17 -CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN=16 diff --git a/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.esp32h2 b/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.esp32h2 deleted file mode 100644 index 26ce34bdd..000000000 --- a/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.esp32h2 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32h2" -CONFIG_EXAMPLE_CONNECT_WIFI=n -CONFIG_EXAMPLE_CONNECT_ETHERNET=y diff --git a/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.linux b/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.linux deleted file mode 100644 index 75186ee56..000000000 --- a/components/esp_wifi_remote/examples/mqtt/sdkconfig.defaults.linux +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_IDF_TARGET="linux" -# CONFIG_ESP_EVENT_POST_FROM_ISR is not set diff --git a/components/esp_wifi_remote/examples/server/sdkconfig.ci.c6 b/components/esp_wifi_remote/examples/server/sdkconfig.ci.c6 new file mode 100644 index 000000000..58f71a366 --- /dev/null +++ b/components/esp_wifi_remote/examples/server/sdkconfig.ci.c6 @@ -0,0 +1,6 @@ +CONFIG_IDF_TARGET="esp32c6" +CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN=22 +CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN=23 +CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CA="MIIDIzCCAgugAwIBAgIUTWOEAhITHAm2ixn5i2XlSeL01mowDQYJKoZIhvcNAQELBQAwITELMAkGA1UEBhMCQ1oxEjAQBgNVBAMMCUVzcHJlc3NpZjAeFw0yNDA0MTAxNTEzNTdaFw0yNTA0MTAxNTEzNTdaMCExCzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlFc3ByZXNzaWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCSewupiSiyZNfLdVW0/smQB0yJ0Ua0KNU423ZZ7HMSrBPhfHtnQQ6SJqTdfqGCl1lvSsJZN9aT4iaEtyAm6N9trmSbSWVlkn0D8MQuBHwHCT7jRsLnyRYURRPUs11TkQdqvxtsIFqFVFB/8nJqy4IuU6JFTobCbUappQMdHKCyidXJUVHZ5y+KK2kEYFiv26rHlry+D0O/VO5/xl97uFIzP0JVdnGNu5sy9uoRYp+ua0moD3tx12tYe83XIuHKbKHMpIayjPIoaZzhCwomZMh0NETEQ5t7RXYneRGZvXXyIb/O8jPCmbfSqJ6umhPhf757xBXHaC0iG/xlND0dnRIvAgMBAAGjUzBRMB0GA1UdDgQWBBTgqejeFi/5UAgNhNv4aH7UniqmQjAfBgNVHSMEGDAWgBTgqejeFi/5UAgNhNv4aH7UniqmQjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCQnqIue6KLXkjOXGtO5Bl4TkZpYAPkQuGiM6RgaBhdt3P5J1mF4T6aav8qGXSHShy1E3XkMR5OC3hkhG+FKBVKSaQLsRipuo+CeHp5RfOCNEzNI0RZwKJI92RcdWlhOA+pOTruXSoYuZvj0xnaePEghTrr7PLdgirpzIffLjvgh8BcQAz5QzP0U1XHkAVzbQjUBChiEiXVAlKChk7kKB/wEzwX3cvYKlTc89RB6I3+a+KhYJt3LIAOIDeyVp+Bhmb1JSo3H7zMpJAksG2RMnZCwlHeR6cMbb/OtJYeUKpNUxj0SaeNyHo3y8Q21G8TXcc9suU6sYJi780ArulC3cbQ" +CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CRT="MIICvzCCAacCFCanehvaDq0bhjZA/3W/h4b0p1VHMA0GCSqGSIb3DQEBCwUAMCExCzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlFc3ByZXNzaWYwHhcNMjQwNDEwMTUxMzU3WhcNMjUwNDEwMTUxMzU3WjAXMRUwEwYDVQQDDAwxOTIuMTY4LjExLjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsyR1FqBhBT3mr9AH/6iYoo1VCHbzB+V/StfCokv6LnMm6t7yiu1GgzqVk1aiHrUJGor5tBfpXywLnfVjFByZSBhhEkI26xQVdK5pZUsU1hMCJ6CWd105CD+0e5tTbGzF0PNH2KzFdg2YUqOSWBsfmgSNtnp3az8XmZN5i4958Sxe1kMN3f6EQwvkxZHGVgXCrUsdsHAEyV5NVfYq7P2nBxz3HJSGkTScFd+PRp3nfVFbBbCQDmqwoPZ7E/gUXjoLIFf7zjIMzCXTsZd/dKgXWWEFHq8SPWmLtAEvPCProT5QUaZ3gJSHup9Wmh+ok9W8wrwMj1sHlfiZWo3tatFmvAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAeWiWyTTyNbZRHq8X9qbr7oG6SYWOqDR3lPfs8wB8B+1Hez/JCrI/8quNqVAjhoTtebtp/2mcEseQDj5BOx8NBCDAmUOwB+ZKPzUoGiALy5XFGqUXzTv9tBMotC6dAMTIbT2Ql1mPJgtg2+Qv7vg6hsk4rlPMoICqN3lW6zXo2GOuJ56Tj5NkvVxv6MOVN2e3p67c92rRBysAxP6MaV8S9s2+VvnENuxpU5cq8sfzaxFkTn4UD9PoQSYGPNL9kv7Y/h7H5wlKiFY24KowPTHjulaH/DC9Fk4F1gNWjnkFcOgepzhiw/ibLrivMptUFtplFFbxGuwY5PaA26yhliBv8=" +CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_KEY="MIIEowIBAAKCAQEArMkdRagYQU95q/QB/+omKKNVQh28wflf0rXwqJL+i5zJure8ortRoM6lZNWoh61CRqK+bQX6V8sC531YxQcmUgYYRJCNusUFXSuaWVLFNYTAieglnddOQg/tHubU2xsxdDzR9isxXYNmFKjklgbH5oEjbZ6d2s/F5mTeYuPefEsXtZDDd3+hEML5MWRxlYFwq1LHbBwBMleTVX2Kuz9pwcc9xyUhpE0nBXfj0ad531RWwWwkA5qsKD2exP4FF46CyBX+84yDMwl07GXf3SoF1lhBR6vEj1pi7QBLzwj66E+UFGmd4CUh7qfVpofqJPVvMK8DI9bB5X4mVqN7WrRZrwIDAQABAoIBAHDh833OlAoXIiZ1A9lt4AAstUa8ptUTVscSlmeLoUEU7bZO0659MpccanG2JKR/TQ1YxY/0l9lDiGI0Qgp24VI1KSWiSvX6Qcbc9bnlmXGdiSyPvgOg5j/Cp+fIZse+vFB0a7eoAFhXwBk/PhfF1lOBiuPS/M43b9NVkvSIapJIaS4pvmkBvKSzHEvSArDHcr+1vFuFssZyHTnXmVgB4WiYPX4ACE8S18cnjXIQDfx8zpBbF/itnqeHDC5echnto63UDB7qHZa+DVvakhEtv50rzAuhq3/uspBClucuQUhlAAimd4OeKuwB1UC0K9AamDZRCnsf0O/Bo8/W4SWYAgECgYEA5LpRmcQ9ghW8V6bzwYvK8XGWyeNy94qOpZysFeOjxqe2sUTHVY2Ty1s44RbDd/bm0n3xcxMtLof/6Oz4TX+JseskQWBQlRiwuqc46CcHHjUQ8qokfWtASwWYgb6AzLa4B/D+H91wP/AzRfYNdRB9xhSCr7AOk9Vo5KmEPRLN/VMCgYEAwWM3oDaCkMicoMgngz/9dZ2/1yohfYdrupC0pGPhtBFNKghP+9S+e6cwWKzwQJbbRjGgt1OA3e4UEuTHJjp1tw+BRkNQ/1FI0psJGwmOtveAE7yiHf7Tw7mNDk+j32vpAPWnL7I3222Kv4G8xi2vSbn3IaI2sl7M0RHLJc/JCrUCgYBh4dI16aMg3khhglLiSv6oYKHU9/8lLChreyaxn19hDjjCl9puJE5RQlKPEPzJg+G3xqnjQxucxBqiBXclQyUb/LLhP2R8ybonxpQ11S3YoYEFOAaxnYpAEL75Fxtrf+41h85YuJzm39YxZGDR7iLE99YNdVxnq3ZeFKVAtaFtfQKBgEalPRvc7eOANZ+SnsSWqru9regnLubRgqw70pG/HyONsnepY7amaBN55vJt8rJVqbLBzGlMKuZn45NnWc0ATCJcmqgVTVCH3Cd7lV74Jdd3IKWVIk/82FVGwl25AC9NF2hPVQzaeQdCxA3jkhd/dupi8gGqZXrRoNa7PlAI0POFAoGBAJDlvddpEYcKhT3pncXIorVfYR67TlXVcKZHvL9XljwgDuf1j52ZhAs8UuoWW+NSgOdWVxocAshrLbu5fjSIN92oDAq6YVeXvxis6e8l79xd6A5iFH9Po+dEuQSaOR8XgW56n39oVR2hfaFwqijawIEzDNlYpiXAD3qNyW5e0MKA" diff --git a/components/esp_wifi_remote/examples/server/sdkconfig.defaults b/components/esp_wifi_remote/examples/server/sdkconfig.defaults index 5aafc155a..f2afde685 100644 --- a/components/esp_wifi_remote/examples/server/sdkconfig.defaults +++ b/components/esp_wifi_remote/examples/server/sdkconfig.defaults @@ -1,15 +1,6 @@ -# This file was generated using idf.py save-defconfig. It can be edited manually. -# Espressif IoT Development Framework (ESP-IDF) 5.3.0 Project Minimal Configuration -# -CONFIG_IDF_TARGET="esp32c6" CONFIG_LWIP_IP_FORWARD=y CONFIG_LWIP_IPV4_NAPT=y CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 CONFIG_LWIP_PPP_SUPPORT=y CONFIG_LWIP_PPP_SERVER_SUPPORT=y CONFIG_LWIP_PPP_VJ_HEADER_COMPRESSION=n -CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN=22 -CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN=23 -CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CA="MIIDIzCCAgugAwIBAgIUTWOEAhITHAm2ixn5i2XlSeL01mowDQYJKoZIhvcNAQELBQAwITELMAkGA1UEBhMCQ1oxEjAQBgNVBAMMCUVzcHJlc3NpZjAeFw0yNDA0MTAxNTEzNTdaFw0yNTA0MTAxNTEzNTdaMCExCzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlFc3ByZXNzaWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCSewupiSiyZNfLdVW0/smQB0yJ0Ua0KNU423ZZ7HMSrBPhfHtnQQ6SJqTdfqGCl1lvSsJZN9aT4iaEtyAm6N9trmSbSWVlkn0D8MQuBHwHCT7jRsLnyRYURRPUs11TkQdqvxtsIFqFVFB/8nJqy4IuU6JFTobCbUappQMdHKCyidXJUVHZ5y+KK2kEYFiv26rHlry+D0O/VO5/xl97uFIzP0JVdnGNu5sy9uoRYp+ua0moD3tx12tYe83XIuHKbKHMpIayjPIoaZzhCwomZMh0NETEQ5t7RXYneRGZvXXyIb/O8jPCmbfSqJ6umhPhf757xBXHaC0iG/xlND0dnRIvAgMBAAGjUzBRMB0GA1UdDgQWBBTgqejeFi/5UAgNhNv4aH7UniqmQjAfBgNVHSMEGDAWgBTgqejeFi/5UAgNhNv4aH7UniqmQjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCQnqIue6KLXkjOXGtO5Bl4TkZpYAPkQuGiM6RgaBhdt3P5J1mF4T6aav8qGXSHShy1E3XkMR5OC3hkhG+FKBVKSaQLsRipuo+CeHp5RfOCNEzNI0RZwKJI92RcdWlhOA+pOTruXSoYuZvj0xnaePEghTrr7PLdgirpzIffLjvgh8BcQAz5QzP0U1XHkAVzbQjUBChiEiXVAlKChk7kKB/wEzwX3cvYKlTc89RB6I3+a+KhYJt3LIAOIDeyVp+Bhmb1JSo3H7zMpJAksG2RMnZCwlHeR6cMbb/OtJYeUKpNUxj0SaeNyHo3y8Q21G8TXcc9suU6sYJi780ArulC3cbQ" -CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CRT="MIICvzCCAacCFCanehvaDq0bhjZA/3W/h4b0p1VHMA0GCSqGSIb3DQEBCwUAMCExCzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlFc3ByZXNzaWYwHhcNMjQwNDEwMTUxMzU3WhcNMjUwNDEwMTUxMzU3WjAXMRUwEwYDVQQDDAwxOTIuMTY4LjExLjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsyR1FqBhBT3mr9AH/6iYoo1VCHbzB+V/StfCokv6LnMm6t7yiu1GgzqVk1aiHrUJGor5tBfpXywLnfVjFByZSBhhEkI26xQVdK5pZUsU1hMCJ6CWd105CD+0e5tTbGzF0PNH2KzFdg2YUqOSWBsfmgSNtnp3az8XmZN5i4958Sxe1kMN3f6EQwvkxZHGVgXCrUsdsHAEyV5NVfYq7P2nBxz3HJSGkTScFd+PRp3nfVFbBbCQDmqwoPZ7E/gUXjoLIFf7zjIMzCXTsZd/dKgXWWEFHq8SPWmLtAEvPCProT5QUaZ3gJSHup9Wmh+ok9W8wrwMj1sHlfiZWo3tatFmvAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAeWiWyTTyNbZRHq8X9qbr7oG6SYWOqDR3lPfs8wB8B+1Hez/JCrI/8quNqVAjhoTtebtp/2mcEseQDj5BOx8NBCDAmUOwB+ZKPzUoGiALy5XFGqUXzTv9tBMotC6dAMTIbT2Ql1mPJgtg2+Qv7vg6hsk4rlPMoICqN3lW6zXo2GOuJ56Tj5NkvVxv6MOVN2e3p67c92rRBysAxP6MaV8S9s2+VvnENuxpU5cq8sfzaxFkTn4UD9PoQSYGPNL9kv7Y/h7H5wlKiFY24KowPTHjulaH/DC9Fk4F1gNWjnkFcOgepzhiw/ibLrivMptUFtplFFbxGuwY5PaA26yhliBv8=" -CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_KEY="MIIEowIBAAKCAQEArMkdRagYQU95q/QB/+omKKNVQh28wflf0rXwqJL+i5zJure8ortRoM6lZNWoh61CRqK+bQX6V8sC531YxQcmUgYYRJCNusUFXSuaWVLFNYTAieglnddOQg/tHubU2xsxdDzR9isxXYNmFKjklgbH5oEjbZ6d2s/F5mTeYuPefEsXtZDDd3+hEML5MWRxlYFwq1LHbBwBMleTVX2Kuz9pwcc9xyUhpE0nBXfj0ad531RWwWwkA5qsKD2exP4FF46CyBX+84yDMwl07GXf3SoF1lhBR6vEj1pi7QBLzwj66E+UFGmd4CUh7qfVpofqJPVvMK8DI9bB5X4mVqN7WrRZrwIDAQABAoIBAHDh833OlAoXIiZ1A9lt4AAstUa8ptUTVscSlmeLoUEU7bZO0659MpccanG2JKR/TQ1YxY/0l9lDiGI0Qgp24VI1KSWiSvX6Qcbc9bnlmXGdiSyPvgOg5j/Cp+fIZse+vFB0a7eoAFhXwBk/PhfF1lOBiuPS/M43b9NVkvSIapJIaS4pvmkBvKSzHEvSArDHcr+1vFuFssZyHTnXmVgB4WiYPX4ACE8S18cnjXIQDfx8zpBbF/itnqeHDC5echnto63UDB7qHZa+DVvakhEtv50rzAuhq3/uspBClucuQUhlAAimd4OeKuwB1UC0K9AamDZRCnsf0O/Bo8/W4SWYAgECgYEA5LpRmcQ9ghW8V6bzwYvK8XGWyeNy94qOpZysFeOjxqe2sUTHVY2Ty1s44RbDd/bm0n3xcxMtLof/6Oz4TX+JseskQWBQlRiwuqc46CcHHjUQ8qokfWtASwWYgb6AzLa4B/D+H91wP/AzRfYNdRB9xhSCr7AOk9Vo5KmEPRLN/VMCgYEAwWM3oDaCkMicoMgngz/9dZ2/1yohfYdrupC0pGPhtBFNKghP+9S+e6cwWKzwQJbbRjGgt1OA3e4UEuTHJjp1tw+BRkNQ/1FI0psJGwmOtveAE7yiHf7Tw7mNDk+j32vpAPWnL7I3222Kv4G8xi2vSbn3IaI2sl7M0RHLJc/JCrUCgYBh4dI16aMg3khhglLiSv6oYKHU9/8lLChreyaxn19hDjjCl9puJE5RQlKPEPzJg+G3xqnjQxucxBqiBXclQyUb/LLhP2R8ybonxpQ11S3YoYEFOAaxnYpAEL75Fxtrf+41h85YuJzm39YxZGDR7iLE99YNdVxnq3ZeFKVAtaFtfQKBgEalPRvc7eOANZ+SnsSWqru9regnLubRgqw70pG/HyONsnepY7amaBN55vJt8rJVqbLBzGlMKuZn45NnWc0ATCJcmqgVTVCH3Cd7lV74Jdd3IKWVIk/82FVGwl25AC9NF2hPVQzaeQdCxA3jkhd/dupi8gGqZXrRoNa7PlAI0POFAoGBAJDlvddpEYcKhT3pncXIorVfYR67TlXVcKZHvL9XljwgDuf1j52ZhAs8UuoWW+NSgOdWVxocAshrLbu5fjSIN92oDAq6YVeXvxis6e8l79xd6A5iFH9Po+dEuQSaOR8XgW56n39oVR2hfaFwqijawIEzDNlYpiXAD3qNyW5e0MKA" diff --git a/components/esp_wifi_remote/examples/test_certs/generate_test_certs.sh b/components/esp_wifi_remote/examples/test_certs/generate_test_certs.sh new file mode 100755 index 000000000..e67249016 --- /dev/null +++ b/components/esp_wifi_remote/examples/test_certs/generate_test_certs.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +if [ -z "$1" ]; then + echo "Usage $0 [CLIENT_CN]" + exit 1; +fi + +SERVER_CN=$1 +CLIENT_CN="${2-client_cn}" + +echo "Server's CN: $SERVER_CN" +echo "Client's CN: $CLIENT_CN" + +## First create our own CA +openssl genrsa -out ca.key 2048 +openssl req -new -x509 -subj "/C=CZ/CN=Espressif" -days 365 -key ca.key -out ca.crt + +# Server side +openssl genrsa -out srv.key 2048 +openssl req -out srv.csr -key srv.key -subj "/CN=$SERVER_CN" -new -sha256 +openssl x509 -req -in srv.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out srv.crt -days 365 -sha256 + +# Client side +openssl genrsa -out client.key 2048 +openssl req -out client.csr -key client.key -subj "/CN=$CLIENT_CN" -new -sha256 +openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 -sha256 + +## Generate config options +# Client side: +CA_CRT=`cat ca.crt | sed '/---/d' | tr -d '\n'` +echo "CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CA=\"$CA_CRT\"" +CLIENT_CRT=`cat client.crt | sed '/---/d' | tr -d '\n'` +echo "CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CRT=\"$CLIENT_CRT\"" +CLIENT_KEY=`cat client.key | sed '/---/d' | tr -d '\n'` +echo "CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_KEY=\"$CLIENT_KEY\"" +## Server side (here it uses the same CA) +echo "CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CA=\"$CA_CRT\"" +SERVER_CRT=`cat srv.crt | sed '/---/d' | tr -d '\n'` +echo "CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CRT=\"$SERVER_CRT\"" +SERVER_KEY=`cat srv.key | sed '/---/d' | tr -d '\n'` +echo "CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_KEY=\"$SERVER_KEY\"" From 6c82ce2915d92971e24c3114acca5fa63a6a8481 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 11 Apr 2024 15:44:47 +0200 Subject: [PATCH 3/4] fix(wifi_remote): Make services restartable, code cleanup --- .github/workflows/wifi_remote__build.yml | 2 +- components/esp_wifi_remote/Kconfig.rpc.in | 38 ++++-------- components/esp_wifi_remote/eppp/eppp_init.c | 7 +-- .../eppp/wifi_remote_rpc_client.cpp | 60 ++++++++++++------- .../eppp/wifi_remote_rpc_impl.hpp | 31 +++++++++- .../eppp/wifi_remote_rpc_server.cpp | 5 +- .../examples/mqtt/CMakeLists.txt | 18 ------ .../esp_wifi_remote/examples/mqtt/README.md | 46 ++++++-------- .../esp_wifi_remote/examples/server/README.md | 22 +++++-- components/esp_wifi_remote/idf_component.yml | 2 +- .../test/smoke_test/main/idf_component.yml | 2 +- 11 files changed, 122 insertions(+), 111 deletions(-) diff --git a/.github/workflows/wifi_remote__build.yml b/.github/workflows/wifi_remote__build.yml index e607787cf..e2d096e01 100644 --- a/.github/workflows/wifi_remote__build.yml +++ b/.github/workflows/wifi_remote__build.yml @@ -48,7 +48,7 @@ jobs: run: | ${IDF_PATH}/install.sh --enable-pytest . ${IDF_PATH}/export.sh - echo "python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.test.path}} -vv --preserve-all" + python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.test.path}} -vv --preserve-all build_wifi_remote_example: if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push' diff --git a/components/esp_wifi_remote/Kconfig.rpc.in b/components/esp_wifi_remote/Kconfig.rpc.in index 204a40083..d63530ab7 100644 --- a/components/esp_wifi_remote/Kconfig.rpc.in +++ b/components/esp_wifi_remote/Kconfig.rpc.in @@ -15,35 +15,20 @@ choice ESP_WIFI_REMOTE_LIBRARY endchoice if ESP_WIFI_REMOTE_LIBRARY_EPPP - menu "WiFi remote by EPPP" - choice ESP_WIFI_REMOTE_EPPP_TRANSPORT - prompt "Choose EPPP transport" - default ESP_WIFI_REMOTE_EPPP_TRANSPORT_UART + config ESP_WIFI_REMOTE_EPPP_UART_TX_PIN + int "TXD Pin Number" + default 10 + range 0 31 help - Select type of EPPP transport + Pin number of UART TX. - config ESP_WIFI_REMOTE_EPPP_TRANSPORT_UART - bool "UART" - config ESP_WIFI_REMOTE_EPPP_TRANSPORT_SPI - bool "SPI" - endchoice - - if ESP_WIFI_REMOTE_EPPP_TRANSPORT_UART - config ESP_WIFI_REMOTE_EPPP_UART_TX_PIN - int "TXD Pin Number" - default 10 - range 0 31 - help - Pin number of UART TX. - - config ESP_WIFI_REMOTE_EPPP_UART_RX_PIN - int "RXD Pin Number" - default 11 - range 0 31 - help - Pin number of UART RX. - endif + config ESP_WIFI_REMOTE_EPPP_UART_RX_PIN + int "RXD Pin Number" + default 11 + range 0 31 + help + Pin number of UART RX. config ESP_WIFI_REMOTE_EPPP_SERVER_CA string "Servers CA certificate" @@ -68,6 +53,5 @@ endchoice config ESP_WIFI_REMOTE_EPPP_SERVER_KEY string "Server key" default "--- Please copy content of the Client key ---" - endmenu endif diff --git a/components/esp_wifi_remote/eppp/eppp_init.c b/components/esp_wifi_remote/eppp/eppp_init.c index 574ebfd2a..9c22eb2f3 100644 --- a/components/esp_wifi_remote/eppp/eppp_init.c +++ b/components/esp_wifi_remote/eppp/eppp_init.c @@ -7,17 +7,14 @@ #include "esp_wifi.h" #include "eppp_link.h" -esp_netif_t *wifi_remote_eppp_init(eppp_type_t role) +__attribute__((weak)) esp_netif_t *wifi_remote_eppp_init(eppp_type_t role) { uint32_t our_ip = role == EPPP_SERVER ? EPPP_DEFAULT_SERVER_IP() : EPPP_DEFAULT_CLIENT_IP(); uint32_t their_ip = role == EPPP_SERVER ? EPPP_DEFAULT_CLIENT_IP() : EPPP_DEFAULT_SERVER_IP(); eppp_config_t config = EPPP_DEFAULT_CONFIG(our_ip, their_ip); -#if CONFIG_ESP_WIFI_REMOTE_EPPP_TRANSPORT_UART + // We currently support only UART transport config.transport = EPPP_TRANSPORT_UART; config.uart.tx_io = CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN; config.uart.rx_io = CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN; -#else -#error ESP_WIFI_REMOTE supports only UART transport -#endif return eppp_open(role, &config, portMAX_DELAY); } diff --git a/components/esp_wifi_remote/eppp/wifi_remote_rpc_client.cpp b/components/esp_wifi_remote/eppp/wifi_remote_rpc_client.cpp index 2bbb76685..c287cc167 100644 --- a/components/esp_wifi_remote/eppp/wifi_remote_rpc_client.cpp +++ b/components/esp_wifi_remote/eppp/wifi_remote_rpc_client.cpp @@ -26,12 +26,15 @@ const char *TAG = "rpc_client"; const unsigned char ca_crt[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CA "\n-----END CERTIFICATE-----"; const unsigned char crt[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CRT "\n-----END CERTIFICATE-----"; const unsigned char key[] = "-----BEGIN RSA PRIVATE KEY-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_KEY "\n-----END RSA PRIVATE KEY-----"; +// TODO: Add option to supply keys and certs via a global symbol (file) } using namespace client; -struct Sync { +class Sync { + friend class RpcInstance; +public: void lock() { xSemaphoreTake(mutex, portMAX_DELAY); @@ -48,7 +51,7 @@ struct Sync { } esp_err_t wait_for(EventBits_t bits, uint32_t timeout = portMAX_DELAY) { - return xEventGroupWaitBits(events, bits, pdTRUE, pdTRUE, timeout) == bits ? ESP_OK : ESP_FAIL; + return (xEventGroupWaitBits(events, bits, pdTRUE, pdTRUE, timeout) & bits) == bits ? ESP_OK : ESP_FAIL; } esp_err_t notify(EventBits_t bits) { @@ -64,30 +67,36 @@ struct Sync { vEventGroupDelete(events); } } + + +private: SemaphoreHandle_t mutex{nullptr}; EventGroupHandle_t events{nullptr}; + const int request = 1; const int resp_header = 2; const int resp_payload = 4; - + const int restart = 8; }; class RpcInstance { + friend class Sync; public: + template esp_err_t send(api_id id, T *t) { - ESP_RETURN_ON_ERROR(sync.notify(sync.request), TAG, "failed to notify req"); pending_resp = id; + ESP_RETURN_ON_ERROR(sync.notify(sync.request), TAG, "failed to notify req"); ESP_RETURN_ON_ERROR(rpc.send(id, t), TAG, "Failed to send request"); return ESP_OK; } - // specialization for (void) + // overload of the templated method (used for functions with no arguments) esp_err_t send(api_id id) { - ESP_RETURN_ON_ERROR(sync.notify(sync.request), TAG, "failed to notify req"); pending_resp = id; + ESP_RETURN_ON_ERROR(sync.notify(sync.request), TAG, "failed to notify req"); ESP_RETURN_ON_ERROR(rpc.send(id), TAG, "Failed to send request"); return ESP_OK; } @@ -103,6 +112,7 @@ public: esp_err_t init() { ESP_RETURN_ON_FALSE(netif = wifi_remote_eppp_init(EPPP_CLIENT), ESP_FAIL, TAG, "Failed to connect to EPPP server"); + ESP_RETURN_ON_ERROR(esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, got_ip, this), TAG, "Failed to register event"); ESP_RETURN_ON_ERROR(sync.init(), TAG, "Failed to init sync primitives"); ESP_RETURN_ON_ERROR(rpc.init(), TAG, "Failed to init RPC engine"); return xTaskCreate(task, "client", 8192, this, 5, nullptr) == pdTRUE ? ESP_OK : ESP_FAIL; @@ -168,15 +178,28 @@ private: static void task(void *ctx) { auto instance = static_cast(ctx); - while (instance->perform() == ESP_OK) {} + do { + while (instance->perform() == ESP_OK) {} + } while (instance->restart() == ESP_OK); vTaskDelete(nullptr); } + esp_err_t restart() + { + rpc.deinit(); + ESP_RETURN_ON_ERROR(sync.wait_for(sync.restart, pdMS_TO_TICKS(10000)), TAG, "Didn't receive EPPP address in time"); + return rpc.init(); + } + static void got_ip(void *ctx, esp_event_base_t base, int32_t id, void *data) + { + auto instance = static_cast(ctx); + instance->sync.notify(instance->sync.restart); + } esp_netif_t *netif{nullptr}; }; namespace client { -RpcInstance instance; +constinit RpcInstance instance; } // namespace client RpcInstance *RpcEngine::init_client() @@ -196,20 +219,17 @@ RpcInstance *RpcEngine::init_client() cfg.clientkey_bytes = sizeof(client::key); cfg.common_name = "espressif.local"; - tls_ = esp_tls_init(); - if (!tls_) { - ESP_LOGE(TAG, "Failed to allocate esp_tls handle!"); - goto exit; - } - if (esp_tls_conn_new_sync(host, strlen(host), rpc_port, &cfg, tls_) <= 0) { - ESP_LOGE(TAG, "Failed to open a new connection %s", host); - goto exit; + ESP_RETURN_ON_FALSE(tls_ = esp_tls_init(), nullptr, TAG, "Failed to create ESP-TLS instance"); + int retries = 0; + while (esp_tls_conn_new_sync(host, strlen(host), rpc_port, &cfg, tls_) <= 0) { + esp_tls_conn_destroy(tls_); + tls_ = nullptr; + ESP_RETURN_ON_FALSE(retries++ < 3, nullptr, TAG, "Failed to open connection to %s", host); + ESP_LOGW(TAG, "Connection to RPC server failed! Will retry in %d second(s)", retries); + vTaskDelay(pdMS_TO_TICKS(1000 * retries)); + ESP_RETURN_ON_FALSE(tls_ = esp_tls_init(), nullptr, TAG, "Failed to create ESP-TLS instance"); } return &client::instance; -exit: - esp_tls_conn_destroy(tls_); - tls_ = nullptr; - return nullptr; } } // namespace eppp_rpc diff --git a/components/esp_wifi_remote/eppp/wifi_remote_rpc_impl.hpp b/components/esp_wifi_remote/eppp/wifi_remote_rpc_impl.hpp index beb87d407..30a0104db 100644 --- a/components/esp_wifi_remote/eppp/wifi_remote_rpc_impl.hpp +++ b/components/esp_wifi_remote/eppp/wifi_remote_rpc_impl.hpp @@ -9,8 +9,11 @@ namespace eppp_rpc { -const int rpc_port = 3333; +static constexpr int rpc_port = 3333; +/** + * @brief Currently supported RPC commands/events + */ enum class api_id : uint32_t { ERROR, UNDEF, @@ -35,6 +38,9 @@ struct RpcHeader { uint32_t size; } __attribute((__packed__)); +/** + * @brief Structure holding the outgoing or incoming parameter + */ template struct RpcData { RpcHeader head; @@ -54,11 +60,17 @@ struct RpcData { } } __attribute((__packed__)); +/** + * @brief Singleton holding the static data for either the client or server side + */ class RpcInstance; +/** + * @brief Engine that implements a simple RPC mechanism + */ class RpcEngine { public: - explicit RpcEngine(role r) : tls_(nullptr), role_(r) {} + constexpr explicit RpcEngine(role r) : tls_(nullptr), role_(r) {} esp_err_t init() { @@ -74,6 +86,19 @@ public: return instance == nullptr ? ESP_FAIL : ESP_OK; } + void deinit() + { + if (tls_ == nullptr) { + return; + } + if (role_ == role::CLIENT) { + esp_tls_conn_destroy(tls_); + } else if (role_ == role::SERVER) { + esp_tls_server_session_delete(tls_); + } + tls_ = nullptr; + } + template esp_err_t send(api_id id, T *t) { @@ -90,7 +115,7 @@ public: return ESP_OK; } - esp_err_t send(api_id id) // specialization for (void) + esp_err_t send(api_id id) // overload for (void) { RpcHeader head = {.id = id, .size = 0}; int len = esp_tls_conn_write(tls_, &head, sizeof(head)); diff --git a/components/esp_wifi_remote/eppp/wifi_remote_rpc_server.cpp b/components/esp_wifi_remote/eppp/wifi_remote_rpc_server.cpp index aed9faa54..0a8645d95 100644 --- a/components/esp_wifi_remote/eppp/wifi_remote_rpc_server.cpp +++ b/components/esp_wifi_remote/eppp/wifi_remote_rpc_server.cpp @@ -26,6 +26,7 @@ const char *TAG = "rpc_server"; const unsigned char ca_crt[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CA "\n-----END CERTIFICATE-----"; const unsigned char crt[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CRT "\n-----END CERTIFICATE-----"; const unsigned char key[] = "-----BEGIN RSA PRIVATE KEY-----\n" CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_KEY "\n-----END RSA PRIVATE KEY-----"; +// TODO: Add option to supply keys and certs via a global symbol (file) } @@ -53,7 +54,7 @@ private: { auto instance = static_cast(ctx); while (instance->perform() == ESP_OK) {} - vTaskDelete(nullptr); + esp_restart(); } esp_err_t start_server() { @@ -181,7 +182,7 @@ private: namespace server { -RpcInstance instance; +constinit RpcInstance instance; } RpcInstance *RpcEngine::init_server() diff --git a/components/esp_wifi_remote/examples/mqtt/CMakeLists.txt b/components/esp_wifi_remote/examples/mqtt/CMakeLists.txt index b07caaa52..500c42d77 100644 --- a/components/esp_wifi_remote/examples/mqtt/CMakeLists.txt +++ b/components/esp_wifi_remote/examples/mqtt/CMakeLists.txt @@ -1,23 +1,5 @@ # This project serves as a demo to enable using esp-mqtt on ESP platform targets as well as on linux cmake_minimum_required(VERSION 3.16) -if("${IDF_TARGET}" STREQUAL "linux") -# For linux-target we have two options: -# - With lwIP (must be defined on command line, e.g. idf.py -DWITH_LWIP=1) -# access networking from linux `tap` interface (TAP networking mode) -# - Without lwIP (must be defined on command line, e.g. idf.py -DWITH_LWIP=0) -# no designated interface, accesses user network via linux/socket sys calls - if(WITH_LWIP STREQUAL 1) - set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_tapif_io - "../../common_components/linux_compat/esp_timer") - set(COMPONENTS main esp_netif lwip protocol_examples_tapif_io startup esp_hw_support esp_system nvs_flash mqtt esp_timer) - else() - list(APPEND EXTRA_COMPONENT_DIRS - "../../common_components/linux_compat/esp_timer" - "$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs") - set(COMPONENTS main nvs_flash esp-tls esp_stubs mqtt protocol_examples_common esp_timer) - endif() -endif() - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(esp_mqtt_demo) diff --git a/components/esp_wifi_remote/examples/mqtt/README.md b/components/esp_wifi_remote/examples/mqtt/README.md index 3277edb00..0c81f4e21 100644 --- a/components/esp_wifi_remote/examples/mqtt/README.md +++ b/components/esp_wifi_remote/examples/mqtt/README.md @@ -4,40 +4,28 @@ This is a simple mqtt demo, that connects to WiFi AP first. This application has ## Overview -This is a simple example demonstrating connecting to an MQTT broker, subscribing and publishing some data. -This example uses IDF build system and could be configured to be build and executed: -* for any ESP32 family chip -* for linux target +When running this example on a target that doesn't natively support WiFi, please make sure that the remote target (slave application) is connected to your chipset via the configured transport interface. -## How to use example +Connection to the slave device also depends on RPC library used. It is recommended to use [`esp_hosted`](https://github.com/espressif/esp-hosted). Alternatively you can use [`eppp_link`](https://components.espressif.com/components/espressif/eppp_link). -### Hardware Required +Please note, that `esp_hosted` as a component is currently WIP, so the `wifi_remote` defaults to `eppp`, for now. -To run this example, you need any ESP32 development board or just PC/virtual machine/container running linux operating system. +## HW connection -### Host build modes +We currently support only `UART` transport, so the connection is very simple. You only need to connect Rx, Tx and GND with the remote target. +You need to configure these fields according to your connection: +* CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN +* CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN -Linux build is supported in these two modes: -* `WITH_LWIP=0`: Without lwIP component. The project uses linux BSD socket interface to interact with TCP/IP stack. There's no connection phase, we use the host network as users. This mode is often referred to as user-side networking. -* `WITH_LWIP=1`: Including lwIP component, which is added to the list of required components and compiled on host. In this mode, we have to map the host network (linux TCP/IP stack) to the target network (lwip). We use IDF's [`tapif_io`](https://github.com/espressif/esp-idf/tree/master/examples/common_components/protocol_examples_tapif_io) component to create a network interface, which will be used to pass packets to and from the simulated target. Please refer to the [README](https://github.com/espressif/esp-idf/tree/master/examples/common_components/protocol_examples_tapif_io#readme) for more details about the host side networking. +## SW configuration -### Building on linux +The RPC mechanism between the host and the slave micro uses TLS with mutual authentication, so you would have to configure certificates and keys for both parties. This application -- host target -- is considered RPC client, so it needs client's certificate and key, as well as the CA certificate to validate the server (slave application). +If self-signed certificates are acceptable, you can use [generate_test_certs](../test_certs/generate_test_certs.sh) script to generate both the CA and the keys itself and convert them to the PEM format that's accepted by the EPPP RPC engine. +You will have to configure these options: +* CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CA +* CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CRT +* CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_KEY -1) Configure linux target -```bash -idf.py --preview set-target linux -``` +## Setting up slave device -2) Build the project with preferred components (with or without lwip) -```bash -idf.py -DWITH_LWIP=0 build # Building without lwip (user networking) -idf.py -DWITH_LWIP=1 build # Building with lwip (TAP networking) -``` - -3) Run the project - -It is possible to run the project elf file directly, or using `idf.py` monitor target (no need to flash): -```bash -idf.py monitor -``` -idf.py -DWITH_LWIP=0 build # Building without lwip (user networking) +You need to set up the connection and configuration in a similar way on the slave part (connection pins + certificates and keys). Please refer to the [slave_application](../server/README.md) README for more information. diff --git a/components/esp_wifi_remote/examples/server/README.md b/components/esp_wifi_remote/examples/server/README.md index a8ff85f9f..f6e63d99b 100644 --- a/components/esp_wifi_remote/examples/server/README.md +++ b/components/esp_wifi_remote/examples/server/README.md @@ -1,7 +1,21 @@ +# WiFi remote EPPP RPC server -# Wi-Fi station to PPPoS server +This is a standalone application serving as the slave device for `esp_wifi_remote` users (with `eppp` RPC). -This example demonstrate using NAPT to bring connectivity from WiFi station to PPPoS server. +## Overview -This example expect a PPPoS client to connect to the server and use the connectivity. -The client could be a Linux computer with `pppd` service or another microcontroller with PPP client (or another ESP32 with not WiFi interface) +You need to configure and connect a slave device to the `esp_wifi_remote` host and run this application. Please fallow carefully these guidelines on HW connection and configuration of the slave device, based on the host device. + +## HW connection + +We currently support only `UART` transport you just need to connect Rx, Tx and GND and configure these fields accordingly: +* CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN +* CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN + +## SW configuration + +You will have to install server side certificates and keys, as well as the CA which should verify the client side. +Please configure these options: +* CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CA +* CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CRT +* CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_KEY diff --git a/components/esp_wifi_remote/idf_component.yml b/components/esp_wifi_remote/idf_component.yml index 9acde64a7..826097bc8 100644 --- a/components/esp_wifi_remote/idf_component.yml +++ b/components/esp_wifi_remote/idf_component.yml @@ -5,6 +5,6 @@ dependencies: espressif/eppp_link: version: '0.0.1' idf: - version: '5.3' + version: '>=5.3' # espressif/esp_hosted: # version: '*' diff --git a/components/esp_wifi_remote/test/smoke_test/main/idf_component.yml b/components/esp_wifi_remote/test/smoke_test/main/idf_component.yml index ecffade56..cb6183a90 100644 --- a/components/esp_wifi_remote/test/smoke_test/main/idf_component.yml +++ b/components/esp_wifi_remote/test/smoke_test/main/idf_component.yml @@ -2,7 +2,7 @@ dependencies: ## Required IDF version idf: - version: "5.3" + version: '>=5.3' espressif/esp_wifi_remote: version: "*" override_path: ../../.. From d16387859fdf96331467404993e9364d08a540fa Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 25 Apr 2024 15:13:49 +0200 Subject: [PATCH 4/4] bump(wifi_remote): 0.1.12 -> 0.2.0 0.2.0 Features - Add support for simple eppp based RPC (fd168d8) Bug Fixes - Make services restartable, code cleanup (6c82ce2) - Add examples to CI (d2b7c55) --- components/esp_wifi_remote/.cz.yaml | 2 +- components/esp_wifi_remote/CHANGELOG.md | 11 +++++++++++ components/esp_wifi_remote/idf_component.yml | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/components/esp_wifi_remote/.cz.yaml b/components/esp_wifi_remote/.cz.yaml index 8bc23f2aa..4cbf53c2b 100644 --- a/components/esp_wifi_remote/.cz.yaml +++ b/components/esp_wifi_remote/.cz.yaml @@ -3,6 +3,6 @@ commitizen: bump_message: 'bump(wifi_remote): $current_version -> $new_version' pre_bump_hooks: python ../../ci/changelog.py esp_wifi_remote tag_format: wifi_remote-v$version - version: 0.1.12 + version: 0.2.0 version_files: - idf_component.yml diff --git a/components/esp_wifi_remote/CHANGELOG.md b/components/esp_wifi_remote/CHANGELOG.md index 414e56c2e..2d49bd147 100644 --- a/components/esp_wifi_remote/CHANGELOG.md +++ b/components/esp_wifi_remote/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [0.2.0](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.2.0) + +### Features + +- Add support for simple eppp based RPC ([fd168d8](https://github.com/espressif/esp-protocols/commit/fd168d8)) + +### Bug Fixes + +- Make services restartable, code cleanup ([6c82ce2](https://github.com/espressif/esp-protocols/commit/6c82ce2)) +- Add examples to CI ([d2b7c55](https://github.com/espressif/esp-protocols/commit/d2b7c55)) + ## [0.1.12](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.1.12) ### Features diff --git a/components/esp_wifi_remote/idf_component.yml b/components/esp_wifi_remote/idf_component.yml index 826097bc8..8073e5b5e 100644 --- a/components/esp_wifi_remote/idf_component.yml +++ b/components/esp_wifi_remote/idf_component.yml @@ -1,4 +1,4 @@ -version: 0.1.12 +version: 0.2.0 url: https://github.com/espressif/esp-protocols/tree/master/components/esp_wifi_remote description: Utility wrapper for esp_wifi functionality on remote targets dependencies: