/* * cmd_ip.c * * Copyright (c) 2025 Umber Networks & Robert McMahon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "esp_console.h" #include "esp_netif.h" #include "esp_wifi.h" #include "argtable3/argtable3.h" #include "wifi_cfg.h" #include "app_console.h" // --- Arguments --- static struct { struct arg_str *ip; struct arg_str *mask; struct arg_str *gw; struct arg_end *end; } set_args; static struct { struct arg_str *mode; // "on" or "off" struct arg_end *end; } dhcp_args; static void print_if_info(esp_netif_t *netif, const char *name) { if (netif == NULL) return; esp_netif_ip_info_t ip_info; if (esp_netif_get_ip_info(netif, &ip_info) == ESP_OK) { printf("%s:\n", name); printf(" IP: " IPSTR "\n", IP2STR(&ip_info.ip)); printf(" Mask: " IPSTR "\n", IP2STR(&ip_info.netmask)); printf(" GW: " IPSTR "\n", IP2STR(&ip_info.gw)); esp_netif_dhcp_status_t status; esp_netif_dhcpc_get_status(netif, &status); printf(" DHCP: %s\n", (status == ESP_NETIF_DHCP_STARTED) ? "ON" : "OFF"); uint8_t mac[6] = {0}; if (esp_netif_get_mac(netif, mac) == ESP_OK) { printf(" MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } printf("\n"); } } static int do_ip_addr(void) { print_if_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), "Wi-Fi Station"); return 0; } static int do_ip_set(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&set_args); if (nerrors > 0) { arg_print_errors(stderr, set_args.end, argv[0]); return 1; } const char *ip = set_args.ip->sval[0]; const char *mask = set_args.mask->sval[0]; const char *gw = set_args.gw->sval[0]; // Validate and Convert (API Fix: esp_ip4addr_aton returns uint32_t) esp_netif_ip_info_t info = {0}; info.ip.addr = esp_ip4addr_aton(ip); info.netmask.addr = esp_ip4addr_aton(mask); info.gw.addr = esp_ip4addr_aton(gw); // Basic validation: 0 means conversion failed (or actual 0.0.0.0) if (info.ip.addr == 0 || info.netmask.addr == 0) { printf("Invalid IP format.\n"); return 1; } // Save wifi_cfg_set_ipv4(ip, mask, gw); wifi_cfg_set_dhcp(false); // Implicitly disable DHCP // Apply esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); if (netif) { esp_netif_dhcpc_stop(netif); esp_netif_set_ip_info(netif, &info); printf("Static IP set. DHCP disabled.\n"); } else { printf("Saved. Will apply on next init.\n"); } return 0; } static int do_ip_dhcp(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&dhcp_args); if (nerrors > 0) { arg_print_errors(stderr, dhcp_args.end, argv[0]); return 1; } bool enable = (strcmp(dhcp_args.mode->sval[0], "on") == 0); wifi_cfg_set_dhcp(enable); esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); if (netif) { if (enable) { esp_netif_dhcpc_start(netif); printf("DHCP enabled.\n"); } else { esp_netif_dhcpc_stop(netif); printf("DHCP disabled.\n"); } } return 0; } static void print_ip_usage(void) { printf("Usage: ip \n"); printf("Subcommands:\n"); printf(" addr Show config\n"); printf(" set Set static IP (Disables DHCP)\n"); printf(" dhcp Enable/Disable DHCP\n"); } static int cmd_ip(int argc, char **argv) { if (argc < 2) { print_ip_usage(); return 0; } if (strcmp(argv[1], "addr") == 0) return do_ip_addr(); if (strcmp(argv[1], "set") == 0) return do_ip_set(argc - 1, &argv[1]); if (strcmp(argv[1], "dhcp") == 0) return do_ip_dhcp(argc - 1, &argv[1]); print_ip_usage(); return 1; } void register_ip_cmd(void) { // Args set_args.ip = arg_str1(NULL, NULL, "", "IP Address"); set_args.mask = arg_str1(NULL, NULL, "", "Netmask"); set_args.gw = arg_str1(NULL, NULL, "", "Gateway"); set_args.end = arg_end(3); dhcp_args.mode = arg_str1(NULL, NULL, "", "Mode"); dhcp_args.end = arg_end(1); const esp_console_cmd_t cmd = { .command = "ip", .help = "IP Config: addr, set, dhcp", .hint = "", .func = &cmd_ip, }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); }