mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-23 15:27:28 +02:00
esp_modem: Refactor the modem to a standalone managed component
This commit is contained in:
8
esp_modem/examples/modem_console/CMakeLists.txt
Normal file
8
esp_modem/examples/modem_console/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
# The following 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.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(modem-console)
|
11
esp_modem/examples/modem_console/Makefile
Normal file
11
esp_modem/examples/modem_console/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := modem-console
|
||||
|
||||
EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
10
esp_modem/examples/modem_console/README.md
Normal file
10
esp_modem/examples/modem_console/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# PPPoS simple client example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## Overview
|
||||
This example is mainly targets experimenting with a modem device, sending custom commands and switching to PPP mode using esp-console, command line API.
|
||||
|
||||
## How to use this example
|
||||
|
||||
See the README.md file in the upper level `pppos` directory for more information about the PPPoS examples.
|
4
esp_modem/examples/modem_console/main/CMakeLists.txt
Normal file
4
esp_modem/examples/modem_console/main/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "modem_console_main.c"
|
||||
"httpget_handle.c"
|
||||
"ping_handle.c"
|
||||
INCLUDE_DIRS ".")
|
4
esp_modem/examples/modem_console/main/component.mk
Normal file
4
esp_modem/examples/modem_console/main/component.mk
Normal file
@ -0,0 +1,4 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
108
esp_modem/examples/modem_console/main/httpget_handle.c
Normal file
108
esp_modem/examples/modem_console/main/httpget_handle.c
Normal file
@ -0,0 +1,108 @@
|
||||
/* Modem console example
|
||||
|
||||
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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_http_client.h"
|
||||
|
||||
static const char *TAG = "modem_console_httpget";
|
||||
|
||||
static esp_err_t http_event_handler(esp_http_client_event_t *evt)
|
||||
{
|
||||
switch(evt->event_id) {
|
||||
case HTTP_EVENT_ERROR:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
|
||||
break;
|
||||
case HTTP_EVENT_ON_CONNECTED:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
|
||||
break;
|
||||
case HTTP_EVENT_HEADER_SENT:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
|
||||
break;
|
||||
case HTTP_EVENT_ON_HEADER:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
|
||||
break;
|
||||
case HTTP_EVENT_ON_DATA:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
|
||||
if ((bool)evt->user_data &&
|
||||
!esp_http_client_is_chunked_response(evt->client)) {
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, evt->data, evt->data_len, ESP_LOG_INFO);
|
||||
}
|
||||
|
||||
break;
|
||||
case HTTP_EVENT_ON_FINISH:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
|
||||
break;
|
||||
case HTTP_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_str *host;
|
||||
struct arg_lit *hex;
|
||||
struct arg_end *end;
|
||||
} http_args;
|
||||
|
||||
static int do_http_client(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&http_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, http_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
esp_http_client_config_t config = {
|
||||
.event_handler = http_event_handler,
|
||||
};
|
||||
|
||||
if (http_args.host->count > 0) {
|
||||
config.url = http_args.host->sval[0];
|
||||
} else {
|
||||
config.url = "http://httpbin.org/get";
|
||||
}
|
||||
|
||||
if (http_args.hex->count > 0) {
|
||||
// show hex data from http-get
|
||||
config.user_data = (void*)true;
|
||||
}
|
||||
|
||||
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||
|
||||
esp_err_t err = esp_http_client_perform(client);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
|
||||
esp_http_client_get_status_code(client),
|
||||
esp_http_client_get_content_length(client));
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void modem_console_register_http(void)
|
||||
{
|
||||
http_args.host = arg_str0(NULL, NULL, "<host>", "address or host-name to send GET request (defaults to http://httpbin.org/get)");
|
||||
http_args.hex = arg_litn("p", "print-hex", 0, 1, "print hex output"),
|
||||
http_args.end = arg_end(1);
|
||||
const esp_console_cmd_t http_cmd = {
|
||||
.command = "httpget",
|
||||
.help = "http get command to test data mode",
|
||||
.hint = NULL,
|
||||
.func = &do_http_client,
|
||||
.argtable = &http_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&http_cmd));
|
||||
}
|
307
esp_modem/examples/modem_console/main/modem_console_main.c
Normal file
307
esp_modem/examples/modem_console/main/modem_console_main.c
Normal file
@ -0,0 +1,307 @@
|
||||
/* Modem console example
|
||||
|
||||
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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <esp_modem_dce_common_commands.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_event.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_modem.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
// utilities to check network connectivity
|
||||
void modem_console_register_http(void);
|
||||
void modem_console_register_ping(void);
|
||||
|
||||
static esp_modem_dce_t *s_dce = NULL;
|
||||
static const char *TAG = "modem_console";
|
||||
|
||||
static struct {
|
||||
struct arg_str *command;
|
||||
struct arg_int *param_int;
|
||||
struct arg_str *param_str;
|
||||
struct arg_str *param_pdp;
|
||||
struct arg_str *param_bool;
|
||||
struct arg_str *param;
|
||||
struct arg_str *result;
|
||||
struct arg_end *end;
|
||||
} at_args;
|
||||
|
||||
static struct {
|
||||
struct arg_str *param;
|
||||
struct arg_end *end;
|
||||
} modem_args;
|
||||
|
||||
|
||||
|
||||
static struct {
|
||||
struct arg_str *command;
|
||||
struct arg_int *timeout;
|
||||
struct arg_str *pattern;
|
||||
struct arg_lit *no_cr;
|
||||
struct arg_end *end;
|
||||
} generic_at_args;
|
||||
|
||||
static char s_common_in_str[100]; // used as common string input param holder
|
||||
static char s_common_out_str[100]; // used as output string/command result holder
|
||||
|
||||
static esp_err_t handle_line_pattern(esp_modem_dce_t *dce, const char *line)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
ESP_LOGI(TAG, "handle_line_pattern: DCE response: %s\n", line);
|
||||
if (strstr(line, dce->handle_line_ctx)) {
|
||||
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int do_dce(int argc, char **argv)
|
||||
{
|
||||
// specific DCE generic command params
|
||||
static bool bool_result;
|
||||
static char pdp_type[10];
|
||||
static char pdp_apn[10];
|
||||
static esp_modem_dce_pdp_ctx_t pdp = { .type = pdp_type, .apn = pdp_apn };
|
||||
static esp_modem_dce_csq_ctx_t csq;
|
||||
static esp_modem_dce_cbc_ctx_t cbc;
|
||||
|
||||
int nerrors = arg_parse(argc, argv, (void **) &at_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, at_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
void * command_param = NULL;
|
||||
void * command_result = NULL;
|
||||
|
||||
// parse input params
|
||||
if (at_args.param_int->count > 0) {
|
||||
command_param = (void*)(at_args.param_int->ival[0]);
|
||||
} else if (at_args.param_bool->count > 0) {
|
||||
const char * bool_in_str = at_args.param_bool->sval[0];
|
||||
s_common_out_str[0] = '\0';
|
||||
command_result = s_common_out_str;
|
||||
if (strstr(bool_in_str,"true") || strstr(bool_in_str,"1")) {
|
||||
command_param = (void*)true;
|
||||
} else {
|
||||
command_param = (void*)false;
|
||||
}
|
||||
} else if (at_args.param_pdp->count > 0) {
|
||||
// parse out three comma separated sub-arguments
|
||||
sscanf(at_args.param_pdp->sval[0], "%d,%s", &pdp.cid, pdp_type);
|
||||
char *str_apn = strchr(pdp_type, ',');
|
||||
if (str_apn) {
|
||||
strncpy(pdp_apn, str_apn + 1, sizeof(pdp_apn));
|
||||
str_apn[0] = '\0';
|
||||
}
|
||||
command_param = &pdp;
|
||||
} else if (at_args.param_str->count > 0) {
|
||||
strncpy(s_common_in_str, at_args.param_str->sval[0], sizeof(s_common_in_str));
|
||||
command_param = s_common_in_str;
|
||||
} else if (at_args.param->count > 0) { // default param is treated as string
|
||||
strncpy(s_common_in_str, at_args.param->sval[0], sizeof(s_common_in_str));
|
||||
command_param = s_common_in_str;
|
||||
}
|
||||
|
||||
// parse output params
|
||||
if (at_args.result->count > 0) {
|
||||
const char *res = at_args.result->sval[0];
|
||||
if (strstr(res, "csq")) {
|
||||
command_result = &csq;
|
||||
}else if (strstr(res, "cbc")) {
|
||||
command_result = &cbc;
|
||||
} else if (strstr(res, "str")) {
|
||||
command_param = (void*)sizeof(s_common_out_str);
|
||||
command_result = s_common_out_str;
|
||||
} else if (strstr(res, "bool")) {
|
||||
command_result = &bool_result;
|
||||
} else {
|
||||
command_param = (void*)sizeof(s_common_out_str);
|
||||
command_result = s_common_out_str;
|
||||
}
|
||||
}
|
||||
|
||||
// by default (if no param/result provided) expect string output
|
||||
if (command_param == NULL && command_result == NULL) {
|
||||
s_common_out_str[0] = '\0';
|
||||
command_param = (void*)sizeof(s_common_out_str);
|
||||
command_result = s_common_out_str;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_modem_command_list_run(s_dce, at_args.command->sval[0], command_param, command_result);
|
||||
if (err == ESP_OK) {
|
||||
printf("Command %s succeeded\n", at_args.command->sval[0]);
|
||||
if (command_result == s_common_out_str && s_common_out_str[0] != '\0') {
|
||||
ESP_LOGI(TAG, "Command string output: %s", s_common_out_str);
|
||||
} else if (command_result == &csq) {
|
||||
ESP_LOGI(TAG, "Command CSQ output: rssi:%d, ber:%d", csq.rssi, csq.ber);
|
||||
} else if (command_result == &cbc) {
|
||||
ESP_LOGI(TAG, "Command battery output:%d mV", cbc.battery_status);
|
||||
} else if (command_result == &bool_result) {
|
||||
ESP_LOGI(TAG, "Command bool output: %s", bool_result ? "true" : "false");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGE(TAG, "Command %s failed with %d", at_args.command->sval[0], err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int do_at_command(int argc, char **argv)
|
||||
{
|
||||
int timeout = 1000;
|
||||
int nerrors = arg_parse(argc, argv, (void **)&generic_at_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, generic_at_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
esp_modem_dce_handle_line_t handle_line = esp_modem_dce_handle_response_default;
|
||||
|
||||
strncpy(s_common_in_str, generic_at_args.command->sval[0], sizeof(s_common_in_str) - 2);
|
||||
if (generic_at_args.no_cr->count == 0) {
|
||||
size_t cmd_len = strlen(generic_at_args.command->sval[0]);
|
||||
s_common_in_str[cmd_len] = '\r';
|
||||
s_common_in_str[cmd_len + 1] = '\0';
|
||||
}
|
||||
|
||||
if (generic_at_args.timeout->count > 0) {
|
||||
timeout = generic_at_args.timeout->ival[0];
|
||||
}
|
||||
|
||||
if (generic_at_args.pattern->count > 0) {
|
||||
strncpy(s_common_out_str, generic_at_args.pattern->sval[0], sizeof(s_common_out_str));
|
||||
handle_line = handle_line_pattern;
|
||||
}
|
||||
|
||||
if (esp_modem_dce_generic_command(s_dce, s_common_in_str, timeout, handle_line, s_common_out_str) == ESP_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int do_modem_lifecycle(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&modem_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, modem_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (modem_args.param->count > 0) {
|
||||
esp_err_t err = ESP_FAIL;
|
||||
if (strstr(modem_args.param->sval[0], "PPP")) {
|
||||
err = esp_modem_start_ppp(s_dce->dte);
|
||||
} else if (strstr(modem_args.param->sval[0], "CMD")) {
|
||||
err = esp_modem_stop_ppp(s_dce->dte);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG, "set_working_mode %s succeeded", at_args.param->sval[0]);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "set_working_mode %s failed with %d", at_args.param->sval[0], err);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void register_dce(void)
|
||||
{
|
||||
at_args.command = arg_str1(NULL, NULL, "<command>", "Symbolic name of DCE command");
|
||||
at_args.param_int = arg_int0("i", "int", "<num>", "Input parameter of integer type");
|
||||
at_args.param_str = arg_str0("s", "str", "<str>", "Input parameter of string type");
|
||||
at_args.param_pdp = arg_str0("p", "pdp", "<pdp>", "Comma separated string with PDP context");
|
||||
at_args.param_bool = arg_str0("b", "bool", "<true/false>", "Input parameter of bool type");
|
||||
at_args.param = arg_str0(NULL, NULL, "<param>", "Default input argument treated as string");
|
||||
at_args.result = arg_str0("o", "out", "<type>", "Type of output parameter");
|
||||
at_args.end = arg_end(1);
|
||||
const esp_console_cmd_t at_cmd = {
|
||||
.command = "dce",
|
||||
.help = "send symbolic command to the modem",
|
||||
.hint = NULL,
|
||||
.func = &do_dce,
|
||||
.argtable = &at_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&at_cmd));
|
||||
}
|
||||
static void register_at_command(void)
|
||||
{
|
||||
generic_at_args.command = arg_str1(NULL, NULL, "<command>", "AT command to send to the modem");
|
||||
generic_at_args.timeout = arg_int0("t", "timeout", "<timeout>", "command timeout");
|
||||
generic_at_args.pattern = arg_str0("p", "pattern", "<pattern>", "command response to wait for");
|
||||
generic_at_args.no_cr = arg_litn("n", "no-cr", 0, 1, "not add trailing CR to the command");
|
||||
generic_at_args.end = arg_end(1);
|
||||
|
||||
const esp_console_cmd_t at_command = {
|
||||
.command = "at",
|
||||
.help = "send generic AT command to the modem",
|
||||
.hint = NULL,
|
||||
.func = &do_at_command,
|
||||
.argtable = &generic_at_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&at_command));
|
||||
}
|
||||
|
||||
static void register_modem_lifecycle(void)
|
||||
{
|
||||
modem_args.param = arg_str1(NULL, NULL, "<mode>", "PPP or CMD");
|
||||
modem_args.end = arg_end(1);
|
||||
const esp_console_cmd_t modem_cmd = {
|
||||
.command = "modem",
|
||||
.help = "set modem mode",
|
||||
.hint = NULL,
|
||||
.func = &do_modem_lifecycle,
|
||||
.argtable = &modem_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&modem_cmd));
|
||||
}
|
||||
|
||||
static esp_console_repl_t *s_repl = NULL;
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// init the DTE
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
dte_config.event_task_stack_size = 4096;
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet");
|
||||
dce_config.populate_command_list = true;
|
||||
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
|
||||
|
||||
esp_modem_dte_t *dte = esp_modem_dte_new(&dte_config);
|
||||
s_dce = esp_modem_dce_new(&dce_config);
|
||||
assert(s_dce != NULL);
|
||||
|
||||
esp_netif_t *esp_netif = esp_netif_new(&ppp_netif_config);
|
||||
assert(esp_netif);
|
||||
|
||||
ESP_ERROR_CHECK(esp_modem_default_attach(dte, s_dce, esp_netif));
|
||||
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
// init console REPL environment
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl));
|
||||
|
||||
register_dce();
|
||||
register_at_command();
|
||||
register_modem_lifecycle();
|
||||
modem_console_register_http();
|
||||
modem_console_register_ping();
|
||||
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(s_repl));
|
||||
}
|
141
esp_modem/examples/modem_console/main/ping_handle.c
Normal file
141
esp_modem/examples/modem_console/main/ping_handle.c
Normal file
@ -0,0 +1,141 @@
|
||||
/* Ping handle example
|
||||
|
||||
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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_log.h"
|
||||
#include "ping/ping_sock.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
static const char *TAG = "modem_console_ping";
|
||||
|
||||
static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint8_t ttl;
|
||||
uint16_t seqno;
|
||||
uint32_t elapsed_time, recv_len;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
|
||||
ESP_LOGI(TAG, "%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n",
|
||||
recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time);
|
||||
}
|
||||
|
||||
static void cmd_ping_on_ping_timeout(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint16_t seqno;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
ESP_LOGE(TAG, "From %s icmp_seq=%d timeout\n", inet_ntoa(target_addr.u_addr.ip4), seqno);
|
||||
}
|
||||
|
||||
static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
ip_addr_t target_addr;
|
||||
uint32_t transmitted;
|
||||
uint32_t received;
|
||||
uint32_t total_time_ms;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
|
||||
uint32_t loss = (uint32_t)((1 - ((float)received) / transmitted) * 100);
|
||||
if (IP_IS_V4(&target_addr)) {
|
||||
ESP_LOGI(TAG, "\n--- %s ping statistics ---\n", inet_ntoa(*ip_2_ip4(&target_addr)));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "\n--- %s ping statistics ---\n", inet6_ntoa(*ip_2_ip6(&target_addr)));
|
||||
}
|
||||
ESP_LOGI(TAG, "%d packets transmitted, %d received, %d%% packet loss, time %dms\n",
|
||||
transmitted, received, loss, total_time_ms);
|
||||
// delete the ping sessions, so that we clean up all resources and can create a new ping session
|
||||
// we don't have to call delete function in the callback, instead we can call delete function from other tasks
|
||||
esp_ping_delete_session(hdl);
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_dbl *timeout;
|
||||
struct arg_int *count;
|
||||
struct arg_str *host;
|
||||
struct arg_end *end;
|
||||
} ping_args;
|
||||
|
||||
static int do_ping_cmd(int argc, char **argv)
|
||||
{
|
||||
esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG();
|
||||
|
||||
int nerrors = arg_parse(argc, argv, (void **)&ping_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, ping_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ping_args.timeout->count > 0) {
|
||||
config.timeout_ms = (uint32_t)(ping_args.timeout->dval[0] * 1000);
|
||||
}
|
||||
|
||||
if (ping_args.count->count > 0) {
|
||||
config.count = (uint32_t)(ping_args.count->ival[0]);
|
||||
}
|
||||
|
||||
// parse IP address
|
||||
ip_addr_t target_addr;
|
||||
struct addrinfo hint;
|
||||
struct addrinfo *res = NULL;
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
memset(&target_addr, 0, sizeof(target_addr));
|
||||
/* convert domain name to IP address */
|
||||
if (getaddrinfo(ping_args.host->sval[0], NULL, &hint, &res) != 0) {
|
||||
printf("ping: unknown host %s\n", ping_args.host->sval[0]);
|
||||
return 1;
|
||||
}
|
||||
if (res->ai_family == AF_INET) {
|
||||
struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr;
|
||||
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
|
||||
} else {
|
||||
struct in6_addr addr6 = ((struct sockaddr_in6 *) (res->ai_addr))->sin6_addr;
|
||||
inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6);
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
config.target_addr = target_addr;
|
||||
|
||||
/* set callback functions */
|
||||
esp_ping_callbacks_t cbs = {
|
||||
.on_ping_success = cmd_ping_on_ping_success,
|
||||
.on_ping_timeout = cmd_ping_on_ping_timeout,
|
||||
.on_ping_end = cmd_ping_on_ping_end,
|
||||
.cb_args = NULL
|
||||
};
|
||||
esp_ping_handle_t ping;
|
||||
esp_ping_new_session(&config, &cbs, &ping);
|
||||
esp_ping_start(ping);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void modem_console_register_ping(void)
|
||||
{
|
||||
ping_args.timeout = arg_dbl0("W", "timeout", "<t>", "Time to wait for a response, in seconds");
|
||||
ping_args.count = arg_int0("c", "count", "<n>", "Stop after sending count packets");
|
||||
ping_args.host = arg_str1(NULL, NULL, "<host>", "Host address");
|
||||
ping_args.end = arg_end(1);
|
||||
const esp_console_cmd_t ping_cmd = {
|
||||
.command = "ping",
|
||||
.help = "send ICMP ECHO_REQUEST to network hosts",
|
||||
.hint = NULL,
|
||||
.func = &do_ping_cmd,
|
||||
.argtable = &ping_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&ping_cmd));
|
||||
}
|
8
esp_modem/examples/modem_console/sdkconfig.defaults
Normal file
8
esp_modem/examples/modem_console/sdkconfig.defaults
Normal file
@ -0,0 +1,8 @@
|
||||
# Override some defaults to enable PPP
|
||||
CONFIG_LWIP_PPP_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_PAP_SUPPORT=y
|
||||
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
|
||||
# Do not enable IPV6 in dte<->dce link local
|
||||
CONFIG_LWIP_PPP_ENABLE_IPV6=n
|
||||
# Disable legacy API
|
||||
CONFIG_MODEM_LEGACY_API=n
|
Reference in New Issue
Block a user