Update examples

This commit is contained in:
David Cermak
2021-04-15 17:23:37 +02:00
parent 6065d89e18
commit 3de57e2c94
11 changed files with 166 additions and 400 deletions

View File

@ -14,16 +14,46 @@ using namespace esp_modem::dce_factory;
class NetModule;
typedef DCE_T<NetModule> 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 <typename T, typename ...Args>
static DCE_T<T>* create(const config *cfg, Args&&... args)
{
return build_generic_DCE<T>
(cfg, std::forward<Args>(args)...);
return build_generic_DCE<T>(cfg, std::forward<Args>(args)...);
}
template <typename T, typename ...Args>
static std::shared_ptr<T> create_module(const config *cfg, Args&&... args)
{
return build_shared_module<T>(cfg, std::forward<Args>(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> 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<void>(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<NetModule>(&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<void>(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> 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<NetModule>(&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<NetModule>(&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);
}

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -7,323 +7,29 @@
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#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;
static esp_console_repl_t *s_repl = nullptr;
using namespace esp_modem;
//template<typename T, typename U> 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);
}

View File

@ -58,7 +58,7 @@ public:
explicit CMux(std::unique_ptr<Terminal> t, std::unique_ptr<uint8_t[]> 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<bool(uint8_t *data, size_t len)> 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;
};
/**

View File

@ -152,7 +152,7 @@ public:
template <typename Module, typename ...Args>
std::shared_ptr<Module> build_shared_module(const config *cfg, Args&&... args)
static std::shared_ptr<Module> build_shared_module(const config *cfg, Args&&... args)
{
return build_module_T<Module>(cfg, std::forward<Args>(args)...);
}
@ -222,14 +222,15 @@ public:
private:
Modem m;
protected:
template <typename Module, typename Ptr = std::shared_ptr<Module>, typename ...Args>
Module build_module_T(const config *cfg, Args&&... args)
static Ptr build_module_T(const config *cfg, Args&&... args)
{
Builder<Module> b(std::forward<Args>(args)...);
return b.template create_module<Module>(cfg);
return b.template create_module<Ptr>(cfg);
}
protected:
template <typename Module, typename Dce = DCE_T<Module>, typename DcePtr = Dce*, typename ...Args>
static DcePtr build_generic_DCE(const config *cfg, Args&&... args)
{

View File

@ -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;

View File

@ -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<Lock> 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<Lock> 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)

View File

@ -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;
}

View File

@ -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<CMux>(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<CMuxInstance>(cmux_term, 0);
if (term == nullptr)
return false;
command_term = term.get(); // use command terminal as previously
other_term = std::make_unique<CMuxInstance>(cmux_term, 1);
return true;
}
command_result DTE::command(const std::string &cmd, got_line_cb got_line, uint32_t time_ms)