#include #include #include #include #include #include "console/cmd_common.h" #include #include #include #include #include #include static int cmd_ip_status(console_ctx_t *ctx, cmd_signature_t *reg) { EMPTY_CMD_SETUP("Show IP status"); if (!gSettings.wifi_enabled || !g_State.wifi_inited) { console_color_printf(COLOR_RED, "WiFi interface is disabled\n"); return 0; } wifi_config_t config; if (ESP_OK == esp_wifi_get_config(ESP_IF_WIFI_STA, &config)) { if (config.sta.ssid[0]) { EventBits_t bits = xEventGroupGetBits(g_wifi_event_group); if (bits & WIFI_CONNECTED_BIT) { console_color_printf(COLOR_GREEN, "Connected to SSID \"%s\"\n", config.sta.ssid); } else if (bits & WIFI_FAIL_BIT) { console_color_printf(COLOR_RED, "WiFi connection failed.\n"); console_printf("Saved SSID = \"%s\"\n", config.sta.ssid); return 0; } else { console_color_printf(COLOR_RED, "Not connected, retries may be in progress.\n"); console_printf("Saved SSID = \"%s\"\n", config.sta.ssid); return 0; } tcpip_adapter_ip_info_t ipinfo; if (ESP_OK == tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ipinfo)) { // ! inet_ntoa uses a global static buffer, cant use multiple in one printf call console_printf("DHCP: %s\n", gSettings.dhcp_enable ? MSG_ENABLED : MSG_DISABLED " (static IP)"); console_printf("IP: %s\n", inet_ntoa(ipinfo.ip.addr)); console_printf("Mask: %s\n", inet_ntoa(ipinfo.netmask.addr)); console_printf("Gateway: %s\n", inet_ntoa(ipinfo.gw.addr)); if (!gSettings.dhcp_enable) { console_printf("DNS: %s\n", inet_ntoa(gSettings.static_dns)); } uint8_t mac[6]; if (ESP_OK == esp_wifi_get_mac(ESP_IF_WIFI_STA, mac)) { console_printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } } else { console_color_printf(COLOR_RED, "No IP address assigned!\n"); } } else { console_color_printf(COLOR_RED, "SSID not configured!\n"); } } return 0; } static int cmd_ip_pingwd(console_ctx_t *ctx, cmd_signature_t *reg) { static struct { struct arg_str *cmd; struct arg_end *end; } cmd_args; if (reg) { cmd_args.cmd = arg_str0(NULL, NULL, "", "Enable or disable. Omit to check current state"); cmd_args.end = arg_end(1); reg->argtable = &cmd_args; reg->help = "Enable/disable ping watchdog, or check the current setting. The watchdog periodically pings the gateway and restarts WiFi on failure."; return 0; } if (cmd_args.cmd->count) { int b = parse_boolean_arg(cmd_args.cmd->sval[0]); if (b < 0) return CONSOLE_ERR_INVALID_ARG; gSettings.dhcp_wd_enable = b; settings_persist(SETTINGS_dhcp_wd_enable); } console_printf("Ping WD = %s\n", gSettings.dhcp_wd_enable ? MSG_ENABLED : MSG_DISABLED); if (cmd_args.cmd->count) { console_printf("Restart to apply changes\n"); } return 0; } static void ping_success_print_cb(int bytes, const char *ip, int seq, int elapsed_ms) { console_printf("Rx %d bytes from %s: icmp_seq=%d time=%d ms\n", bytes, ip, seq, (int) elapsed_ms); } static void ping_fail_print_cb(int seq) { console_printf("Request timeout for icmp_seq %d\n", seq); } static int cmd_ip_ping(console_ctx_t *ctx, cmd_signature_t *reg) { static struct { struct arg_str *ip; struct arg_int *num; struct arg_int *timeout; struct arg_int *interval; struct arg_int *size; struct arg_end *end; } args; if (reg) { args.ip = arg_str1(NULL, NULL, "", "Target IP"); args.num = arg_int0("n", NULL, "", "Ping count (def 1)"); args.timeout = arg_int0("t", NULL, "", "Timeout (def 3000)"); args.interval = arg_int0("i", NULL, "", "Interval (def 1000)"); args.size = arg_int0("s", NULL, "", "Payload size (def 32)"); args.end = arg_end(5); reg->argtable = &args; reg->help = "Ping a host using ICMP"; return 0; } ping_opts_t opts = PING_CONFIG_DEFAULT(); opts.success_cb = ping_success_print_cb; opts.fail_cb = ping_fail_print_cb; opts.count = args.num->count ? args.num->ival[0] : 1; opts.payload_size = args.size->count ? args.size->ival[0] : 32; opts.interval_ms = args.interval->count ? args.interval->ival[0] : 1000; opts.timeout_ms = args.timeout->count ? args.timeout->ival[0] : 3000; if (0 == inet_aton(args.ip->sval[0], &opts.ip_addr)) { // we could have received a domain name here struct hostent * ent = gethostbyname(args.ip->sval[0]); if (!ent) { console_println("Could not resolve"); return CONSOLE_ERR_IO; } memcpy(&opts.ip_addr, ent->h_addr_list[0], sizeof(ip4_addr_t)); console_printf("Resolved as %s\n", inet_ntoa(opts.ip_addr)); } ping_result_t result = {}; esp_err_t ret = ping(&opts, &result); if (ret != ESP_OK) { console_println("Ping error"); return ret; } else { console_printf("%d tx, %d rx, %.1f%% loss, latency min %d ms, max %d ms\n", result.sent, result.received, result.loss_pt, result.min_time_ms, result.max_time_ms); } return 0; } static int cmd_ip_static_set(console_ctx_t *ctx, cmd_signature_t *reg) { static struct { struct arg_str *ip; struct arg_str *gw; struct arg_str *mask; struct arg_str *dns; struct arg_str *cmd; struct arg_end *end; } args; if (reg) { args.ip = arg_str0("a", NULL, "", "Set IP address"); args.gw = arg_str0("g", NULL, "", "Set gateway address"); args.mask = arg_str0("n", NULL, "", "Set netmask"); args.dns = arg_str0("d", NULL, "", "Set DNS server IP"); args.cmd = arg_str0(NULL, NULL, "{enable|disable}", "Enable or disable static IP"); args.end = arg_end(1); reg->argtable = &args; reg->help = "Configure, enable/disable, or check config of static IP."; return 0; } bool any_change = false; if (args.ip->count) { uint32_t a = 0; if (!inet_aton(args.ip->sval[0], &a)) { console_println("Invalid IP"); return CONSOLE_ERR_INVALID_ARG; } gSettings.static_ip = a; // aton output is already in network byte order settings_persist(SETTINGS_static_ip); any_change = true; } if (args.gw->count) { uint32_t a = 0; if (!inet_aton(args.gw->sval[0], &a)) { console_println("Invalid GW"); return CONSOLE_ERR_INVALID_ARG; } gSettings.static_ip_gw = a; // aton output is already in network byte order settings_persist(SETTINGS_static_ip_gw); any_change = true; } if (args.mask->count) { uint32_t a = 0; if (!inet_aton(args.mask->sval[0], &a)) { console_println("Invalid mask"); return CONSOLE_ERR_INVALID_ARG; } gSettings.static_ip_mask = a; // aton output is already in network byte order settings_persist(SETTINGS_static_ip_mask); any_change = true; } if (args.dns->count) { uint32_t a = 0; if (!inet_aton(args.dns->sval[0], &a)) { console_println("Invalid DNS IP"); return CONSOLE_ERR_INVALID_ARG; } gSettings.static_dns = a; // aton output is already in network byte order settings_persist(SETTINGS_static_dns); any_change = true; } if (args.cmd->count) { int b = parse_boolean_arg(args.cmd->sval[0]); if (b < 0) return CONSOLE_ERR_INVALID_ARG; gSettings.dhcp_enable = !b; settings_persist(SETTINGS_dhcp_enable); any_change = true; } console_printf("Static IP: %s\n", gSettings.dhcp_enable ? MSG_DISABLED : MSG_ENABLED); console_printf("- IP: %s\n", inet_ntoa(gSettings.static_ip)); console_printf("- Mask: %s\n", inet_ntoa(gSettings.static_ip_mask)); console_printf("- Gateway: %s\n", inet_ntoa(gSettings.static_ip_gw)); console_printf("- DNS: %s\n", inet_ntoa(gSettings.static_dns)); if (any_change) { console_println("Restart to apply changes."); } return 0; } static int cmd_ip_ntp(console_ctx_t *ctx, cmd_signature_t *reg) { static struct { struct arg_str *cmd; struct arg_str *addr; struct arg_end *end; } cmd_args; if (reg) { cmd_args.cmd = arg_str0(NULL, NULL, "", "Enable or disable autostart. Omit to check current state. start = start now"); cmd_args.addr = arg_str0("s", NULL, "", "Set NTP server"); cmd_args.end = arg_end(2); reg->argtable = &cmd_args; reg->help = "Check or modify NTP client setting, or start it manually."; return 0; } if (cmd_args.addr->count) { strncpy(gSettings.ntp_srv, cmd_args.addr->sval[0], NTP_SRV_LEN); gSettings.ntp_srv[NTP_SRV_LEN - 1] = 0; settings_persist(SETTINGS_ntp_srv); console_printf("NTP server set to %s\n", gSettings.ntp_srv); } if (cmd_args.cmd->count) { if (streq(cmd_args.cmd->sval[0], "start")) { bool started = sntp_cli_start(); if (started) { console_printf("NTP client started manually.\n"); } else { console_color_printf(COLOR_RED, "Start failed. Client may be already running.\n"); } return 0; } int b = parse_boolean_arg(cmd_args.cmd->sval[0]); if (b < 0) return CONSOLE_ERR_INVALID_ARG; gSettings.ntp_enable = b; settings_persist(SETTINGS_ntp_enable); } console_printf("Client status: %s\n", gSettings.ntp_enable ? MSG_ENABLED : MSG_DISABLED); console_printf("NTP server: %s\n", gSettings.ntp_srv); /* show the current date */ time_t now; struct tm timeinfo; time(&now); localtime_r(&now, &timeinfo); if(timeinfo.tm_year < (2016 - 1900)) { console_printf("Device time is not valid.\n"); } else { char strftime_buf[64]; strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); console_printf("The current UTC date/time is: %s\n", strftime_buf); } if (cmd_args.cmd->count) { // if it was "start", we returned early. console_printf("Restart to apply changes\n"); } return 0; } void register_cmd_ip(void) { console_group_add("ip", "IP status and settings"); console_cmd_register(cmd_ip_status, "ip status"); console_cmd_register(cmd_ip_pingwd, "ip wd"); console_cmd_register(cmd_ip_ntp, "ip ntp"); console_cmd_register(cmd_ip_ping, "ip ping"); console_cmd_register(cmd_ip_static_set, "ip static"); // this may be used for shortcuts like "ip in" console_cmd_add_alias_fn(cmd_ip_status, "ip info"); }