diff --git a/examples/common_components/protocol_examples_common/CMakeLists.txt b/examples/common_components/protocol_examples_common/CMakeLists.txt new file mode 100644 index 00000000..0ccb219b --- /dev/null +++ b/examples/common_components/protocol_examples_common/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "connect.c" "stdin_out.c" + INCLUDE_DIRS "include") diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild new file mode 100644 index 00000000..8a0b4ada --- /dev/null +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -0,0 +1,22 @@ +menu "Example Connection Configuration" + config EXAMPLE_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + + config EXAMPLE_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + Can be left blank if the network has no security set. + + config EXAMPLE_CONNECT_IPV6 + bool "Obtain IPv6 link-local address" + default n + select LWIP_IPV6 + help + By default, examples will wait until IPv4 and IPv6 addresses are obtained. + Disable this option if the network does not support IPv6. +endmenu diff --git a/examples/common_components/protocol_examples_common/component.mk b/examples/common_components/protocol_examples_common/component.mk new file mode 100644 index 00000000..e69de29b diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c new file mode 100644 index 00000000..5b6b2814 --- /dev/null +++ b/examples/common_components/protocol_examples_common/connect.c @@ -0,0 +1,142 @@ +/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection. + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + */ + +#include +#include "protocol_examples_common.h" +#include "sdkconfig.h" +#include "esp_event.h" +#include "esp_wifi.h" +#include "esp_log.h" +#include "esp_event_loop.h" +#include "tcpip_adapter.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "lwip/err.h" +#include "lwip/sys.h" + +#define GOT_IPV4_BIT BIT(0) +#define GOT_IPV6_BIT BIT(1) + +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 +#define CONNECTED_BITS (GOT_IPV4_BIT | GOT_IPV6_BIT) +#else +#define CONNECTED_BITS (GOT_IPV4_BIT) +#endif + +static EventGroupHandle_t s_connect_event_group; +static ip4_addr_t s_ip_addr; +static const char *s_connection_name; + +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 +static ip6_addr_t s_ipv6_addr; +#endif + +static const char *TAG = "example_connect"; + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + /* For accessing reason codes in case of disconnection */ + system_event_info_t *info = &event->event_info; + + switch (event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + memcpy(&s_ip_addr, &event->event_info.got_ip.ip_info.ip, sizeof(s_ip_addr)); + xEventGroupSetBits(s_connect_event_group, GOT_IPV4_BIT);; + break; +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + case SYSTEM_EVENT_STA_CONNECTED: + tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); + break; + case SYSTEM_EVENT_AP_STA_GOT_IP6: + memcpy(&s_ipv6_addr, &event->event_info.got_ip6.ip6_info, sizeof(s_ipv6_addr)); + xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); + break; +#endif + case SYSTEM_EVENT_STA_DISCONNECTED: + ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); + if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { + /*Switch to 802.11 bgn mode */ + esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); + } + esp_wifi_connect(); + xEventGroupClearBits(s_connect_event_group, GOT_IPV4_BIT); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + xEventGroupClearBits(s_connect_event_group, GOT_IPV6_BIT); +#endif + break; + default: + break; + } + return ESP_OK; +} + +static void start(void) +{ + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + wifi_config_t wifi_config = { + .sta = { + .ssid = CONFIG_EXAMPLE_WIFI_SSID, + .password = CONFIG_EXAMPLE_WIFI_PASSWORD, + }, + }; + ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + s_connection_name = CONFIG_EXAMPLE_WIFI_SSID; +} + +static void stop(void) +{ + esp_err_t err = esp_wifi_stop(); + if (err == ESP_ERR_WIFI_NOT_INIT) { + return; + } + ESP_ERROR_CHECK(err); + ESP_ERROR_CHECK(esp_wifi_deinit()); +} + +esp_err_t example_connect(void) +{ + if (s_connect_event_group != NULL) { + return ESP_ERR_INVALID_STATE; + } + + s_connect_event_group = xEventGroupCreate(); + start(); + xEventGroupWaitBits(s_connect_event_group, CONNECTED_BITS, true, true, portMAX_DELAY); + ESP_LOGI(TAG, "Connected to %s", s_connection_name); + ESP_LOGI(TAG, "IPv4 address: " IPSTR, IP2STR(&s_ip_addr)); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + ESP_LOGI(TAG, "IPv6 address: " IPV6STR, IPV62STR(s_ipv6_addr)); +#endif + return ESP_OK; +} + +esp_err_t example_disconnect(void) +{ + if (s_connect_event_group == NULL) { + return ESP_ERR_INVALID_STATE; + } + vEventGroupDelete(s_connect_event_group); + s_connect_event_group = NULL; + stop(); + ESP_LOGI(TAG, "Disconnected from %s", s_connection_name); + s_connection_name = NULL; + return ESP_OK; +} diff --git a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h new file mode 100644 index 00000000..222ab6c1 --- /dev/null +++ b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h @@ -0,0 +1,53 @@ +/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection. + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#include "tcpip_adapter.h" + +#define EXAMPLE_INTERFACE TCPIP_ADAPTER_IF_STA + +/** + * @brief Configure Wi-Fi or Ethernet, connect, wait for IP + * + * This all-in-one helper function is used in protocols examples to + * reduce the amount of boilerplate in the example. + * + * It is not intended to be used in real world applications. + * See examples under examples/wifi/getting_started/ and examples/ethernet/ + * for more complete Wi-Fi or Ethernet initialization code. + * + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + * + * @return ESP_OK on successful connection + */ +esp_err_t example_connect(void); + +/** + * Counterpart to example_connect, de-initializes Wi-Fi or Ethernet + */ +esp_err_t example_disconnect(void); + +/** + * @brief Configure stdin and stdout to use blocking I/O + * + * This helper function is used in ASIO examples. It wraps installing the + * UART driver and configuring VFS layer to use UART driver for console I/O. + */ +esp_err_t example_configure_stdin_stdout(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/common_components/protocol_examples_common/stdin_out.c b/examples/common_components/protocol_examples_common/stdin_out.c new file mode 100644 index 00000000..1c54026e --- /dev/null +++ b/examples/common_components/protocol_examples_common/stdin_out.c @@ -0,0 +1,32 @@ +/* Common functions for protocol examples, to configure stdin and stdout. + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + */ + +#include "protocol_examples_common.h" +#include "esp_err.h" +#include "esp_vfs_dev.h" +#include "driver/uart.h" +#include "sdkconfig.h" + +#ifdef CONFIG_USING_ESP_VFS +esp_err_t example_configure_stdin_stdout(void) +{ + // Initialize VFS & UART so we can use std::cout/cin + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + /* Install UART driver for interrupt-driven reads and writes */ + ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, + 256, 0, 0, NULL, 0) ); + /* Tell VFS to use UART driver */ + esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); + esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + return ESP_OK; +} +#endif