From 3de57e2c949a4eea547b0c6150cdaa619838ff0c Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 15 Apr 2021 17:23:37 +0200 Subject: [PATCH] Update examples --- .../examples/ap_to_pppos/main/NetworkDCE.cpp | 120 ++++--- .../ap_to_pppos/main/ap2pppos_example_main.c | 25 +- .../modem_console/main/console_helper.cpp | 11 +- .../modem_console/main/console_helper.hpp | 11 +- .../modem_console/main/modem_console_main.cpp | 325 +----------------- .../include/cxx_include/esp_modem_cmux.hpp | 4 +- .../cxx_include/esp_modem_dce_factory.hpp | 9 +- .../include/cxx_include/esp_modem_dte.hpp | 7 +- esp_modem/src/esp_modem_cmux.cpp | 20 +- esp_modem/src/esp_modem_dce.cpp | 22 +- esp_modem/src/esp_modem_dte.cpp | 12 +- 11 files changed, 166 insertions(+), 400 deletions(-) diff --git a/esp_modem/examples/ap_to_pppos/main/NetworkDCE.cpp b/esp_modem/examples/ap_to_pppos/main/NetworkDCE.cpp index 03c8800d1..2f0fbea18 100644 --- a/esp_modem/examples/ap_to_pppos/main/NetworkDCE.cpp +++ b/esp_modem/examples/ap_to_pppos/main/NetworkDCE.cpp @@ -14,16 +14,46 @@ using namespace esp_modem::dce_factory; class NetModule; typedef DCE_T NetDCE; +/** + * @brief Local network object used to setup PPP network + */ +class PPPNetwork { +public: + esp_err_t init(esp_netif_t *netif, const std::string& apn, const std::string &pin_number); + NetDCE * get_dce(); +private: + NetDCE *dce; +}; + +/** + * @brief The PPP network is a singleton, allocate statically here + */ +static PPPNetwork ppp_network; + +/** + * @brief Custom factory for creating NetDCE and NetModule + */ class NetDCE_Factory: public Factory { public: template static DCE_T* create(const config *cfg, Args&&... args) { - return build_generic_DCE - (cfg, std::forward(args)...); + return build_generic_DCE(cfg, std::forward(args)...); + } + + template + static std::shared_ptr create_module(const config *cfg, Args&&... args) + { + return build_shared_module(cfg, std::forward(args)...); } }; +/** + * @brief This is an example of implementing minimal network module functionality + * + * This does only include those AT commands, that are needed for setting the network up + * and also initialization part (set pin, ...) + */ class NetModule: public ModuleIf { public: explicit NetModule(std::shared_ptr dte, const esp_modem_dce_config *cfg): @@ -31,20 +61,6 @@ public: bool setup_data_mode() override { - // switch to command mode (in case we were in PPP mode) - static_cast(set_command_mode()); // ignore the potential failure, as we might be in command mode after startup - - bool is_pin_ok; - if (read_pin(is_pin_ok) != command_result::OK) - return false; - if (!is_pin_ok) { - if (set_pin() != command_result::OK) - return false; - vTaskDelay(pdMS_TO_TICKS(1000)); - if (read_pin(is_pin_ok) != command_result::OK || !is_pin_ok) - return false; - } - PdpContext pdp(apn); if (set_pdp_context(pdp) != command_result::OK) return false; @@ -64,54 +80,76 @@ public: return false; } - static esp_err_t init(esp_netif_t *netif, const std::string& apn, std::string pin_number) + bool init(const std::string& pin) { - // configure - pin = std::move(pin_number); - esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); - dte_config.event_task_stack_size = 4096; - dte_config.rx_buffer_size = 16384; - dte_config.tx_buffer_size = 2048; - esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(apn.c_str()); - - // create DTE and minimal network DCE - auto uart_dte = create_uart_dte(&dte_config); - dce = NetDCE_Factory::create(&dce_config, uart_dte, netif); - return dce == nullptr ? ESP_FAIL : ESP_OK; + // switch to command mode (in case we were in PPP mode) + static_cast(set_command_mode()); // ignore the potential failure, as we might be in command mode after startup + bool is_pin_ok; + if (read_pin(is_pin_ok) != command_result::OK) + return false; + if (!is_pin_ok) { + if (set_pin(pin) != command_result::OK) + return false; + vTaskDelay(pdMS_TO_TICKS(1000)); + if (read_pin(is_pin_ok) != command_result::OK || !is_pin_ok) + return false; + } + return true; } - static void deinit() { delete dce; } - static void start() { dce->set_data(); } - static void stop() { dce->exit_data(); } - private: - static NetDCE *dce; std::shared_ptr dte; std::string apn; - static std::string pin; [[nodiscard]] command_result set_pdp_context(PdpContext& pdp) { return dce_commands::set_pdp_context(dte.get(),pdp); } - [[nodiscard]] command_result set_pin() { return dce_commands::set_pin(dte.get(), pin); } + [[nodiscard]] command_result set_pin(const std::string &pin) { return dce_commands::set_pin(dte.get(), pin); } [[nodiscard]] command_result read_pin(bool& pin_ok) { return dce_commands::read_pin(dte.get(), pin_ok); } [[nodiscard]] command_result set_data_mode() { return dce_commands::set_data_mode(dte.get()); } [[nodiscard]] command_result resume_data_mode() { return dce_commands::resume_data_mode(dte.get()); } [[nodiscard]] command_result set_command_mode() { return dce_commands::set_command_mode(dte.get()); } }; -NetDCE *NetModule::dce = nullptr; -std::string NetModule::pin; + +esp_err_t PPPNetwork::init(esp_netif_t *netif, const std::string& apn, const std::string &pin_number) +{ + // configure + esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); + dte_config.event_task_stack_size = 4096; + dte_config.rx_buffer_size = 16384; + dte_config.tx_buffer_size = 2048; + esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(apn.c_str()); + + // create DTE and minimal network DCE + auto uart_dte = create_uart_dte(&dte_config); + + // create the specific device (and initialize it) + auto dev = NetDCE_Factory::create_module(&dce_config, uart_dte, netif); + if (!dev->init(pin_number)) + return ESP_FAIL; + + // now create the DCE from our already existent device + dce = NetDCE_Factory::create(&dce_config, uart_dte, netif, dev); + if (dce == nullptr) + return ESP_FAIL; + return ESP_OK; +} + +NetDCE *PPPNetwork::get_dce() +{ + return dce; +} extern "C" esp_err_t modem_init_network(esp_netif_t *netif) { - return NetModule::init(netif, "internet", "1234"); + return ppp_network.init(netif, "internet", "1234"); } extern "C" void modem_start_network() { - NetModule::start(); + ppp_network.get_dce()->set_mode(esp_modem::modem_mode::DATA_MODE); } extern "C" void modem_stop_network() { - NetModule::stop(); + ppp_network.get_dce()->set_mode(esp_modem::modem_mode::COMMAND_MODE); } diff --git a/esp_modem/examples/ap_to_pppos/main/ap2pppos_example_main.c b/esp_modem/examples/ap_to_pppos/main/ap2pppos_example_main.c index 46d1322f7..848abcc38 100644 --- a/esp_modem/examples/ap_to_pppos/main/ap2pppos_example_main.c +++ b/esp_modem/examples/ap_to_pppos/main/ap2pppos_example_main.c @@ -26,8 +26,8 @@ static EventGroupHandle_t event_group = NULL; static const int CONNECT_BIT = BIT0; static const int DISCONNECT_BIT = BIT1; -static void on_modem_event(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) +static void on_ip_event(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { if (event_base == IP_EVENT) { ESP_LOGD(TAG, "IP event! %d", event_id); @@ -146,26 +146,9 @@ void app_main(void) assert(ppp_netif); ESP_ERROR_CHECK(modem_init_network(ppp_netif)); -// vTaskDelay(pdMS_TO_TICKS(1000)); -// esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); -// dte_config.event_task_stack_size = 4096; -// dte_config.rx_buffer_size = 16384; -// dte_config.tx_buffer_size = 2048; -// esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet23"); -// dce_config.populate_command_list = true; + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event, NULL)); - - // Initialize esp-modem units, DTE, DCE, ppp-netif -// esp_modem_dte_t *dte = esp_modem_dte_new(&dte_config); -// esp_modem_dce_t *dce = sim7600_board_create(&dce_config); -// -// ESP_ERROR_CHECK(esp_modem_set_event_handler(dte, on_modem_event, ESP_EVENT_ANY_ID, dte)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_modem_event, NULL)); -// -// ESP_ERROR_CHECK(esp_modem_default_attach(dte, dce, ppp_netif)); -// -// ESP_ERROR_CHECK(esp_modem_default_start(dte)); // use retry -// ESP_ERROR_CHECK(esp_modem_start_ppp(dte)); + /* Init and start the modem network */ modem_start_network(); /* Wait for the first connection */ EventBits_t bits; diff --git a/esp_modem/examples/modem_console/main/console_helper.cpp b/esp_modem/examples/modem_console/main/console_helper.cpp index 86b0bdafd..4c32ccb41 100644 --- a/esp_modem/examples/modem_console/main/console_helper.cpp +++ b/esp_modem/examples/modem_console/main/console_helper.cpp @@ -1,6 +1,11 @@ -// -// Created by david on 3/17/21. -// +/* 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 "console_helper.hpp" #include "esp_log.h" diff --git a/esp_modem/examples/modem_console/main/console_helper.hpp b/esp_modem/examples/modem_console/main/console_helper.hpp index f92f07688..f7c2475a4 100644 --- a/esp_modem/examples/modem_console/main/console_helper.hpp +++ b/esp_modem/examples/modem_console/main/console_helper.hpp @@ -1,6 +1,11 @@ -// -// Created by david on 3/17/21. -// +/* 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. +*/ #ifndef MODEM_CONSOLE_CONSOLE_HELPER_H #define MODEM_CONSOLE_CONSOLE_HELPER_H diff --git a/esp_modem/examples/modem_console/main/modem_console_main.cpp b/esp_modem/examples/modem_console/main/modem_console_main.cpp index 7ce082844..67d8388ce 100644 --- a/esp_modem/examples/modem_console/main/modem_console_main.cpp +++ b/esp_modem/examples/modem_console/main/modem_console_main.cpp @@ -7,323 +7,29 @@ CONDITIONS OF ANY KIND, either express or implied. */ -#include -#include +#include +#include +#include +#include #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 -#include -#include -#include #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, "", "Symbolic name of DCE command"); -// at_args.param_int = arg_int0("i", "int", "", "Input parameter of integer type"); -// at_args.param_str = arg_str0("s", "str", "", "Input parameter of string type"); -// at_args.param_pdp = arg_str0("p", "pdp", "", "Comma separated string with PDP context"); -// at_args.param_bool = arg_str0("b", "bool", "", "Input parameter of bool type"); -// at_args.param = arg_str0(NULL, NULL, "", "Default input argument treated as string"); -// at_args.result = arg_str0("o", "out", "", "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, "", "AT command to send to the modem"); -// generic_at_args.timeout = arg_int0("t", "timeout", "", "command timeout"); -// generic_at_args.pattern = arg_str0("p", "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 *dce) -//{ -// modem_args.param = arg_str1(NULL, NULL, "", "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; +static esp_console_repl_t *s_repl = nullptr; using namespace esp_modem; -//template constexpr size_t offset_of(U T::*member) -//{ -// return (char*)&((T*)nullptr->*member) - (char*)nullptr; -//} #define CHECK_ERR(cmd, success_action) do { \ auto err = cmd; \ @@ -346,7 +52,6 @@ extern "C" void app_main(void) 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); @@ -363,9 +68,6 @@ extern "C" void app_main(void) // 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(); @@ -460,16 +162,19 @@ extern "C" void app_main(void) }, timeout),); }); - ConsoleCommand GetSignalQuality("get_signal_quality", "Gets signal quality", no_args, [&](ConsoleCommand *c){ + const ConsoleCommand GetSignalQuality("get_signal_quality", "Gets signal quality", no_args, [&](ConsoleCommand *c){ int rssi, ber; CHECK_ERR(dce->get_signal_quality(rssi, ber), ESP_LOGI(TAG, "OK. rssi=%d, ber=%d", rssi, ber)); }); + signal_group exit_signal; + const ConsoleCommand ExitConsole("exit", "exit the console appliation", no_args, [&](ConsoleCommand *c){ + ESP_LOGI(TAG, "Exiting..."); + exit_signal.set(1); + s_repl->del(s_repl); + return true; + }); // start console REPL ESP_ERROR_CHECK(esp_console_start_repl(s_repl)); - ESP_LOGE(TAG, "Exit console!!!"); - ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %d bytes)", __LINE__, esp_get_free_heap_size()); - while(1) { - vTaskDelay(pdMS_TO_TICKS(50000)); - ESP_LOGI(TAG, "working!"); - } + // wait till for exit + exit_signal.wait_any(1, UINT32_MAX); } diff --git a/esp_modem/include/cxx_include/esp_modem_cmux.hpp b/esp_modem/include/cxx_include/esp_modem_cmux.hpp index 636faaf10..2622fd8ab 100644 --- a/esp_modem/include/cxx_include/esp_modem_cmux.hpp +++ b/esp_modem/include/cxx_include/esp_modem_cmux.hpp @@ -58,7 +58,7 @@ public: explicit CMux(std::unique_ptr t, std::unique_ptr b, size_t buff_size): term(std::move(t)), buffer_size(buff_size), buffer(std::move(b)) {} ~CMux() = default; - void init(); + [[nodiscard]] bool init(); void set_read_cb(int inst, std::function f); int write(int i, uint8_t *data, size_t len); @@ -79,6 +79,8 @@ private: static uint8_t fcs_crc(const uint8_t frame[6]); Lock lock; int instance; + int sabm_ack; + }; /** diff --git a/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp b/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp index e6a54d06f..5be6d1fb8 100644 --- a/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp +++ b/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp @@ -152,7 +152,7 @@ public: template - std::shared_ptr build_shared_module(const config *cfg, Args&&... args) + static std::shared_ptr build_shared_module(const config *cfg, Args&&... args) { return build_module_T(cfg, std::forward(args)...); } @@ -222,14 +222,15 @@ public: private: Modem m; +protected: template , typename ...Args> - Module build_module_T(const config *cfg, Args&&... args) + static Ptr build_module_T(const config *cfg, Args&&... args) { Builder b(std::forward(args)...); - return b.template create_module(cfg); + return b.template create_module(cfg); } -protected: + template , typename DcePtr = Dce*, typename ...Args> static DcePtr build_generic_DCE(const config *cfg, Args&&... args) { diff --git a/esp_modem/include/cxx_include/esp_modem_dte.hpp b/esp_modem/include/cxx_include/esp_modem_dte.hpp index d47c04788..c8c96b6d6 100644 --- a/esp_modem/include/cxx_include/esp_modem_dte.hpp +++ b/esp_modem/include/cxx_include/esp_modem_dte.hpp @@ -82,7 +82,7 @@ public: void start() { term->start(); } - void set_mode(modem_mode m) { + [[nodiscard]] bool set_mode(modem_mode m) { term->start(); mode = m; if (m == modem_mode::DATA_MODE) { @@ -91,8 +91,9 @@ public: command_term = other_term.get(); } } else if (m == modem_mode::CMUX_MODE) { - setup_cmux(); + return setup_cmux(); } + return true; } command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms) override; @@ -102,7 +103,7 @@ public: private: Lock lock; - void setup_cmux(); + [[nodiscard]] bool setup_cmux(); static const size_t GOT_LINE = signal_group::bit0; size_t buffer_size; diff --git a/esp_modem/src/esp_modem_cmux.cpp b/esp_modem/src/esp_modem_cmux.cpp index 0008f4afd..e5cc73afe 100644 --- a/esp_modem/src/esp_modem_cmux.cpp +++ b/esp_modem/src/esp_modem_cmux.cpp @@ -91,6 +91,9 @@ void CMux::data_available(uint8_t *data, size_t len) int virtual_term = dlci - 1; if (virtual_term < max_terms && read_cb[virtual_term]) read_cb[virtual_term](data, len); + } else if (type == 0x73 && len == 0) { // notify the initial SABM command + Scoped l(lock); + sabm_ack = dlci; } } @@ -205,7 +208,8 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len) } return true; } -void CMux::init() + +bool CMux::init() { frame_header_offset = 0; state = cmux_state::INIT; @@ -215,11 +219,23 @@ void CMux::init() return false; }); + sabm_ack = -1; for (size_t i = 0; i < 3; i++) { + int timeout = 0; send_sabm(i); - usleep(100'000); + while (1) { + usleep(10'000); + Scoped l(lock); + if (sabm_ack == i) { + sabm_ack = -1; + break; + } + if (timeout++ > 100) + return false; + } } + return true; } int CMux::write(int virtual_term, uint8_t *data, size_t len) diff --git a/esp_modem/src/esp_modem_dce.cpp b/esp_modem/src/esp_modem_dce.cpp index 2a23e7989..e084799f6 100644 --- a/esp_modem/src/esp_modem_dce.cpp +++ b/esp_modem/src/esp_modem_dce.cpp @@ -28,22 +28,27 @@ bool DCE_Mode::set(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m) if (mode == modem_mode::COMMAND_MODE) return false; netif.stop(); - device->set_mode(modem_mode::COMMAND_MODE); + if (!device->set_mode(modem_mode::COMMAND_MODE)) + return false; dte->set_read_cb([&](uint8_t *data, size_t len) -> bool { ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data", data, len, ESP_LOG_INFO); return false; }); netif.wait_until_ppp_exits(); dte->set_read_cb(nullptr); - dte->set_mode(modem_mode::COMMAND_MODE); + if (!dte->set_mode(modem_mode::COMMAND_MODE)) + return false; mode = m; return true; case modem_mode::DATA_MODE: if (mode == modem_mode::DATA_MODE) return false; - device->setup_data_mode(); - device->set_mode(modem_mode::DATA_MODE); - dte->set_mode(modem_mode::DATA_MODE); + if (!device->setup_data_mode()) + return false; + if (!device->set_mode(modem_mode::DATA_MODE)) + return false; + if (!dte->set_mode(modem_mode::DATA_MODE)) + return false; netif.start(); mode = m; return true; @@ -51,11 +56,8 @@ bool DCE_Mode::set(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m) if (mode == modem_mode::DATA_MODE || mode == modem_mode::CMUX_MODE) return false; device->set_mode(modem_mode::CMUX_MODE); - dte->set_mode(modem_mode::CMUX_MODE); -// auto dte1 = create_virtual(dte, 1); -// auto dte2 = create_virtual(dte, 2); -// device->swap_dte(dte1); -// netif->swap_dte(dte2;); + if (!dte->set_mode(modem_mode::CMUX_MODE)) + return false; mode = modem_mode::COMMAND_MODE; return true; } diff --git a/esp_modem/src/esp_modem_dte.cpp b/esp_modem/src/esp_modem_dte.cpp index be298f3be..c98533a7c 100644 --- a/esp_modem/src/esp_modem_dte.cpp +++ b/esp_modem/src/esp_modem_dte.cpp @@ -56,15 +56,23 @@ command_result DTE::command(const std::string &command, got_line_cb got_line, ui return res; } -void DTE::setup_cmux() +bool DTE::setup_cmux() { auto original_term = std::move(term); + if (original_term == nullptr) + return false; auto cmux_term = std::make_shared(std::move(original_term), std::move(buffer), buffer_size); + if (cmux_term == nullptr) + return false; buffer_size = 0; - cmux_term->init(); + if (!cmux_term->init()) + return false; term = std::make_unique(cmux_term, 0); + if (term == nullptr) + return false; command_term = term.get(); // use command terminal as previously other_term = std::make_unique(cmux_term, 1); + return true; } command_result DTE::command(const std::string &cmd, got_line_cb got_line, uint32_t time_ms)