diff --git a/Client/CMakeLists.txt b/Client/CMakeLists.txt new file mode 100644 index 0000000..9b588fa --- /dev/null +++ b/Client/CMakeLists.txt @@ -0,0 +1,7 @@ +# 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) +idf_build_set_property(MINIMAL_BUILD ON) +project(Client) diff --git a/Client/dependencies.lock b/Client/dependencies.lock new file mode 100644 index 0000000..a8d3e86 --- /dev/null +++ b/Client/dependencies.lock @@ -0,0 +1,133 @@ +dependencies: + espressif/ethernet_init: + component_hash: 9f7d29acf5fe32315579ddb6247388291cda555aa529409108c0ada0aa7cd99d + dependencies: + - matches: + - if: $CONFIG{ETHERNET_SPI_USE_CH390} == 1 + name: espressif/ch390 + registry_url: https://components.espressif.com + require: private + version: '*' + - matches: + - if: $CONFIG{ETHERNET_SPI_USE_DM9051} == 1 + name: espressif/dm9051 + registry_url: https://components.espressif.com + require: private + rules: + - if: idf_version >=6.0 + version: ^1.0.0 + version: '*' + - matches: + - if: idf_version >=6.0 + version: ^1.0.0 + name: espressif/dp83848 + registry_url: https://components.espressif.com + require: private + rules: + - if: target in [esp32, esp32p4] + - if: $CONFIG{ETHERNET_PHY_USE_DP83848} == 1 + version: '*' + - matches: + - if: $CONFIG{ETHERNET_SPI_USE_ENC28J60} == 1 + name: espressif/enc28j60 + registry_url: https://components.espressif.com + require: private + version: '*' + - matches: + - if: idf_version >=6.0 + version: ^1.0.0 + name: espressif/ip101 + registry_url: https://components.espressif.com + require: private + rules: + - if: target in [esp32, esp32p4] + - if: $CONFIG{ETHERNET_PHY_USE_IP101} == 1 + version: '*' + - matches: + - if: idf_version >=6.0 + version: ^1.0.0 + name: espressif/ksz80xx + registry_url: https://components.espressif.com + require: private + rules: + - if: target in [esp32, esp32p4] + - if: $CONFIG{ETHERNET_PHY_USE_KSZ80XX} == 1 + version: '*' + - matches: + - if: $CONFIG{ETHERNET_SPI_USE_KSZ8851SNL} == 1 + name: espressif/ksz8851snl + registry_url: https://components.espressif.com + require: private + rules: + - if: idf_version >=6.0 + version: ^1.0.0 + version: '*' + - matches: + - if: $CONFIG{ETHERNET_SPI_USE_LAN865X} == 1 + name: espressif/lan865x + registry_url: https://components.espressif.com + require: private + version: ^0.1.1 + - name: espressif/lan867x + registry_url: https://components.espressif.com + require: private + rules: + - if: target in [esp32, esp32p4] + - if: $CONFIG{ETHERNET_PHY_USE_LAN867X} == 1 + version: '>=2.0.0' + - matches: + - if: idf_version >=6.0 + version: ^1.0.0 + name: espressif/lan87xx + registry_url: https://components.espressif.com + require: private + rules: + - if: target in [esp32, esp32p4] + - if: $CONFIG{ETHERNET_PHY_USE_LAN87XX} == 1 + version: '*' + - matches: + - if: idf_version >=6.0 + version: ^1.0.0 + name: espressif/rtl8201 + registry_url: https://components.espressif.com + require: private + rules: + - if: target in [esp32, esp32p4] + - if: $CONFIG{ETHERNET_PHY_USE_RTL8201} == 1 + version: '*' + - matches: + - if: $CONFIG{ETHERNET_SPI_USE_W5500} == 1 + name: espressif/w5500 + registry_url: https://components.espressif.com + require: private + rules: + - if: idf_version >=6.0 + version: ^1.0.0 + version: '*' + - name: idf + require: private + version: '>=5.4.3,!=5.5.0,!=5.5.1' + source: + registry_url: https://components.espressif.com/ + type: service + version: 1.3.0 + idf: + source: + type: idf + version: 5.5.3 + network: + dependencies: + - name: idf + version: '>=4.1.0' + - name: espressif/ethernet_init + version: ^1.3.0 + source: + path: C:\Dev\Classified\Calendink\components\network + type: local + version: 1.0.0 +direct_dependencies: +- idf +- network +manifest_hash: 12f55da0a0684644c57ee6a400e8e98810d36140fad54f35a96e434eb9774b8c +target: esp32 +version: 2.0.0 diff --git a/Client/main/CMakeLists.txt b/Client/main/CMakeLists.txt new file mode 100644 index 0000000..f13668e --- /dev/null +++ b/Client/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "main.cpp" + PRIV_REQUIRES esp_eth esp_wifi esp_netif driver network nvs_flash + INCLUDE_DIRS ".") diff --git a/Client/main/idf_component.yml b/Client/main/idf_component.yml new file mode 100644 index 0000000..d1a398e --- /dev/null +++ b/Client/main/idf_component.yml @@ -0,0 +1,6 @@ +## IDF Component Manager Manifest File +dependencies: + idf: + version: '>=4.1.0' + network: + path: "../../components/network" diff --git a/Client/main/main.cpp b/Client/main/main.cpp new file mode 100644 index 0000000..e590fa9 --- /dev/null +++ b/Client/main/main.cpp @@ -0,0 +1,54 @@ +#include +#include "esp_log.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "nvs_flash.h" +#include "network.hpp" + +static const char *TAG = "ClientMain"; + +extern "C" void app_main() +{ + ESP_LOGI(TAG, "Hello, Calendink Client!"); + + // Initialize NVS (required for some Wi-Fi configurations and network features) + 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_event_loop_create_default()); + + // Connect to WiFi + ESP_LOGI(TAG, "Initializing WiFi connection"); + + // Attempting to connect, we don't necessarily need to block forever here + // as network.cpp already handles some of the retries + esp_err_t err = connect_wifi(CONFIG_CALENDINK_WIFI_SSID, CONFIG_CALENDINK_WIFI_PASSWORD, false); + + if (err == ESP_OK) { + uint8_t retries = 1; + do { + err = check_wifi_connection(retries); + if (err != ESP_OK) { + ESP_LOGW(TAG, "WiFi connection check timeout, retrying... (%d)", retries); + vTaskDelay(pdMS_TO_TICKS(1000)); + } + retries++; + } while (err == ESP_ERR_TIMEOUT && retries <= CONFIG_CALENDINK_WIFI_RETRIES); + } + + if (err == ESP_OK) { + ESP_LOGI(TAG, "Successfully connected to WiFi!"); + } else { + ESP_LOGE(TAG, "Failed to connect to WiFi."); + } + + while (true) + { + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} diff --git a/Provider/dependencies.lock b/Provider/dependencies.lock index d8ce71e..cb35a78 100644 --- a/Provider/dependencies.lock +++ b/Provider/dependencies.lock @@ -152,6 +152,16 @@ dependencies: registry_url: https://components.espressif.com/ type: service version: 9.4.0 + network: + dependencies: + - name: idf + version: '>=4.1.0' + - name: espressif/ethernet_init + version: ^1.3.0 + source: + path: C:\Dev\Classified\Calendink\components\network + type: local + version: 1.0.0 direct_dependencies: - espressif/ethernet_init - espressif/led_strip @@ -159,6 +169,7 @@ direct_dependencies: - idf - joltwallet/littlefs - lvgl/lvgl -manifest_hash: 0c7ea64d32655d6be4f726b7946e96626bce0de88c2dc8f091bb5e365d26a374 +- network +manifest_hash: adc42d97d037e4815c3e1d03227cf1a5b29b8a914aa24fefa5760edd541a6bac target: esp32s3 version: 2.0.0 diff --git a/Provider/main/CMakeLists.txt b/Provider/main/CMakeLists.txt index 4387faf..3b2cd99 100644 --- a/Provider/main/CMakeLists.txt +++ b/Provider/main/CMakeLists.txt @@ -1,8 +1,7 @@ idf_component_register(SRCS "main.cpp" - # Needed as we use minimal build PRIV_REQUIRES esp_http_server esp_eth esp_wifi nvs_flash esp_netif vfs - json app_update esp_timer esp_psram mdns driver + json app_update esp_timer esp_psram mdns driver network INCLUDE_DIRS ".") if(CONFIG_CALENDINK_DEPLOY_WEB_PAGES) diff --git a/Provider/main/Kconfig.projbuild b/Provider/main/Kconfig.projbuild index fc625f8..0df0767 100644 --- a/Provider/main/Kconfig.projbuild +++ b/Provider/main/Kconfig.projbuild @@ -1,76 +1,3 @@ -menu "CalendarInk Network Configuration" - - config CALENDINK_WIFI_SSID - string "WiFi SSID" - default "" - help - SSID (network name) for the WiFi connection. - - config CALENDINK_WIFI_PASSWORD - string "WiFi Password" - default "" - help - Password for the WiFi connection. - - config CALENDINK_ETH_RETRIES - int "Maximum Ethernet Connection Retries" - default 5 - help - Number of times to retry the Ethernet connection before falling back to WiFi. - - config CALENDINK_WIFI_RETRIES - int "Maximum WiFi Connection Retries" - default 5 - help - Number of times to retry the WiFi connection before failing completely. - - config CALENDINK_BLINK_IP - bool "Blink last IP digit on connect" - default n - help - If enabled, the LED will blink the last digit of the IP address - acquired to assist in debugging. - - config CALENDINK_MDNS_HOSTNAME - string "mDNS Hostname" - default "calendink" - help - The hostname to use for mDNS. The device will be accessible - at .local. (e.g., calendink.local) - - config CALENDINK_UDP_LOG_TARGET_IP - string "UDP Logger Target IP Address" - default "" - help - The IP address to send UDP logs to via port 514. - If left blank, logs will be broadcast to 255.255.255.255. - - choice CALENDINK_WIFI_PS_MODE - prompt "WiFi Power Save Mode" - default CALENDINK_WIFI_PS_NONE - help - Select the WiFi power save mode to balance power consumption and network stability. - - config CALENDINK_WIFI_PS_NONE - bool "None (No power save, highest consumption)" - - config CALENDINK_WIFI_PS_MIN_MODEM - bool "Minimum Modem (Wakes on beacon, balanced)" - - config CALENDINK_WIFI_PS_MAX_MODEM - bool "Maximum Modem (Lowest consumption, may drop connection on strict routers)" - endchoice - - config CALENDINK_ALLOW_LIGHT_SLEEP - bool "Allow Light Sleep (Tickless Idle)" - default n - help - If enabled, the device will heavily use light sleep to reduce power - consumption. Note that this may BREAK the UART console monitor since the - CPU sleeps and halts the UART! Use UDP logging if you need logs - while light sleep is enabled. - -endmenu menu "Calendink Web Server" diff --git a/Provider/main/idf_component.yml b/Provider/main/idf_component.yml index 8943f88..b841858 100644 --- a/Provider/main/idf_component.yml +++ b/Provider/main/idf_component.yml @@ -19,3 +19,5 @@ dependencies: espressif/ethernet_init: ^1.3.0 joltwallet/littlefs: "^1.20" # https://github.com/joltwallet/esp_littlefs lvgl/lvgl: "9.4.0" + network: + path: "../../components/network" diff --git a/Provider/main/main.cpp b/Provider/main/main.cpp index 7a94db7..abd4564 100644 --- a/Provider/main/main.cpp +++ b/Provider/main/main.cpp @@ -16,13 +16,12 @@ #include "soc/gpio_num.h" // Project headers -#include "appstate.hpp" #include "types.hpp" +#include "network.hpp" // Project cpp (Unity Build entry) // clang-format off #include "led_status.cpp" -#include "connect.cpp" #include "http_server.cpp" #include "mdns_service.cpp" #include "udp_logger.cpp" diff --git a/components/network/CMakeLists.txt b/components/network/CMakeLists.txt new file mode 100644 index 0000000..1f3ef90 --- /dev/null +++ b/components/network/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "network.cpp" + INCLUDE_DIRS "include" + PRIV_REQUIRES esp_eth esp_wifi esp_netif driver) diff --git a/components/network/Kconfig.projbuild b/components/network/Kconfig.projbuild new file mode 100644 index 0000000..aacd5d5 --- /dev/null +++ b/components/network/Kconfig.projbuild @@ -0,0 +1,73 @@ +menu "CalendarInk Network Configuration" + + config CALENDINK_WIFI_SSID + string "WiFi SSID" + default "" + help + SSID (network name) for the WiFi connection. + + config CALENDINK_WIFI_PASSWORD + string "WiFi Password" + default "" + help + Password for the WiFi connection. + + config CALENDINK_ETH_RETRIES + int "Maximum Ethernet Connection Retries" + default 5 + help + Number of times to retry the Ethernet connection before falling back to WiFi. + + config CALENDINK_WIFI_RETRIES + int "Maximum WiFi Connection Retries" + default 5 + help + Number of times to retry the WiFi connection before failing completely. + + config CALENDINK_BLINK_IP + bool "Blink last IP digit on connect" + default n + help + If enabled, the LED will blink the last digit of the IP address + acquired to assist in debugging. + + config CALENDINK_MDNS_HOSTNAME + string "mDNS Hostname" + default "calendink" + help + The hostname to use for mDNS. The device will be accessible + at .local. (e.g., calendink.local) + + config CALENDINK_UDP_LOG_TARGET_IP + string "UDP Logger Target IP Address" + default "" + help + The IP address to send UDP logs to via port 514. + If left blank, logs will be broadcast to 255.255.255.255. + + choice CALENDINK_WIFI_PS_MODE + prompt "WiFi Power Save Mode" + default CALENDINK_WIFI_PS_NONE + help + Select the WiFi power save mode to balance power consumption and network stability. + + config CALENDINK_WIFI_PS_NONE + bool "None (No power save, highest consumption)" + + config CALENDINK_WIFI_PS_MIN_MODEM + bool "Minimum Modem (Wakes on beacon, balanced)" + + config CALENDINK_WIFI_PS_MAX_MODEM + bool "Maximum Modem (Lowest consumption, may drop connection on strict routers)" + endchoice + + config CALENDINK_ALLOW_LIGHT_SLEEP + bool "Allow Light Sleep (Tickless Idle)" + default n + help + If enabled, the device will heavily use light sleep to reduce power + consumption. Note that this may BREAK the UART console monitor since the + CPU sleeps and halts the UART! Use UDP logging if you need logs + while light sleep is enabled. + +endmenu diff --git a/components/network/idf_component.yml b/components/network/idf_component.yml new file mode 100644 index 0000000..8b1121c --- /dev/null +++ b/components/network/idf_component.yml @@ -0,0 +1,7 @@ +version: "1.0.0" +description: "CalendarInk Shared Network Component" + +dependencies: + idf: + version: '>=4.1.0' + espressif/ethernet_init: ^1.3.0 diff --git a/components/network/include/network.hpp b/components/network/include/network.hpp new file mode 100644 index 0000000..dd95aee --- /dev/null +++ b/components/network/include/network.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "esp_err.h" +#include + +esp_err_t connect_ethernet(bool blockUntilIPAcquired); +void disconnect_ethernet(); +esp_err_t check_ethernet_connection(uint32_t timeoutSeconds); + +esp_err_t connect_wifi(const char *ssid, const char *password, bool blockUntilIPAcquired); +void disconnect_wifi(); +esp_err_t check_wifi_connection(uint32_t timeoutSeconds); diff --git a/Provider/main/connect.cpp b/components/network/network.cpp similarity index 97% rename from Provider/main/connect.cpp rename to components/network/network.cpp index 9f631dc..eab39ab 100644 --- a/Provider/main/connect.cpp +++ b/components/network/network.cpp @@ -17,7 +17,11 @@ #include "freertos/timers.h" // Project includes -#include "types.hpp" +#include "network.hpp" + +#ifndef internal +#define internal static +#endif // Forward declarations #if CONFIG_CALENDINK_BLINK_IP @@ -116,7 +120,7 @@ void teardown_ethernet() esp_netif_deinit(); } -internal esp_err_t connect_ethernet(bool blockUntilIPAcquired) +esp_err_t connect_ethernet(bool blockUntilIPAcquired) { #ifndef NDEBUG assert(!s_ethernet_connected && @@ -185,7 +189,7 @@ void disconnect_ethernet() ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&teardown_ethernet)); } -internal esp_err_t check_ethernet_connection(uint32_t timeoutSeconds) +esp_err_t check_ethernet_connection(uint32_t timeoutSeconds) { // Wait up to 5000ms for the physical link to negotiate if (!s_eth_link_up) @@ -302,7 +306,7 @@ void teardown_wifi() } } -internal esp_err_t connect_wifi(const char *ssid, const char *password, +esp_err_t connect_wifi(const char *ssid, const char *password, bool blockUntilIPAcquired) { #ifndef NDEBUG @@ -379,7 +383,7 @@ void disconnect_wifi() ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&teardown_wifi)); } -internal esp_err_t check_wifi_connection(uint32_t timeoutSeconds) +esp_err_t check_wifi_connection(uint32_t timeoutSeconds) { // Wait up to 10000ms for the physical link to associate with the AP if (!s_wifi_link_up)