mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-18 21:12:22 +02:00
Examples: Modem console
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
idf_component_register(SRCS "modem_console_main.c"
|
idf_component_register(SRCS "modem_console_main.cpp"
|
||||||
|
"console_helper.cpp"
|
||||||
"httpget_handle.c"
|
"httpget_handle.c"
|
||||||
"ping_handle.c"
|
"ping_handle.c"
|
||||||
INCLUDE_DIRS ".")
|
INCLUDE_DIRS ".")
|
||||||
|
97
esp_modem/examples/modem_console/main/console_helper.cpp
Normal file
97
esp_modem/examples/modem_console/main/console_helper.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 3/17/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "console_helper.hpp"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
static const char *TAG = "modem_console_helper";
|
||||||
|
|
||||||
|
ConsoleCommand::ConsoleCommand(const char* command, const char* help, std::vector<CommandArgs>& args, std::function<bool(ConsoleCommand *)> f):
|
||||||
|
func(std::move(f))
|
||||||
|
{
|
||||||
|
RegisterCommand(command, help, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleCommand::RegisterCommand(const char* command, const char* help, std::vector<CommandArgs>& args)
|
||||||
|
{
|
||||||
|
assert(last_command <= MAX_REPEAT_NR);
|
||||||
|
void * common_arg = nullptr;
|
||||||
|
for (auto it: args) {
|
||||||
|
switch(it.type) {
|
||||||
|
case ARG_END:
|
||||||
|
break;
|
||||||
|
case STR0:
|
||||||
|
common_arg = arg_str0(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||||
|
break;
|
||||||
|
case STR1:
|
||||||
|
common_arg = arg_str1(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||||
|
break;
|
||||||
|
case INT0:
|
||||||
|
common_arg = arg_int0(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||||
|
break;
|
||||||
|
case INT1:
|
||||||
|
common_arg = arg_int1(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (common_arg) {
|
||||||
|
arg_table.emplace_back(common_arg);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Creating argument parser failed for %s", it.glossary);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arg_table.emplace_back( arg_end(1));
|
||||||
|
const esp_console_cmd_t command_def = {
|
||||||
|
.command = command,
|
||||||
|
.help = help,
|
||||||
|
.hint = nullptr,
|
||||||
|
.func = command_func_pts[last_command],
|
||||||
|
.argtable = &arg_table[0]
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(esp_console_cmd_register(&command_def));
|
||||||
|
last_command++;
|
||||||
|
console_commands.emplace_back(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConsoleCommand::get_count(int index)
|
||||||
|
{
|
||||||
|
return ((struct arg_str *)arg_table[index])->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ConsoleCommand::get_string(int index)
|
||||||
|
{
|
||||||
|
if (get_count(index) > 0) {
|
||||||
|
return std::string(((struct arg_str *)arg_table[index])->sval[0]);
|
||||||
|
}
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<ConsoleCommand*> ConsoleCommand::console_commands;
|
||||||
|
int ConsoleCommand::last_command = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const esp_console_cmd_func_t ConsoleCommand::command_func_pts[] = {
|
||||||
|
|
||||||
|
#define TEMPLATE(index) ConsoleCommand::command_func_ ## index ,
|
||||||
|
REPEAT_TEMPLATE_DEF(list of function pointers to command_func_XX() )
|
||||||
|
|
||||||
|
#undef TEMPLATE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int ConsoleCommand::command_func(int argc, char **argv) {
|
||||||
|
void * plain_arg_array = &arg_table[0];
|
||||||
|
int nerrors = arg_parse(argc, argv, (void **)plain_arg_array);
|
||||||
|
if (nerrors != 0) {
|
||||||
|
arg_print_errors(stderr, (struct arg_end *) arg_table.back(), argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (func) {
|
||||||
|
return func(this);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
76
esp_modem/examples/modem_console/main/console_helper.hpp
Normal file
76
esp_modem/examples/modem_console/main/console_helper.hpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 3/17/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MODEM_CONSOLE_CONSOLE_HELPER_H
|
||||||
|
#define MODEM_CONSOLE_CONSOLE_HELPER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <esp_console.h>
|
||||||
|
#include "argtable3/argtable3.h"
|
||||||
|
#include "repeat_helper.inc"
|
||||||
|
|
||||||
|
#define MAX_REPEAT_NR 10
|
||||||
|
|
||||||
|
enum arg_type {
|
||||||
|
STR0,
|
||||||
|
STR1,
|
||||||
|
INT0,
|
||||||
|
INT1,
|
||||||
|
ARG_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommandArgs {
|
||||||
|
CommandArgs(arg_type t, const char * shopts, const char * lopts, const char * data, const char * glos):
|
||||||
|
type(t), shortopts(shopts), longopts(lopts), datatype(data), glossary(glos) {}
|
||||||
|
arg_type type;
|
||||||
|
const char *shortopts;
|
||||||
|
const char *longopts;
|
||||||
|
const char *datatype;
|
||||||
|
const char *glossary;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConsoleCommand {
|
||||||
|
public:
|
||||||
|
template<typename T> explicit ConsoleCommand(const char* command, const char* help,
|
||||||
|
const T *arg_struct, size_t srg_struct_size , std::function<bool(ConsoleCommand *)> f):
|
||||||
|
func(std::move(f))
|
||||||
|
{
|
||||||
|
size_t args_plain_size = srg_struct_size / sizeof(CommandArgs);
|
||||||
|
auto first_arg = reinterpret_cast<const CommandArgs *>(arg_struct);
|
||||||
|
std::vector<CommandArgs> args(first_arg, first_arg + args_plain_size);
|
||||||
|
RegisterCommand(command, help, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit ConsoleCommand(const char* command, const char* help, std::vector<CommandArgs>& args, std::function<bool(ConsoleCommand *)> f);
|
||||||
|
int get_count(int index);
|
||||||
|
template<typename T> int get_count_of(CommandArgs T::*member) { return get_count(index_arg(member)); }
|
||||||
|
template<typename T> std::string get_string_of(CommandArgs T::*member) { return get_string(index_arg(member)); }
|
||||||
|
|
||||||
|
std::string get_string(int index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RegisterCommand(const char* command, const char* help, std::vector<CommandArgs>& args);
|
||||||
|
template<typename T> static constexpr size_t index_arg(CommandArgs T::*member)
|
||||||
|
{ return ((uint8_t *)&((T*)nullptr->*member) - (uint8_t *)nullptr)/sizeof(CommandArgs); }
|
||||||
|
std::function<bool(ConsoleCommand *)> func;
|
||||||
|
std::vector<void*> arg_table;
|
||||||
|
|
||||||
|
int command_func(int argc, char **argv);
|
||||||
|
|
||||||
|
#define TEMPLATE(index) \
|
||||||
|
static inline int command_func_ ## index(int argc, char **argv) \
|
||||||
|
{ return console_commands[index]->command_func(argc, argv); }
|
||||||
|
|
||||||
|
REPEAT_TEMPLATE_DEF(definition of command_func_XX() )
|
||||||
|
#undef TEMPLATE
|
||||||
|
|
||||||
|
static std::vector<ConsoleCommand*> console_commands;
|
||||||
|
static int last_command;
|
||||||
|
const static esp_console_cmd_func_t command_func_pts[];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //MODEM_CONSOLE_CONSOLE_HELPER_H
|
@ -1,309 +0,0 @@
|
|||||||
/* 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.pattern_queue_size = 100;
|
|
||||||
dte_config.event_task_stack_size = 4096;
|
|
||||||
dte_config.event_task_priority = 15;
|
|
||||||
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));
|
|
||||||
}
|
|
420
esp_modem/examples/modem_console/main/modem_console_main.cpp
Normal file
420
esp_modem/examples/modem_console/main/modem_console_main.cpp
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
/* 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 "esp_event.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
#include "argtable3/argtable3.h"
|
||||||
|
#include "cxx_include/esp_modem_dte.hpp"
|
||||||
|
#include "esp_modem_config.h"
|
||||||
|
#include "cxx_include/esp_modem_api.hpp"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "console_helper.hpp"
|
||||||
|
|
||||||
|
// utilities to check network connectivity
|
||||||
|
extern "C" void modem_console_register_http(void);
|
||||||
|
extern "C" 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_the_work(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;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return 0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//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_set_mode(s_dce, ESP_MODEM_MODE_DATA);
|
||||||
|
// } else if (strstr(modem_args.param->sval[0], "CMD")) {
|
||||||
|
// err = esp_modem_set_mode(s_dce, ESP_MODEM_MODE_COMMAND);
|
||||||
|
// } 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));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//enum arg_type {
|
||||||
|
// STR0,
|
||||||
|
// STR1,
|
||||||
|
// INT0,
|
||||||
|
// INT1,
|
||||||
|
// ARG_END,
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//struct CommandArgs {
|
||||||
|
// CommandArgs(arg_type t, const char * shopts, const char * lopts, const char * data, const char * glos):
|
||||||
|
// type(t), shortopts(shopts), longopts(lopts), datatype(data), glossary(glos) {}
|
||||||
|
// arg_type type;
|
||||||
|
// const char *shortopts;
|
||||||
|
// const char *longopts;
|
||||||
|
// const char *datatype;
|
||||||
|
// const char *glossary;
|
||||||
|
//};
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_COMMAND 10
|
||||||
|
//#define TEMPLATE(index) _TEMPLATE(index)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//#define REPEAT(a) _REPEAT(a)
|
||||||
|
#define MY_REPEAT(a) \
|
||||||
|
TEMPLATE(0) \
|
||||||
|
TEMPLATE(1) \
|
||||||
|
TEMPLATE(2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//static void register_modem_lifecycle(DCE<SIM7600> *dce)
|
||||||
|
//{
|
||||||
|
// 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 = "set_mode",
|
||||||
|
// .help = "set modem mode",
|
||||||
|
// .hint = nullptr,
|
||||||
|
// .func = do_the_work,
|
||||||
|
// .argtable = &modem_args
|
||||||
|
// };
|
||||||
|
// ESP_ERROR_CHECK(esp_console_cmd_register(&modem_cmd));
|
||||||
|
//}
|
||||||
|
|
||||||
|
static esp_console_repl_t *s_repl = NULL;
|
||||||
|
|
||||||
|
//template<typename T, typename U> constexpr size_t offset_of(U T::*member)
|
||||||
|
//{
|
||||||
|
// return (char*)&((T*)nullptr->*member) - (char*)nullptr;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" 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.pattern_queue_size = 100;
|
||||||
|
dte_config.event_task_stack_size = 4096;
|
||||||
|
dte_config.event_task_priority = 15;
|
||||||
|
// esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet");
|
||||||
|
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
|
||||||
|
|
||||||
|
esp_netif_t *esp_netif = esp_netif_new(&ppp_netif_config);
|
||||||
|
assert(esp_netif);
|
||||||
|
auto uart_dte = create_uart_dte(&dte_config);
|
||||||
|
std::string apn = "internet";
|
||||||
|
auto dce = create_SIM7600_dce(uart_dte, esp_netif, apn);
|
||||||
|
assert(dce != NULL);
|
||||||
|
|
||||||
|
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(dce.get());
|
||||||
|
modem_console_register_http();
|
||||||
|
modem_console_register_ping();
|
||||||
|
|
||||||
|
const struct SetModeArgs {
|
||||||
|
SetModeArgs(): mode(STR1, nullptr, nullptr, "<mode>", "PPP or CMD") {}
|
||||||
|
CommandArgs mode;
|
||||||
|
} set_mode_args;
|
||||||
|
ConsoleCommand SetModeParser("set_mode", "sets modem mode", &set_mode_args, sizeof(set_mode_args), [&](ConsoleCommand *c){
|
||||||
|
if (c->get_count_of(&SetModeArgs::mode)) {
|
||||||
|
auto mode = c->get_string_of(&SetModeArgs::mode);
|
||||||
|
if (mode == "CMD") {
|
||||||
|
ESP_LOGI(TAG, "Switching to command mode...");
|
||||||
|
dce->exit_data();
|
||||||
|
} else if (mode == "PPP") {
|
||||||
|
ESP_LOGI(TAG, "Switching to data mode...");
|
||||||
|
dce->set_data();
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Unsupported mode: %s", mode.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
const struct SetPinArgs {
|
||||||
|
SetPinArgs(): pin(STR1, nullptr, nullptr, "<pin>", "PIN") {}
|
||||||
|
CommandArgs pin;
|
||||||
|
} set_pin_args;
|
||||||
|
ConsoleCommand SetPinParser("set_pin", "sets SIM card PIN", &set_pin_args, sizeof(set_pin_args), [&](ConsoleCommand *c){
|
||||||
|
if (c->get_count_of(&SetPinArgs::pin)) {
|
||||||
|
auto pin = c->get_string_of(&SetPinArgs::pin);
|
||||||
|
ESP_LOGI(TAG, "Setting pin=%s...", pin.c_str());
|
||||||
|
auto err = dce->set_pin(pin);
|
||||||
|
if (err == command_result::OK) {
|
||||||
|
ESP_LOGI(TAG, "OK");
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT":"");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
std::vector<CommandArgs> no_args;
|
||||||
|
ConsoleCommand ReadPinArgs("read_pin", "checks if SIM is unlocked", no_args, [&](ConsoleCommand *c){
|
||||||
|
bool pin_ok;
|
||||||
|
ESP_LOGI(TAG, "Checking pin...");
|
||||||
|
auto err = dce->read_pin(pin_ok);
|
||||||
|
if (err == command_result::OK) {
|
||||||
|
ESP_LOGI(TAG, "OK. Pin status: %s", pin_ok ? "true": "false");
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT":"");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// start console REPL
|
||||||
|
ESP_ERROR_CHECK(esp_console_start_repl(s_repl));
|
||||||
|
ESP_LOGE(TAG, "Exit console!!!");
|
||||||
|
while(1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(50000));
|
||||||
|
ESP_LOGI(TAG, "working!");
|
||||||
|
}
|
||||||
|
}
|
27
esp_modem/examples/modem_console/main/repeat_helper.inc
Normal file
27
esp_modem/examples/modem_console/main/repeat_helper.inc
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 3/17/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MODEM_CONSOLE_REPEAT_HELPER_INC_H
|
||||||
|
#define MODEM_CONSOLE_REPEAT_HELPER_INC_H
|
||||||
|
|
||||||
|
#if MAX_REPEAT_NR < 10
|
||||||
|
#define REPEAT_TEMPLATE_DEF(...) REPEAT_10_TIMES(VA_ARG)
|
||||||
|
#else
|
||||||
|
#define REPEAT_TEMPLATE_DEF(...) REPEAT_100_TIMES(VA_ARG)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REPEAT_10_TIMES(a) \
|
||||||
|
TEMPLATE(0) \
|
||||||
|
TEMPLATE(1) \
|
||||||
|
TEMPLATE(2) \
|
||||||
|
TEMPLATE(3) \
|
||||||
|
TEMPLATE(4) \
|
||||||
|
TEMPLATE(5) \
|
||||||
|
TEMPLATE(6) \
|
||||||
|
TEMPLATE(7) \
|
||||||
|
TEMPLATE(8) \
|
||||||
|
TEMPLATE(9)
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MODEM_CONSOLE_REPEAT_HELPER_INC_H
|
@ -8,8 +8,8 @@
|
|||||||
#include "freertos/event_groups.h"
|
#include "freertos/event_groups.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||||
|
#define THROW(exception) throw(exception)
|
||||||
class esp_err_exception: virtual public std::exception {
|
class esp_err_exception: virtual public std::exception {
|
||||||
public:
|
public:
|
||||||
explicit esp_err_exception(esp_err_t err): esp_err(err) {}
|
explicit esp_err_exception(esp_err_t err): esp_err(err) {}
|
||||||
@ -24,25 +24,28 @@ private:
|
|||||||
esp_err_t esp_err;
|
esp_err_t esp_err;
|
||||||
std::string message;
|
std::string message;
|
||||||
};
|
};
|
||||||
|
#else
|
||||||
|
#define THROW(exception) abort()
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void throw_if_false(bool condition, std::string message)
|
static inline void throw_if_false(bool condition, std::string message)
|
||||||
{
|
{
|
||||||
if (!condition) {
|
if (!condition) {
|
||||||
throw(esp_err_exception(std::move(message)));
|
THROW(esp_err_exception(std::move(message)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void throw_if_esp_fail(esp_err_t err, std::string message)
|
static inline void throw_if_esp_fail(esp_err_t err, std::string message)
|
||||||
{
|
{
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
throw(esp_err_exception(std::move(message), err));
|
THROW(esp_err_exception(std::move(message), err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void throw_if_esp_fail(esp_err_t err)
|
static inline void throw_if_esp_fail(esp_err_t err)
|
||||||
{
|
{
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
throw(esp_err_exception(err));
|
THROW(esp_err_exception(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,20 +5,28 @@
|
|||||||
#ifndef SIMPLE_CXX_CLIENT_ESP_MODEM_API_H
|
#ifndef SIMPLE_CXX_CLIENT_ESP_MODEM_API_H
|
||||||
#define SIMPLE_CXX_CLIENT_ESP_MODEM_API_H
|
#define SIMPLE_CXX_CLIENT_ESP_MODEM_API_H
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "generate/esp_modem_command_declare.inc"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct esp_modem_dce_wrap esp_modem_t;
|
typedef struct esp_modem_dce_wrap esp_modem_dce_t;
|
||||||
|
typedef struct esp_modem_dte_config esp_modem_dte_config_t;
|
||||||
|
typedef enum esp_modem_dce_mode
|
||||||
|
{
|
||||||
|
ESP_MODEM_MODE_COMMAND,
|
||||||
|
ESP_MODEM_MODE_DATA,
|
||||||
|
} esp_modem_dce_mode_t;
|
||||||
|
|
||||||
esp_modem_t *esp_modem_new(const esp_modem_dte_config *config, esp_netif_t *netif, const char* apn);
|
esp_modem_dce_t *esp_modem_new(const esp_modem_dte_config_t *config, esp_netif_t *netif, const char* apn);
|
||||||
|
|
||||||
void esp_modem_destroy(esp_modem_t * dce);
|
void esp_modem_destroy(esp_modem_dce_t * dce);
|
||||||
|
esp_err_t esp_modem_set_mode(esp_modem_dce_t * dce, esp_modem_dce_mode_t mode);
|
||||||
|
|
||||||
|
|
||||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \
|
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \
|
||||||
esp_err_t esp_modem_ ## name(esp_modem_t *dce, ##__VA_ARGS__);
|
esp_err_t esp_modem_ ## name(esp_modem_dce_t *dce, ##__VA_ARGS__);
|
||||||
|
|
||||||
DECLARE_ALL_COMMAND_APIS(declares esp_modem_<API>(esp_modem_t * dce, ...);)
|
DECLARE_ALL_COMMAND_APIS(declares esp_modem_<API>(esp_modem_t * dce, ...);)
|
||||||
|
|
||||||
|
@ -6,11 +6,20 @@
|
|||||||
#define SIMPLE_CXX_CLIENT_ESP_MODEM_COMMAND_DECLARE_INC
|
#define SIMPLE_CXX_CLIENT_ESP_MODEM_COMMAND_DECLARE_INC
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define STRING_IN const std::string&
|
#include <string>
|
||||||
#define STRING_OUT std::string&
|
#define STRING_IN const std::string& string_in
|
||||||
|
#define STRING_OUT std::string& string_out
|
||||||
|
#define BOOL_IN const bool bool_in
|
||||||
|
#define BOOL_OUT bool& bool_out
|
||||||
|
#define STRUCT_OUT(struct_name) struct_name& struct_out
|
||||||
#else
|
#else
|
||||||
#define STRING_IN const char*
|
struct PdpContext;
|
||||||
#define STRING_OUT char*
|
|
||||||
|
#define STRING_IN const char* string_in
|
||||||
|
#define STRING_OUT char* string_out
|
||||||
|
#define BOOL_IN const bool bool_in
|
||||||
|
#define BOOL_OUT bool* bool_out
|
||||||
|
#define STRUCT_OUT(struct_name) struct struct_name* struct_out
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -30,28 +39,28 @@ ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, TEMPLATE_ARG, MUX_ARG, S
|
|||||||
*
|
*
|
||||||
* @param[out] pin_ok Pin
|
* @param[out] pin_ok Pin
|
||||||
*/ \
|
*/ \
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, TEMPLATE_ARG, MUX_ARG, bool& pin_ok) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, TEMPLATE_ARG, MUX_ARG, BOOL_OUT) \
|
||||||
\
|
\
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, TEMPLATE_ARG, MUX_ARG, bool on) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, TEMPLATE_ARG, MUX_ARG, BOOL_IN) \
|
||||||
\
|
\
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, TEMPLATE_ARG, MUX_ARG) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, TEMPLATE_ARG, MUX_ARG) \
|
||||||
\
|
\
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, TEMPLATE_ARG, MUX_ARG, PdpContext& pdp_context) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, TEMPLATE_ARG, MUX_ARG, STRUCT_OUT(PdpContext)) \
|
||||||
\
|
\
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_command_mode, command_result, TEMPLATE_ARG, MUX_ARG) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(set_command_mode, command_result, TEMPLATE_ARG, MUX_ARG) \
|
||||||
\
|
\
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, TEMPLATE_ARG, MUX_ARG) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, TEMPLATE_ARG, MUX_ARG) \
|
||||||
\
|
\
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, TEMPLATE_ARG, MUX_ARG, std::string& imsi_number) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, TEMPLATE_ARG, MUX_ARG, STRING_OUT) \
|
||||||
\
|
\
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, TEMPLATE_ARG, MUX_ARG, std::string& imsi_number) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, TEMPLATE_ARG, MUX_ARG, STRING_OUT) \
|
||||||
\
|
\
|
||||||
/**
|
/**
|
||||||
* @brief Reads the module name
|
* @brief Reads the module name
|
||||||
*
|
*
|
||||||
* @param[out] module name
|
* @param[out] module name
|
||||||
*/ \
|
*/ \
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, TEMPLATE_ARG, MUX_ARG, std::string& name) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, TEMPLATE_ARG, MUX_ARG, STRING_OUT) \
|
||||||
\
|
\
|
||||||
/**
|
/**
|
||||||
* @brief Sets the modem to data mode
|
* @brief Sets the modem to data mode
|
||||||
|
26
esp_modem/private_include/exception_stub.hpp
Normal file
26
esp_modem/private_include/exception_stub.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by david on 3/16/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MODEM_CONSOLE_EXCEPTION_STUB_HPP
|
||||||
|
#define MODEM_CONSOLE_EXCEPTION_STUB_HPP
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||||
|
#define TRY_CATCH_RET_NULL(block) \
|
||||||
|
try { block } \
|
||||||
|
} catch (std::bad_alloc& e) { \
|
||||||
|
ESP_LOGE(TAG, "Out of memory"); \
|
||||||
|
return nullptr; \
|
||||||
|
} catch (esp_err_exception& e) { \
|
||||||
|
esp_err_t err = e.get_err_t(); \
|
||||||
|
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err); \
|
||||||
|
ESP_LOGE(TAG, "%s", e.what()); \
|
||||||
|
return nullptr; \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define TRY_CATCH_RET_NULL(block) \
|
||||||
|
block
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MODEM_CONSOLE_EXCEPTION_STUB_HPP
|
@ -7,41 +7,24 @@
|
|||||||
#include "cxx_include/esp_modem_api.hpp"
|
#include "cxx_include/esp_modem_api.hpp"
|
||||||
#include "esp_modem_api.h"
|
#include "esp_modem_api.h"
|
||||||
#include "esp_modem_config.h"
|
#include "esp_modem_config.h"
|
||||||
|
#include "exception_stub.hpp"
|
||||||
|
|
||||||
static const char *TAG = "dce_factory";
|
|
||||||
struct PdpContext;
|
struct PdpContext;
|
||||||
|
|
||||||
std::shared_ptr<DTE> create_uart_dte(const esp_modem_dte_config *config)
|
std::shared_ptr<DTE> create_uart_dte(const esp_modem_dte_config *config)
|
||||||
{
|
{
|
||||||
try {
|
TRY_CATCH_RET_NULL(
|
||||||
auto term = create_uart_terminal(config);
|
auto term = create_uart_terminal(config);
|
||||||
return std::make_shared<DTE>(std::move(term));
|
return std::make_shared<DTE>(std::move(term));
|
||||||
} catch (std::bad_alloc& e) {
|
)
|
||||||
ESP_LOGE(TAG, "Out of memory");
|
|
||||||
return nullptr;
|
|
||||||
} catch (esp_err_exception& e) {
|
|
||||||
esp_err_t err = e.get_err_t();
|
|
||||||
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err);
|
|
||||||
ESP_LOGE(TAG, "%s", e.what());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename SpecificModule>
|
template<typename SpecificModule>
|
||||||
std::unique_ptr<DCE<SpecificModule>> create_dce(const std::shared_ptr<DTE>& dte, const std::shared_ptr<SpecificModule>& dev, esp_netif_t *netif)
|
std::unique_ptr<DCE<SpecificModule>> create_dce(const std::shared_ptr<DTE>& dte, const std::shared_ptr<SpecificModule>& dev, esp_netif_t *netif)
|
||||||
{
|
{
|
||||||
try {
|
TRY_CATCH_RET_NULL(
|
||||||
return std::make_unique<DCE<SpecificModule>>(dte, dev, netif);
|
return std::make_unique<DCE<SpecificModule>>(dte, dev, netif);
|
||||||
} catch (std::bad_alloc& e) {
|
)
|
||||||
ESP_LOGE(TAG, "Out of memory");
|
|
||||||
return nullptr;
|
|
||||||
} catch (esp_err_exception& e) {
|
|
||||||
esp_err_t err = e.get_err_t();
|
|
||||||
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err);
|
|
||||||
ESP_LOGE(TAG, "%s", e.what());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<DCE<GenericModule>> create_generic_dce_from_module(const std::shared_ptr<DTE>& dte, const std::shared_ptr<GenericModule>& dev, esp_netif_t *netif)
|
std::unique_ptr<DCE<GenericModule>> create_generic_dce_from_module(const std::shared_ptr<DTE>& dte, const std::shared_ptr<GenericModule>& dev, esp_netif_t *netif)
|
||||||
@ -86,7 +69,7 @@ static inline esp_err_t command_response_to_esp_err(command_result res)
|
|||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" esp_modem_t *esp_modem_new(const esp_modem_dte_config *config, esp_netif_t *netif, const char* apn)
|
extern "C" esp_modem_dce_t *esp_modem_new(const esp_modem_dte_config_t *config, esp_netif_t *netif, const char* apn)
|
||||||
{
|
{
|
||||||
auto dce_wrap = new (std::nothrow) esp_modem_dce_wrap;
|
auto dce_wrap = new (std::nothrow) esp_modem_dce_wrap;
|
||||||
if (dce_wrap == nullptr)
|
if (dce_wrap == nullptr)
|
||||||
@ -99,7 +82,7 @@ extern "C" esp_modem_t *esp_modem_new(const esp_modem_dte_config *config, esp_ne
|
|||||||
return dce_wrap;
|
return dce_wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void esp_modem_destroy(esp_modem_t * dce)
|
extern "C" void esp_modem_destroy(esp_modem_dce_t * dce)
|
||||||
{
|
{
|
||||||
assert(dce->modem_type == esp_modem_dce_wrap::MODEM_SIM7600);
|
assert(dce->modem_type == esp_modem_dce_wrap::MODEM_SIM7600);
|
||||||
auto dce_sim7600 = static_cast<DCE<SIM7600>*>(dce->dce_ptr);
|
auto dce_sim7600 = static_cast<DCE<SIM7600>*>(dce->dce_ptr);
|
||||||
@ -107,7 +90,21 @@ extern "C" void esp_modem_destroy(esp_modem_t * dce)
|
|||||||
delete dce;
|
delete dce;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" esp_err_t esp_modem_read_pin(esp_modem_t * dce, bool &x)
|
extern "C" esp_err_t esp_modem_set_mode(esp_modem_dce_t * dce, esp_modem_dce_mode_t mode)
|
||||||
|
{
|
||||||
|
assert(dce->modem_type == esp_modem_dce_wrap::MODEM_SIM7600);
|
||||||
|
auto dce_sim7600 = static_cast<DCE<SIM7600>*>(dce->dce_ptr);
|
||||||
|
if (mode == ESP_MODEM_MODE_DATA) {
|
||||||
|
dce_sim7600->set_data();
|
||||||
|
} else if (mode == ESP_MODEM_MODE_COMMAND) {
|
||||||
|
dce_sim7600->set_data();
|
||||||
|
} else {
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" esp_err_t esp_modem_read_pin(esp_modem_dce_t * dce, bool &x)
|
||||||
{
|
{
|
||||||
assert(dce->modem_type == esp_modem_dce_wrap::MODEM_SIM7600);
|
assert(dce->modem_type == esp_modem_dce_wrap::MODEM_SIM7600);
|
||||||
auto dce_sim7600 = static_cast<DCE<SIM7600>*>(dce->dce_ptr);
|
auto dce_sim7600 = static_cast<DCE<SIM7600>*>(dce->dce_ptr);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
#include "esp_modem_config.h"
|
#include "esp_modem_config.h"
|
||||||
|
#include "exception_stub.hpp"
|
||||||
|
|
||||||
#define ESP_MODEM_EVENT_QUEUE_SIZE (16)
|
#define ESP_MODEM_EVENT_QUEUE_SIZE (16)
|
||||||
|
|
||||||
@ -164,19 +165,11 @@ private:
|
|||||||
|
|
||||||
std::unique_ptr<Terminal> create_uart_terminal(const esp_modem_dte_config *config)
|
std::unique_ptr<Terminal> create_uart_terminal(const esp_modem_dte_config *config)
|
||||||
{
|
{
|
||||||
try {
|
TRY_CATCH_RET_NULL(
|
||||||
auto term = std::make_unique<uart_terminal>(config);
|
auto term = std::make_unique<uart_terminal>(config);
|
||||||
term->start();
|
term->start();
|
||||||
return term;
|
return term;
|
||||||
} catch (std::bad_alloc& e) {
|
)
|
||||||
ESP_LOGE(TAG, "Out of memory");
|
|
||||||
return nullptr;
|
|
||||||
} catch (esp_err_exception& e) {
|
|
||||||
esp_err_t err = e.get_err_t();
|
|
||||||
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err);
|
|
||||||
ESP_LOGE(TAG, "%s", e.what());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_terminal::task()
|
void uart_terminal::task()
|
||||||
|
Reference in New Issue
Block a user