Applied astyle code formatting

This commit is contained in:
David Cermak
2021-06-01 10:21:51 +02:00
parent dc64f862c4
commit a61e9e2d40
43 changed files with 865 additions and 662 deletions

View File

@ -32,13 +32,13 @@ using NetDCE = DCE_T<NetModule>;
class NetDCE_Factory: public Factory { class NetDCE_Factory: public Factory {
public: public:
template <typename Module, typename ...Args> template <typename Module, typename ...Args>
static DCE_T<Module>* create(const config *cfg, Args&&... args) static DCE_T<Module> *create(const config *cfg, Args &&... args)
{ {
return build_generic_DCE<Module>(cfg, std::forward<Args>(args)...); return build_generic_DCE<Module>(cfg, std::forward<Args>(args)...);
} }
template <typename Module, typename ...Args> template <typename Module, typename ...Args>
static std::shared_ptr<Module> create_module(const config *cfg, Args&&... args) static std::shared_ptr<Module> create_module(const config *cfg, Args &&... args)
{ {
return build_shared_module<Module>(cfg, std::forward<Args>(args)...); return build_shared_module<Module>(cfg, std::forward<Args>(args)...);
} }
@ -53,44 +53,48 @@ public:
class NetModule: public ModuleIf { class NetModule: public ModuleIf {
public: public:
explicit NetModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config *cfg): explicit NetModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config *cfg):
dte(std::move(dte)), apn(std::string(cfg->apn)) {} dte(std::move(dte)), apn(std::string(cfg->apn)) {}
[[nodiscard]] bool setup_data_mode() override [[nodiscard]] bool setup_data_mode() override
{ {
PdpContext pdp(apn); PdpContext pdp(apn);
if (set_pdp_context(pdp) != command_result::OK) if (set_pdp_context(pdp) != command_result::OK) {
return false; return false;
}
return true; return true;
} }
bool set_mode(modem_mode mode) override bool set_mode(modem_mode mode) override
{ {
switch (mode) { switch (mode) {
case esp_modem::modem_mode::DATA_MODE: case esp_modem::modem_mode::DATA_MODE:
if (set_data_mode() != command_result::OK) { if (set_data_mode() != command_result::OK) {
return resume_data_mode() == command_result::OK; return resume_data_mode() == command_result::OK;
} }
return true; return true;
case esp_modem::modem_mode::COMMAND_MODE: case esp_modem::modem_mode::COMMAND_MODE:
return set_command_mode() == command_result::OK; return set_command_mode() == command_result::OK;
default: default:
return false; return false;
} }
} }
[[maybe_unused]] bool init_sim(const std::string& pin) [[maybe_unused]] bool init_sim(const std::string &pin)
{ {
// switch to command mode (in case we were in PPP mode) // 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 static_cast<void>(set_command_mode()); // ignore the potential failure, as we might be in command mode after startup
bool is_pin_ok; bool is_pin_ok;
if (read_pin(is_pin_ok) != command_result::OK) if (read_pin(is_pin_ok) != command_result::OK) {
return false; return false;
}
if (!is_pin_ok) { if (!is_pin_ok) {
if (set_pin(pin) != command_result::OK) if (set_pin(pin) != command_result::OK) {
return false; return false;
}
vTaskDelay(pdMS_TO_TICKS(1000)); vTaskDelay(pdMS_TO_TICKS(1000));
if (read_pin(is_pin_ok) != command_result::OK || !is_pin_ok) if (read_pin(is_pin_ok) != command_result::OK || !is_pin_ok) {
return false; return false;
}
} }
return true; return true;
} }
@ -99,12 +103,30 @@ private:
std::shared_ptr<DTE> dte; std::shared_ptr<DTE> dte;
std::string apn; std::string apn;
[[nodiscard]] command_result set_pdp_context(PdpContext& pdp) { return dce_commands::set_pdp_context(dte.get(),pdp); } [[nodiscard]] command_result set_pdp_context(PdpContext &pdp)
[[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); } return dce_commands::set_pdp_context(dte.get(), pdp);
[[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_pin(const std::string &pin)
[[nodiscard]] command_result set_command_mode() { return dce_commands::set_command_mode(dte.get()); } {
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());
}
}; };
@ -132,13 +154,15 @@ extern "C" esp_err_t modem_init_network(esp_netif_t *netif)
// create the specific device (and initialize it) // create the specific device (and initialize it)
auto dev = NetDCE_Factory::create_module<NetModule>(&dce_config, uart_dte, netif); auto dev = NetDCE_Factory::create_module<NetModule>(&dce_config, uart_dte, netif);
#if CONFIG_EXAMPLE_NEED_SIM_PIN == 1 #if CONFIG_EXAMPLE_NEED_SIM_PIN == 1
if (!dev->init_sim(CONFIG_EXAMPLE_SIM_PIN)) if (!dev->init_sim(CONFIG_EXAMPLE_SIM_PIN)) {
return ESP_FAIL; return ESP_FAIL;
}
#endif #endif
// now create the DCE from our already existent device // now create the DCE from our already existent device
dce = NetDCE_Factory::create<NetModule>(&dce_config, uart_dte, netif, dev); dce = NetDCE_Factory::create<NetModule>(&dce_config, uart_dte, netif, dev);
if (dce == nullptr) if (dce == nullptr) {
return ESP_FAIL; return ESP_FAIL;
}
return ESP_OK; return ESP_OK;
} }

View File

@ -22,15 +22,15 @@ int main()
{ {
// init the DTE // init the DTE
esp_modem_dte_config_t dte_config = { esp_modem_dte_config_t dte_config = {
.dte_buffer_size = 512, .dte_buffer_size = 512,
.task_stack_size = 1024, .task_stack_size = 1024,
.task_priority = 10, .task_priority = 10,
.vfs_config = {} .vfs_config = {}
}; };
#if CONFIG_USE_VFS_UART == 1 #if CONFIG_USE_VFS_UART == 1
struct esp_modem_vfs_uart_creator uart_config = { struct esp_modem_vfs_uart_creator uart_config = {
.dev_name = "/dev/ttyUSB0", .dev_name = "/dev/ttyUSB0",
.uart = {} .uart = {}
}; };
assert(vfs_create_uart(&uart_config, &dte_config.vfs_config) == true); assert(vfs_create_uart(&uart_config, &dte_config.vfs_config) == true);
#else #else
@ -39,16 +39,16 @@ int main()
* socat TCP-L:2222 GOPEN:/dev/ttyS0,ispeed=115200,ospeed=1152000,b115200,raw,echo=0 * socat TCP-L:2222 GOPEN:/dev/ttyS0,ispeed=115200,ospeed=1152000,b115200,raw,echo=0
*/ */
struct esp_modem_vfs_socket_creator socket_config = { struct esp_modem_vfs_socket_creator socket_config = {
.host_name = "raspberrypi.local", .host_name = "raspberrypi.local",
.port = 2222 .port = 2222
}; };
assert(vfs_create_socket(&socket_config, &dte_config.vfs_config) == true); assert(vfs_create_socket(&socket_config, &dte_config.vfs_config) == true);
#endif #endif
auto dte = create_vfs_dte(&dte_config); auto dte = create_vfs_dte(&dte_config);
esp_netif_config_t netif_config = { esp_netif_config_t netif_config = {
.dev_name = "/dev/net/tun", .dev_name = "/dev/net/tun",
.if_name = "tun0" .if_name = "tun0"
}; };
esp_netif_t *tun_netif = esp_netif_new(&netif_config); esp_netif_t *tun_netif = esp_netif_new(&netif_config);
@ -67,12 +67,13 @@ int main()
std::string str; std::string str;
// dce->set_mode(esp_modem::modem_mode::CMUX_MODE); // dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
dce->get_imsi(str); dce->get_imsi(str);
ESP_LOGI(TAG, "Modem IMSI number: %s",str.c_str()); ESP_LOGI(TAG, "Modem IMSI number: %s", str.c_str());
dce->get_imei(str); dce->get_imei(str);
ESP_LOGI(TAG, "Modem IMEI number: %s",str.c_str()); ESP_LOGI(TAG, "Modem IMEI number: %s", str.c_str());
while (command_result::OK != dce->get_operator_name(str)) while (command_result::OK != dce->get_operator_name(str)) {
{ printf(".\n"); } printf(".\n");
ESP_LOGI(TAG, "Operator name: %s",str.c_str()); }
ESP_LOGI(TAG, "Operator name: %s", str.c_str());
dce->set_mode(esp_modem::modem_mode::DATA_MODE); dce->set_mode(esp_modem::modem_mode::DATA_MODE);

View File

@ -12,35 +12,35 @@
static const char *TAG = "modem_console_helper"; static const char *TAG = "modem_console_helper";
ConsoleCommand::ConsoleCommand(const char* command, const char* help, const std::vector<CommandArgs>& args, std::function<bool(ConsoleCommand *)> f): ConsoleCommand::ConsoleCommand(const char *command, const char *help, const std::vector<CommandArgs> &args, std::function<bool(ConsoleCommand *)> f):
func(std::move(f)) func(std::move(f))
{ {
RegisterCommand(command, help, args); RegisterCommand(command, help, args);
} }
void ConsoleCommand::RegisterCommand(const char* command, const char* help, const std::vector<CommandArgs>& args) void ConsoleCommand::RegisterCommand(const char *command, const char *help, const std::vector<CommandArgs> &args)
{ {
assert(last_command <= MAX_REPEAT_NR); assert(last_command <= MAX_REPEAT_NR);
arg_type common_arg = { }; arg_type common_arg = { };
for (auto& it: args) { for (auto &it : args) {
switch(it.type) { switch (it.type) {
case ARG_END: case ARG_END:
break; break;
case STR0: case STR0:
common_arg.str = arg_str0(it.shortopts, it.longopts, it.datatype, it.glossary); common_arg.str = arg_str0(it.shortopts, it.longopts, it.datatype, it.glossary);
break; break;
case STR1: case STR1:
common_arg.str = arg_str1(it.shortopts, it.longopts, it.datatype, it.glossary); common_arg.str = arg_str1(it.shortopts, it.longopts, it.datatype, it.glossary);
break; break;
case INT0: case INT0:
common_arg.intx = arg_int0(it.shortopts, it.longopts, it.datatype, it.glossary); common_arg.intx = arg_int0(it.shortopts, it.longopts, it.datatype, it.glossary);
break; break;
case INT1: case INT1:
common_arg.intx = arg_int1(it.shortopts, it.longopts, it.datatype, it.glossary); common_arg.intx = arg_int1(it.shortopts, it.longopts, it.datatype, it.glossary);
break; break;
case LIT0: case LIT0:
common_arg.lit = arg_lit0(it.shortopts, it.longopts, it.glossary); common_arg.lit = arg_lit0(it.shortopts, it.longopts, it.glossary);
break; break;
} }
if (common_arg.is_null()) { if (common_arg.is_null()) {
arg_table.emplace_back(common_arg); arg_table.emplace_back(common_arg);
@ -53,11 +53,11 @@ void ConsoleCommand::RegisterCommand(const char* command, const char* help, cons
arg_type end = { .end = arg_end(1) }; arg_type end = { .end = arg_end(1) };
arg_table.emplace_back(end); arg_table.emplace_back(end);
const esp_console_cmd_t command_def = { const esp_console_cmd_t command_def = {
.command = command, .command = command,
.help = help, .help = help,
.hint = nullptr, .hint = nullptr,
.func = command_func_pts[last_command], .func = command_func_pts[last_command],
.argtable = &arg_table[0] .argtable = &arg_table[0]
}; };
ESP_ERROR_CHECK(esp_console_cmd_register(&command_def)); ESP_ERROR_CHECK(esp_console_cmd_register(&command_def));
last_command++; last_command++;
@ -86,8 +86,9 @@ int ConsoleCommand::get_int(int index)
} }
int ConsoleCommand::command_func(int argc, char **argv) { int ConsoleCommand::command_func(int argc, char **argv)
arg_type* plain_arg_array = &arg_table[0]; {
arg_type *plain_arg_array = &arg_table[0];
int nerrors = arg_parse(argc, argv, (void **)plain_arg_array); int nerrors = arg_parse(argc, argv, (void **)plain_arg_array);
if (nerrors != 0) { if (nerrors != 0) {
arg_print_errors(stderr, arg_table.back().end, argv[0]); arg_print_errors(stderr, arg_table.back().end, argv[0]);
@ -122,7 +123,7 @@ const esp_console_cmd_func_t ConsoleCommand::command_func_pts[] = {
#define ITEM_TO_REPEAT(index) StaticCommands::command_func_ ## index , #define ITEM_TO_REPEAT(index) StaticCommands::command_func_ ## index ,
_DO_REPEAT_ITEM() _DO_REPEAT_ITEM()
#undef ITEM_TO_REPEAT #undef ITEM_TO_REPEAT
}; };
@ -130,5 +131,5 @@ const esp_console_cmd_func_t ConsoleCommand::command_func_pts[] = {
/** /**
* @brief Static members defined for ConsoleCommand * @brief Static members defined for ConsoleCommand
*/ */
std::vector<ConsoleCommand*> ConsoleCommand::console_commands; std::vector<ConsoleCommand *> ConsoleCommand::console_commands;
int ConsoleCommand::last_command = 0; int ConsoleCommand::last_command = 0;

View File

@ -34,10 +34,10 @@ enum arg_type {
* Command argument struct definition for list of arguments of one command * Command argument struct definition for list of arguments of one command
*/ */
struct CommandArgs { struct CommandArgs {
CommandArgs(arg_type t, const char * shopts, const char * lopts, const char * data, const char * glos): 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) {} type(t), shortopts(shopts), longopts(lopts), datatype(data), glossary(glos) {}
CommandArgs(arg_type t, const char * shopts, const char * lopts, const char * glos): CommandArgs(arg_type t, const char *shopts, const char *lopts, const char *glos):
type(t), shortopts(shopts), longopts(lopts), datatype(nullptr), glossary(glos) {} type(t), shortopts(shopts), longopts(lopts), datatype(nullptr), glossary(glos) {}
arg_type type; arg_type type;
const char *shortopts; const char *shortopts;
@ -56,14 +56,16 @@ class ConsoleCommand {
* @brief Common argument types to be stored internally for parsing later * @brief Common argument types to be stored internally for parsing later
*/ */
using arg_type = using arg_type =
union { union {
struct arg_int *intx; struct arg_int *intx;
struct arg_str *str; struct arg_str *str;
struct arg_lit *lit; struct arg_lit *lit;
struct arg_end *end; struct arg_end *end;
void *__raw_ptr; void *__raw_ptr;
bool is_null() const { return __raw_ptr; } bool is_null() const {
}; return __raw_ptr;
}
};
friend class StaticCommands; friend class StaticCommands;
public: public:
@ -75,8 +77,8 @@ public:
* @param srg_struct_size Size of the argument struct * @param srg_struct_size Size of the argument struct
* @param f Function callback for the command * @param f Function callback for the command
*/ */
template<typename T> explicit ConsoleCommand(const char* command, const char* help, const T *arg_struct, size_t srg_struct_size, 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)) std::function<bool(ConsoleCommand *)> f): func(std::move(f))
{ {
size_t args_plain_size = srg_struct_size / sizeof(CommandArgs); size_t args_plain_size = srg_struct_size / sizeof(CommandArgs);
auto first_arg = reinterpret_cast<const CommandArgs *>(arg_struct); auto first_arg = reinterpret_cast<const CommandArgs *>(arg_struct);
@ -87,27 +89,38 @@ public:
/** /**
* @brief Another method of Console command definitions using vector arg struct * @brief Another method of Console command definitions using vector arg struct
*/ */
explicit ConsoleCommand(const char* command, const char* help, const std::vector<CommandArgs>& args, std::function<bool(ConsoleCommand *)> f); explicit ConsoleCommand(const char *command, const char *help, const std::vector<CommandArgs> &args, std::function<bool(ConsoleCommand *)> f);
/** /**
* @brief Utility getters of various params from the argument list * @brief Utility getters of various params from the argument list
*/ */
template<typename T> int get_count_of(CommandArgs T::*member) { return get_count(index_arg(member)); } template<typename T> int get_count_of(CommandArgs T::*member)
template<typename T> std::string get_string_of(CommandArgs T::*member) { return get_string(index_arg(member)); } {
template<typename T> int get_int_of(CommandArgs T::*member) { return get_int(index_arg(member)); } return get_count(index_arg(member));
}
template<typename T> std::string get_string_of(CommandArgs T::*member)
{
return get_string(index_arg(member));
}
template<typename T> int get_int_of(CommandArgs T::*member)
{
return get_int(index_arg(member));
}
std::string get_string(int index); std::string get_string(int index);
int get_int(int index); int get_int(int index);
private: private:
int get_count(int index); int get_count(int index);
void RegisterCommand(const char* command, const char* help, const std::vector<CommandArgs>& args); void RegisterCommand(const char *command, const char *help, const std::vector<CommandArgs> &args);
template<typename T> static constexpr size_t index_arg(CommandArgs T::*member) template<typename T> static constexpr size_t index_arg(CommandArgs T::*member)
{ return ((uint8_t *)&((T*)nullptr->*member) - (uint8_t *)nullptr)/sizeof(CommandArgs); } {
return ((uint8_t *) & ((T *)nullptr->*member) - (uint8_t *)nullptr) / sizeof(CommandArgs);
}
std::vector<arg_type> arg_table; std::vector<arg_type> arg_table;
int command_func(int argc, char **argv); int command_func(int argc, char **argv);
static int last_command; static int last_command;
static std::vector<ConsoleCommand*> console_commands; static std::vector<ConsoleCommand *> console_commands;
std::function<bool(ConsoleCommand *)> func; std::function<bool(ConsoleCommand *)> func;
const static esp_console_cmd_func_t command_func_pts[]; const static esp_console_cmd_func_t command_func_pts[];
}; };

View File

@ -73,7 +73,7 @@ extern "C" void app_main(void)
SetModeArgs(): mode(STR1, nullptr, nullptr, "<mode>", "PPP, CMD or CMUX") {} SetModeArgs(): mode(STR1, nullptr, nullptr, "<mode>", "PPP, CMD or CMUX") {}
CommandArgs mode; CommandArgs mode;
} set_mode_args; } set_mode_args;
const ConsoleCommand SetModeParser("set_mode", "sets modem mode", &set_mode_args, sizeof(set_mode_args), [&](ConsoleCommand *c){ const ConsoleCommand SetModeParser("set_mode", "sets modem mode", &set_mode_args, sizeof(set_mode_args), [&](ConsoleCommand * c) {
if (c->get_count_of(&SetModeArgs::mode)) { if (c->get_count_of(&SetModeArgs::mode)) {
auto mode = c->get_string_of(&SetModeArgs::mode); auto mode = c->get_string_of(&SetModeArgs::mode);
modem_mode dev_mode; modem_mode dev_mode;
@ -101,7 +101,7 @@ extern "C" void app_main(void)
SetPinArgs(): pin(STR1, nullptr, nullptr, "<pin>", "PIN") {} SetPinArgs(): pin(STR1, nullptr, nullptr, "<pin>", "PIN") {}
CommandArgs pin; CommandArgs pin;
} set_pin_args; } set_pin_args;
const ConsoleCommand SetPinParser("set_pin", "sets SIM card PIN", &set_pin_args, sizeof(set_pin_args), [&](ConsoleCommand *c){ const ConsoleCommand SetPinParser("set_pin", "sets SIM card PIN", &set_pin_args, sizeof(set_pin_args), [&](ConsoleCommand * c) {
if (c->get_count_of(&SetPinArgs::pin)) { if (c->get_count_of(&SetPinArgs::pin)) {
auto pin = c->get_string_of(&SetPinArgs::pin); auto pin = c->get_string_of(&SetPinArgs::pin);
ESP_LOGI(TAG, "Setting pin=%s...", pin.c_str()); ESP_LOGI(TAG, "Setting pin=%s...", pin.c_str());
@ -109,7 +109,7 @@ extern "C" void app_main(void)
if (err == command_result::OK) { if (err == command_result::OK) {
ESP_LOGI(TAG, "OK"); ESP_LOGI(TAG, "OK");
} else { } else {
ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT":""); ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT" : "");
return 1; return 1;
} }
} }
@ -117,26 +117,26 @@ extern "C" void app_main(void)
}); });
const std::vector<CommandArgs> no_args; const std::vector<CommandArgs> no_args;
const ConsoleCommand ReadPinArgs("read_pin", "checks if SIM is unlocked", no_args, [&](ConsoleCommand *c){ const ConsoleCommand ReadPinArgs("read_pin", "checks if SIM is unlocked", no_args, [&](ConsoleCommand * c) {
bool pin_ok; bool pin_ok;
ESP_LOGI(TAG, "Checking pin..."); ESP_LOGI(TAG, "Checking pin...");
auto err = dce->read_pin(pin_ok); auto err = dce->read_pin(pin_ok);
if (err == command_result::OK) { if (err == command_result::OK) {
ESP_LOGI(TAG, "OK. Pin status: %s", pin_ok ? "true": "false"); ESP_LOGI(TAG, "OK. Pin status: %s", pin_ok ? "true" : "false");
} else { } else {
ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT":""); ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT" : "");
return 1; return 1;
} }
return 0; return 0;
}); });
const ConsoleCommand GetModuleName("get_module_name", "reads the module name", no_args, [&](ConsoleCommand *c){ const ConsoleCommand GetModuleName("get_module_name", "reads the module name", no_args, [&](ConsoleCommand * c) {
std::string module_name; std::string module_name;
ESP_LOGI(TAG, "Reading module name..."); ESP_LOGI(TAG, "Reading module name...");
CHECK_ERR(dce->get_module_name(module_name), ESP_LOGI(TAG, "OK. Module name: %s", module_name.c_str())); CHECK_ERR(dce->get_module_name(module_name), ESP_LOGI(TAG, "OK. Module name: %s", module_name.c_str()));
}); });
const ConsoleCommand GetOperatorName("get_operator_name", "reads the operator name", no_args, [&](ConsoleCommand *c){ const ConsoleCommand GetOperatorName("get_operator_name", "reads the operator name", no_args, [&](ConsoleCommand * c) {
std::string operator_name; std::string operator_name;
ESP_LOGI(TAG, "Reading operator name..."); ESP_LOGI(TAG, "Reading operator name...");
CHECK_ERR(dce->get_operator_name(operator_name), ESP_LOGI(TAG, "OK. Operator name: %s", operator_name.c_str())); CHECK_ERR(dce->get_operator_name(operator_name), ESP_LOGI(TAG, "OK. Operator name: %s", operator_name.c_str()));
@ -153,10 +153,10 @@ extern "C" void app_main(void)
CommandArgs pattern; CommandArgs pattern;
CommandArgs no_cr; CommandArgs no_cr;
} send_cmd_args; } send_cmd_args;
const ConsoleCommand SendCommand("cmd", "sends generic AT command, no_args", &send_cmd_args, sizeof(send_cmd_args), [&](ConsoleCommand *c) { const ConsoleCommand SendCommand("cmd", "sends generic AT command, no_args", &send_cmd_args, sizeof(send_cmd_args), [&](ConsoleCommand * c) {
auto cmd = c->get_string_of(&GenericCommandArgs::cmd); auto cmd = c->get_string_of(&GenericCommandArgs::cmd);
auto timeout = c->get_count_of(&GenericCommandArgs::timeout) ? c->get_int_of(&GenericCommandArgs::timeout) auto timeout = c->get_count_of(&GenericCommandArgs::timeout) ? c->get_int_of(&GenericCommandArgs::timeout)
: 1000; : 1000;
ESP_LOGI(TAG, "Sending command %s with timeout %d", cmd.c_str(), timeout); ESP_LOGI(TAG, "Sending command %s with timeout %d", cmd.c_str(), timeout);
auto pattern = c->get_string_of(&GenericCommandArgs::pattern); auto pattern = c->get_string_of(&GenericCommandArgs::pattern);
if (c->get_count_of(&GenericCommandArgs::no_cr) == 0) { if (c->get_count_of(&GenericCommandArgs::no_cr) == 0) {
@ -165,27 +165,29 @@ extern "C" void app_main(void)
CHECK_ERR(dce->command(cmd, [&](uint8_t *data, size_t len) { CHECK_ERR(dce->command(cmd, [&](uint8_t *data, size_t len) {
std::string response((char *) data, len); std::string response((char *) data, len);
ESP_LOGI(TAG, "%s", response.c_str()); ESP_LOGI(TAG, "%s", response.c_str());
if (pattern.empty() || response.find(pattern) != std::string::npos) if (pattern.empty() || response.find(pattern) != std::string::npos) {
return command_result::OK; return command_result::OK;
if (response.find(pattern) != std::string::npos) }
if (response.find(pattern) != std::string::npos) {
return command_result::OK; return command_result::OK;
}
return command_result::TIMEOUT; return command_result::TIMEOUT;
}, timeout),); }, timeout),);
}); });
const 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; int rssi, ber;
CHECK_ERR(dce->get_signal_quality(rssi, ber), ESP_LOGI(TAG, "OK. rssi=%d, ber=%d", rssi, ber)); CHECK_ERR(dce->get_signal_quality(rssi, ber), ESP_LOGI(TAG, "OK. rssi=%d, ber=%d", rssi, ber));
}); });
const ConsoleCommand GetBatteryStatus("get_battery_status", "Reads voltage/battery status", no_args, [&](ConsoleCommand *c){ const ConsoleCommand GetBatteryStatus("get_battery_status", "Reads voltage/battery status", no_args, [&](ConsoleCommand * c) {
int volt, bcl, bcs; int volt, bcl, bcs;
CHECK_ERR(dce->get_battery_status(volt, bcl, bcs), ESP_LOGI(TAG, "OK. volt=%d, bcl=%d, bcs=%d", volt, bcl, bcs)); CHECK_ERR(dce->get_battery_status(volt, bcl, bcs), ESP_LOGI(TAG, "OK. volt=%d, bcl=%d, bcs=%d", volt, bcl, bcs));
}); });
const ConsoleCommand PowerDown("power_down", "power down the module", no_args, [&](ConsoleCommand *c){ const ConsoleCommand PowerDown("power_down", "power down the module", no_args, [&](ConsoleCommand * c) {
ESP_LOGI(TAG, "Power down the module..."); ESP_LOGI(TAG, "Power down the module...");
CHECK_ERR(dce->power_down(), ESP_LOGI(TAG, "OK")); CHECK_ERR(dce->power_down(), ESP_LOGI(TAG, "OK"));
}); });
const ConsoleCommand Reset("reset", "reset the module", no_args, [&](ConsoleCommand *c){ const ConsoleCommand Reset("reset", "reset the module", no_args, [&](ConsoleCommand * c) {
ESP_LOGI(TAG, "Resetting the module..."); ESP_LOGI(TAG, "Resetting the module...");
CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK")); CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK"));
}); });
@ -193,7 +195,7 @@ extern "C" void app_main(void)
SetApn(): apn(STR1, nullptr, nullptr, "<apn>", "APN (Access Point Name)") {} SetApn(): apn(STR1, nullptr, nullptr, "<apn>", "APN (Access Point Name)") {}
CommandArgs apn; CommandArgs apn;
} set_apn; } set_apn;
const ConsoleCommand SetApnParser("set_apn", "sets APN", &set_apn, sizeof(set_apn), [&](ConsoleCommand *c){ const ConsoleCommand SetApnParser("set_apn", "sets APN", &set_apn, sizeof(set_apn), [&](ConsoleCommand * c) {
if (c->get_count_of(&SetApn::apn)) { if (c->get_count_of(&SetApn::apn)) {
auto apn = c->get_string_of(&SetApn::apn); auto apn = c->get_string_of(&SetApn::apn);
ESP_LOGI(TAG, "Setting the APN=%s...", apn.c_str()); ESP_LOGI(TAG, "Setting the APN=%s...", apn.c_str());
@ -205,7 +207,7 @@ extern "C" void app_main(void)
}); });
SignalGroup exit_signal; SignalGroup exit_signal;
const ConsoleCommand ExitConsole("exit", "exit the console application", no_args, [&](ConsoleCommand *c){ const ConsoleCommand ExitConsole("exit", "exit the console application", no_args, [&](ConsoleCommand * c) {
ESP_LOGI(TAG, "Exiting..."); ESP_LOGI(TAG, "Exiting...");
exit_signal.set(1); exit_signal.set(1);
s_repl->del(s_repl); s_repl->del(s_repl);

View File

@ -20,7 +20,7 @@
class MyShinyModem: public esp_modem::GenericModule { class MyShinyModem: public esp_modem::GenericModule {
using GenericModule::GenericModule; using GenericModule::GenericModule;
public: public:
esp_modem::command_result get_module_name(std::string& name) override esp_modem::command_result get_module_name(std::string &name) override
{ {
name = "Custom Shiny Module"; name = "Custom Shiny Module";
return esp_modem::command_result::OK; return esp_modem::command_result::OK;
@ -32,8 +32,8 @@ public:
* @return unique pointer of the resultant DCE * @return unique pointer of the resultant DCE
*/ */
std::unique_ptr<esp_modem::DCE> create_shiny_dce(const esp_modem::dce_config *config, std::unique_ptr<esp_modem::DCE> create_shiny_dce(const esp_modem::dce_config *config,
std::shared_ptr<esp_modem::DTE> dte, std::shared_ptr<esp_modem::DTE> dte,
esp_netif_t *netif) esp_netif_t *netif)
{ {
return esp_modem::dce_factory::Factory::build_unique<MyShinyModem>(config, std::move(dte), netif); return esp_modem::dce_factory::Factory::build_unique<MyShinyModem>(config, std::move(dte), netif);
} }

View File

@ -122,10 +122,10 @@ extern "C" void app_main(void)
event_handler.listen_to(MqttClient::get_event(MqttClient::Event::DATA)); event_handler.listen_to(MqttClient::get_event(MqttClient::Event::DATA));
auto reg = loop->register_event(MqttClient::get_event(MqttClient::Event::DATA), auto reg = loop->register_event(MqttClient::get_event(MqttClient::Event::DATA),
[&mqtt](const ESPEvent &event, void *data) { [&mqtt](const ESPEvent & event, void *data) {
std::cout << " TOPIC:" << mqtt.get_topic(data) << std::endl; std::cout << " TOPIC:" << mqtt.get_topic(data) << std::endl;
std::cout << " DATA:" << mqtt.get_data(data) << std::endl; std::cout << " DATA:" << mqtt.get_data(data) << std::endl;
}); });
mqtt.connect(); mqtt.connect();
while (true) { while (true) {
result = event_handler.wait_event_for(std::chrono::milliseconds(60000)); result = event_handler.wait_event_for(std::chrono::milliseconds(60000));

View File

@ -22,9 +22,8 @@ ESP_EVENT_DECLARE_BASE(MQTT_EVENTS);
/** /**
* Thin wrapper around C mqtt_client * Thin wrapper around C mqtt_client
*/ */
struct MqttClientHandle struct MqttClientHandle {
{ explicit MqttClientHandle(const std::string &uri)
explicit MqttClientHandle(const std::string & uri)
{ {
esp_mqtt_client_config_t config = { }; esp_mqtt_client_config_t config = { };
config.uri = uri.c_str(); config.uri = uri.c_str();
@ -49,9 +48,9 @@ struct MqttClientHandle
/** /**
* @brief Definitions of MqttClient methods * @brief Definitions of MqttClient methods
*/ */
MqttClient::MqttClient(const std::string & uri): MqttClient::MqttClient(const std::string &uri):
h(std::unique_ptr<MqttClientHandle>(new MqttClientHandle(uri))) h(std::unique_ptr<MqttClientHandle>(new MqttClientHandle(uri)))
{} {}
void MqttClient::connect() void MqttClient::connect()
{ {
@ -61,11 +60,11 @@ void MqttClient::connect()
idf::event::ESPEvent MqttClient::get_event(MqttClient::Event ev) idf::event::ESPEvent MqttClient::get_event(MqttClient::Event ev)
{ {
switch (ev) { switch (ev) {
case Event::CONNECT: { case Event::CONNECT: {
return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_CONNECTED) }; return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_CONNECTED) };
} }
case Event::DATA: case Event::DATA:
return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_DATA) }; return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_DATA) };
} }
return { }; return { };
} }
@ -80,7 +79,7 @@ int MqttClient::subscribe(const std::string &topic, int qos)
return esp_mqtt_client_subscribe(h->client, topic.c_str(), qos); return esp_mqtt_client_subscribe(h->client, topic.c_str(), qos);
} }
std::string MqttClient::get_topic(void * event_data) std::string MqttClient::get_topic(void *event_data)
{ {
auto event = (esp_mqtt_event_handle_t)event_data; auto event = (esp_mqtt_event_handle_t)event_data;
if (event == nullptr || event->client != h->client) if (event == nullptr || event->client != h->client)
@ -89,7 +88,7 @@ std::string MqttClient::get_topic(void * event_data)
return std::string(event->topic, event->topic_len); return std::string(event->topic, event->topic_len);
} }
std::string MqttClient::get_data(void * event_data) std::string MqttClient::get_data(void *event_data)
{ {
auto event = (esp_mqtt_event_handle_t)event_data; auto event = (esp_mqtt_event_handle_t)event_data;
if (event == nullptr || event->client != h->client) if (event == nullptr || event->client != h->client)

View File

@ -24,7 +24,7 @@ public:
DATA, DATA,
}; };
explicit MqttClient(const std::string & uri); explicit MqttClient(const std::string &uri);
~MqttClient(); ~MqttClient();
/** /**
@ -39,7 +39,7 @@ public:
* @param qos QoS (0 by default) * @param qos QoS (0 by default)
* @return message id * @return message id
*/ */
int publish(const std::string & topic, const std::string & data, int qos = 0); int publish(const std::string &topic, const std::string &data, int qos = 0);
/** /**
* @brief Subscribe to a topic * @brief Subscribe to a topic
@ -47,7 +47,7 @@ public:
* @param qos QoS (0 by default) * @param qos QoS (0 by default)
* @return message id * @return message id
*/ */
int subscribe(const std::string & topic, int qos = 0); int subscribe(const std::string &topic, int qos = 0);
/** /**
* @brief Get topic from event data * @brief Get topic from event data

View File

@ -55,7 +55,7 @@ class CMuxInstance;
class CMux { class CMux {
public: public:
explicit CMux(std::unique_ptr<Terminal> t, std::unique_ptr<uint8_t[]> b, size_t buff_size): 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)), payload_start(nullptr), total_payload_size(0) {} term(std::move(t)), buffer_size(buff_size), buffer(std::move(b)), payload_start(nullptr), total_payload_size(0) {}
~CMux() = default; ~CMux() = default;
[[nodiscard]] bool init(); [[nodiscard]] bool init();
void set_read_cb(int inst, std::function<bool(uint8_t *data, size_t len)> f); void set_read_cb(int inst, std::function<bool(uint8_t *data, size_t len)> f);
@ -92,9 +92,18 @@ class CMuxInstance: public Terminal {
public: public:
explicit CMuxInstance(std::shared_ptr<CMux> parent, int i): cmux(std::move(parent)), instance(i) {} explicit CMuxInstance(std::shared_ptr<CMux> parent, int i): cmux(std::move(parent)), instance(i) {}
int write(uint8_t *data, size_t len) override { return cmux->write(instance, data, len); } int write(uint8_t *data, size_t len) override
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override { return cmux->set_read_cb(instance, std::move(f)); } {
int read(uint8_t *data, size_t len) override { return 0; } return cmux->write(instance, data, len);
}
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override
{
return cmux->set_read_cb(instance, std::move(f));
}
int read(uint8_t *data, size_t len) override
{
return 0;
}
void start() override { } void start() override { }
void stop() override { } void stop() override { }
private: private:

View File

@ -36,17 +36,17 @@ namespace dce_commands {
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \ #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
return_type name(CommandableIf *t, ## __VA_ARGS__); return_type name(CommandableIf *t, ## __VA_ARGS__);
DECLARE_ALL_COMMAND_APIS(declare name(Commandable *p, ...);) DECLARE_ALL_COMMAND_APIS(declare name(Commandable *p, ...);)
#undef ESP_MODEM_DECLARE_DCE_COMMAND #undef ESP_MODEM_DECLARE_DCE_COMMAND
/** /**
* @brief Following commands that are different for some specific modules * @brief Following commands that are different for some specific modules
*/ */
command_result get_battery_status_sim7xxx(CommandableIf* t, int& voltage, int &bcs, int &bcl); command_result get_battery_status_sim7xxx(CommandableIf *t, int &voltage, int &bcs, int &bcl);
command_result power_down_sim7xxx(CommandableIf* t); command_result power_down_sim7xxx(CommandableIf *t);
command_result power_down_sim8xx(CommandableIf* t); command_result power_down_sim8xx(CommandableIf *t);
command_result set_data_mode_sim8xx(CommandableIf* t); command_result set_data_mode_sim8xx(CommandableIf *t);
/** /**
* @} * @}

View File

@ -52,8 +52,8 @@ template<class SpecificModule>
class DCE_T { class DCE_T {
static_assert(std::is_base_of<ModuleIf, SpecificModule>::value, "DCE must be instantiated with Module class only"); static_assert(std::is_base_of<ModuleIf, SpecificModule>::value, "DCE must be instantiated with Module class only");
public: public:
explicit DCE_T(const std::shared_ptr<DTE>& dte, std::shared_ptr<SpecificModule> dev, esp_netif_t * netif): explicit DCE_T(const std::shared_ptr<DTE> &dte, std::shared_ptr<SpecificModule> dev, esp_netif_t *netif):
dte(dte), device(std::move(dev)), netif(dte, netif) dte(dte), device(std::move(dev)), netif(dte, netif)
{ } { }
~DCE_T() = default; ~DCE_T() = default;
@ -61,20 +61,35 @@ public:
/** /**
* @brief Set data mode! * @brief Set data mode!
*/ */
void set_data() { set_mode(modem_mode::DATA_MODE); } void set_data()
{
set_mode(modem_mode::DATA_MODE);
}
void exit_data() { set_mode(modem_mode::COMMAND_MODE); } void exit_data()
{
set_mode(modem_mode::COMMAND_MODE);
}
void set_cmux() { set_mode(modem_mode::CMUX_MODE); } void set_cmux()
{
set_mode(modem_mode::CMUX_MODE);
}
SpecificModule* get_module() { return device.get(); } SpecificModule *get_module()
{
return device.get();
}
command_result command(const std::string& command, got_line_cb got_line, uint32_t time_ms) command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms)
{ {
return dte->command(command, std::move(got_line), time_ms); return dte->command(command, std::move(got_line), time_ms);
} }
bool set_mode(modem_mode m) { return mode.set(dte.get(), device.get(), netif, m); } bool set_mode(modem_mode m)
{
return mode.set(dte.get(), device.get(), netif, m);
}
protected: protected:
std::shared_ptr<DTE> dte; std::shared_ptr<DTE> dte;
@ -98,7 +113,10 @@ public:
return device->name(std::forward<Agrs>(args)...); \ return device->name(std::forward<Agrs>(args)...); \
} }
DECLARE_ALL_COMMAND_APIS(forwards name(...) { device->name(...); } ) DECLARE_ALL_COMMAND_APIS(forwards name(...)
{
device->name(...);
} )
#undef ESP_MODEM_DECLARE_DCE_COMMAND #undef ESP_MODEM_DECLARE_DCE_COMMAND

View File

@ -38,19 +38,19 @@ public:
static std::unique_ptr<PdpContext> create_pdp_context(std::string &apn); static std::unique_ptr<PdpContext> create_pdp_context(std::string &apn);
template <typename T, typename T_Ptr, typename ...Args> template <typename T, typename T_Ptr, typename ...Args>
static auto make(Args&&... args) -> typename std::enable_if<std::is_same<T_Ptr, T*>::value, T*>::type static auto make(Args &&... args) -> typename std::enable_if<std::is_same<T_Ptr, T *>::value, T *>::type
{ {
return new T(std::forward<Args>(args)...); return new T(std::forward<Args>(args)...);
} }
template <typename T, typename T_Ptr, typename ...Args> template <typename T, typename T_Ptr, typename ...Args>
static auto make(Args&&... args) -> typename std::enable_if<std::is_same<T_Ptr, std::shared_ptr<T>>::value, std::shared_ptr<T>>::type static auto make(Args &&... args) -> typename std::enable_if<std::is_same<T_Ptr, std::shared_ptr<T>>::value, std::shared_ptr<T>>::type
{ {
return std::make_shared<T>(std::forward<Args>(args)...); return std::make_shared<T>(std::forward<Args>(args)...);
} }
template <typename T, typename T_Ptr = std::unique_ptr<T>, typename ...Args> template <typename T, typename T_Ptr = std::unique_ptr<T>, typename ...Args>
static auto make(Args&&... args) -> typename std::enable_if<std::is_same<T_Ptr, std::unique_ptr<T>>::value, std::unique_ptr<T>>::type static auto make(Args && ... args) -> typename std::enable_if<std::is_same<T_Ptr, std::unique_ptr<T>>::value, std::unique_ptr<T>>::type
{ {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
} }
@ -67,12 +67,12 @@ template<typename T_Module>
class Builder { class Builder {
static_assert(std::is_base_of<ModuleIf, T_Module>::value, "Builder must be used only for Module classes"); static_assert(std::is_base_of<ModuleIf, T_Module>::value, "Builder must be used only for Module classes");
public: public:
Builder(std::shared_ptr<DTE> dte, esp_netif_t* esp_netif): dte(std::move(dte)), device(nullptr), netif(esp_netif) Builder(std::shared_ptr<DTE> dte, esp_netif_t *esp_netif): dte(std::move(dte)), device(nullptr), netif(esp_netif)
{ {
throw_if_false(netif != nullptr, "Null netif"); throw_if_false(netif != nullptr, "Null netif");
} }
Builder(std::shared_ptr<DTE> dte, esp_netif_t* esp_netif, std::shared_ptr<T_Module> dev): dte(std::move(dte)), device(std::move(dev)), netif(esp_netif) Builder(std::shared_ptr<DTE> dte, esp_netif_t *esp_netif, std::shared_ptr<T_Module> dev): dte(std::move(dte)), device(std::move(dev)), netif(esp_netif)
{ {
throw_if_false(netif != nullptr, "Null netif"); throw_if_false(netif != nullptr, "Null netif");
} }
@ -93,12 +93,14 @@ public:
template<typename T_Dce, typename T_Ptr> template<typename T_Dce, typename T_Ptr>
auto create(const esp_modem_dce_config *config) -> T_Ptr auto create(const esp_modem_dce_config *config) -> T_Ptr
{ {
if (dte == nullptr) if (dte == nullptr) {
return nullptr; return nullptr;
}
if (device == nullptr) { if (device == nullptr) {
device = create_module<decltype(device)>(config); device = create_module<decltype(device)>(config);
if (device == nullptr) if (device == nullptr) {
return nullptr; return nullptr;
}
} }
return FactoryHelper::make<T_Dce, T_Ptr>(std::move(dte), std::move(device), netif); return FactoryHelper::make<T_Dce, T_Ptr>(std::move(dte), std::move(device), netif);
} }
@ -136,7 +138,7 @@ public:
* @return unique_ptr DCE of the created DCE on success * @return unique_ptr DCE of the created DCE on success
*/ */
template <typename T_Module, typename ...Args> template <typename T_Module, typename ...Args>
static std::unique_ptr<DCE> build_unique(const config *cfg, Args&&... args) static std::unique_ptr<DCE> build_unique(const config *cfg, Args &&... args)
{ {
return build_generic_DCE<T_Module, DCE, std::unique_ptr<DCE>>(cfg, std::forward<Args>(args)...); return build_generic_DCE<T_Module, DCE, std::unique_ptr<DCE>>(cfg, std::forward<Args>(args)...);
} }
@ -150,33 +152,33 @@ public:
* @return DCE pointer the created DCE on success * @return DCE pointer the created DCE on success
*/ */
template <typename T_Module, typename ...Args> template <typename T_Module, typename ...Args>
static DCE* build(const config *cfg, Args&&... args) static DCE *build(const config *cfg, Args &&... args)
{ {
return build_generic_DCE<T_Module, DCE>(cfg, std::forward<Args>(args)...); return build_generic_DCE<T_Module, DCE>(cfg, std::forward<Args>(args)...);
} }
template <typename T_Module, typename ...Args> template <typename T_Module, typename ...Args>
static std::shared_ptr<T_Module> build_shared_module(const config *cfg, Args&&... args) static std::shared_ptr<T_Module> build_shared_module(const config *cfg, Args &&... args)
{ {
return build_module_T<T_Module>(cfg, std::forward<Args>(args)...); return build_module_T<T_Module>(cfg, std::forward<Args>(args)...);
} }
template <typename ...Args> template <typename ...Args>
std::shared_ptr<GenericModule> build_shared_module(const config *cfg, Args&&... args) std::shared_ptr<GenericModule> build_shared_module(const config *cfg, Args &&... args)
{ {
switch (m) { switch (m) {
case ModemType::SIM800: case ModemType::SIM800:
return build_shared_module<SIM800>(cfg, std::forward<Args>(args)...); return build_shared_module<SIM800>(cfg, std::forward<Args>(args)...);
case ModemType::SIM7600: case ModemType::SIM7600:
return build_shared_module<SIM7600>(cfg, std::forward<Args>(args)...); return build_shared_module<SIM7600>(cfg, std::forward<Args>(args)...);
case ModemType::BG96: case ModemType::BG96:
return build_shared_module<BG96>(cfg, std::forward<Args>(args)...); return build_shared_module<BG96>(cfg, std::forward<Args>(args)...);
case ModemType::GenericModule: case ModemType::GenericModule:
return build_shared_module<GenericModule>(cfg, std::forward<Args>(args)...); return build_shared_module<GenericModule>(cfg, std::forward<Args>(args)...);
default: default:
break; break;
} }
return nullptr; return nullptr;
} }
@ -189,37 +191,37 @@ public:
* @return unique_ptr DCE of the created DCE on success * @return unique_ptr DCE of the created DCE on success
*/ */
template <typename ...Args> template <typename ...Args>
std::unique_ptr<DCE> build_unique(const config *cfg, Args&&... args) std::unique_ptr<DCE> build_unique(const config *cfg, Args &&... args)
{ {
switch (m) { switch (m) {
case ModemType::SIM800: case ModemType::SIM800:
return build_unique<SIM800>(cfg, std::forward<Args>(args)...); return build_unique<SIM800>(cfg, std::forward<Args>(args)...);
case ModemType::SIM7600: case ModemType::SIM7600:
return build_unique<SIM7600>(cfg, std::forward<Args>(args)...); return build_unique<SIM7600>(cfg, std::forward<Args>(args)...);
case ModemType::BG96: case ModemType::BG96:
return build_unique<BG96>(cfg, std::forward<Args>(args)...); return build_unique<BG96>(cfg, std::forward<Args>(args)...);
case ModemType::GenericModule: case ModemType::GenericModule:
return build_unique<GenericModule>(cfg, std::forward<Args>(args)...); return build_unique<GenericModule>(cfg, std::forward<Args>(args)...);
default: default:
break; break;
} }
return nullptr; return nullptr;
} }
template <typename ...Args> template <typename ...Args>
DCE* build(const config *cfg, Args&&... args) DCE *build(const config *cfg, Args &&... args)
{ {
switch (m) { switch (m) {
case ModemType::SIM800: case ModemType::SIM800:
return build<SIM800>(cfg, std::forward<Args>(args)...); return build<SIM800>(cfg, std::forward<Args>(args)...);
case ModemType::SIM7600: case ModemType::SIM7600:
return build<SIM7600>(cfg, std::forward<Args>(args)...); return build<SIM7600>(cfg, std::forward<Args>(args)...);
case ModemType::BG96: case ModemType::BG96:
return build<BG96>(cfg, std::forward<Args>(args)...); return build<BG96>(cfg, std::forward<Args>(args)...);
case ModemType::GenericModule: case ModemType::GenericModule:
return build<GenericModule>(cfg, std::forward<Args>(args)...); return build<GenericModule>(cfg, std::forward<Args>(args)...);
default: default:
break; break;
} }
return nullptr; return nullptr;
} }
@ -229,15 +231,15 @@ private:
protected: protected:
template <typename T_Module, typename Ptr = std::shared_ptr<T_Module>, typename ...Args> template <typename T_Module, typename Ptr = std::shared_ptr<T_Module>, typename ...Args>
static Ptr build_module_T(const config *cfg, Args&&... args) static Ptr build_module_T(const config *cfg, Args && ... args)
{ {
Builder<T_Module> b(std::forward<Args>(args)...); Builder<T_Module> b(std::forward<Args>(args)...);
return b.template create_module<Ptr>(cfg); return b.template create_module<Ptr>(cfg);
} }
template <typename T_Module, typename T_Dce = DCE_T<T_Module>, typename T_DcePtr = T_Dce*, typename ...Args> template <typename T_Module, typename T_Dce = DCE_T<T_Module>, typename T_DcePtr = T_Dce *, typename ...Args>
static auto build_generic_DCE(const config *cfg, Args&&... args) -> T_DcePtr static auto build_generic_DCE(const config *cfg, Args && ... args) -> T_DcePtr
{ {
Builder<T_Module> b(std::forward<Args>(args)...); Builder<T_Module> b(std::forward<Args>(args)...);
return b.template create<T_Dce, T_DcePtr>(cfg); return b.template create<T_Dce, T_DcePtr>(cfg);

View File

@ -47,8 +47,8 @@ public:
* The configuration could be either the dce-config struct or just a pdp context * The configuration could be either the dce-config struct or just a pdp context
*/ */
explicit GenericModule(std::shared_ptr<DTE> dte, std::unique_ptr<PdpContext> pdp): explicit GenericModule(std::shared_ptr<DTE> dte, std::unique_ptr<PdpContext> pdp):
dte(std::move(dte)), pdp(std::move(pdp)) {} dte(std::move(dte)), pdp(std::move(pdp)) {}
explicit GenericModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config* config); explicit GenericModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config *config);
/** /**
* @brief This is a mandatory method for ModuleIf class, which sets up the device * @brief This is a mandatory method for ModuleIf class, which sets up the device
@ -58,10 +58,12 @@ public:
*/ */
bool setup_data_mode() override bool setup_data_mode() override
{ {
if (set_echo(false) != command_result::OK) if (set_echo(false) != command_result::OK) {
return false; return false;
if (set_pdp_context(*pdp) != command_result::OK) }
if (set_pdp_context(*pdp) != command_result::OK) {
return false; return false;
}
return true; return true;
} }
@ -72,8 +74,9 @@ public:
bool set_mode(modem_mode mode) override bool set_mode(modem_mode mode) override
{ {
if (mode == modem_mode::DATA_MODE) { if (mode == modem_mode::DATA_MODE) {
if (set_data_mode() != command_result::OK) if (set_data_mode() != command_result::OK) {
return resume_data_mode() == command_result::OK; return resume_data_mode() == command_result::OK;
}
return true; return true;
} else if (mode == modem_mode::COMMAND_MODE) { } else if (mode == modem_mode::COMMAND_MODE) {
return set_command_mode() == command_result::OK; return set_command_mode() == command_result::OK;
@ -115,8 +118,8 @@ protected:
class SIM7600: public GenericModule { class SIM7600: public GenericModule {
using GenericModule::GenericModule; using GenericModule::GenericModule;
public: public:
command_result get_module_name(std::string& name) override; command_result get_module_name(std::string &name) override;
command_result get_battery_status(int& voltage, int &bcs, int &bcl) override; command_result get_battery_status(int &voltage, int &bcs, int &bcl) override;
command_result power_down() override; command_result power_down() override;
}; };
@ -126,7 +129,7 @@ public:
class SIM800: public GenericModule { class SIM800: public GenericModule {
using GenericModule::GenericModule; using GenericModule::GenericModule;
public: public:
command_result get_module_name(std::string& name) override; command_result get_module_name(std::string &name) override;
command_result power_down() override; command_result power_down() override;
command_result set_data_mode() override; command_result set_data_mode() override;
}; };
@ -137,7 +140,7 @@ public:
class BG96: public GenericModule { class BG96: public GenericModule {
using GenericModule::GenericModule; using GenericModule::GenericModule;
public: public:
command_result get_module_name(std::string& name) override; command_result get_module_name(std::string &name) override;
}; };
/** /**

View File

@ -26,9 +26,13 @@ public:
explicit esp_err_exception(esp_err_t err): esp_err(err) {} explicit esp_err_exception(esp_err_t err): esp_err(err) {}
explicit esp_err_exception(std::string msg): esp_err(ESP_FAIL), message(std::move(msg)) {} explicit esp_err_exception(std::string msg): esp_err(ESP_FAIL), message(std::move(msg)) {}
explicit esp_err_exception(std::string msg, esp_err_t err): esp_err(err), message(std::move(msg)) {} explicit esp_err_exception(std::string msg, esp_err_t err): esp_err(err), message(std::move(msg)) {}
virtual esp_err_t get_err_t() { return esp_err; } virtual esp_err_t get_err_t()
{
return esp_err;
}
~esp_err_exception() noexcept override = default; ~esp_err_exception() noexcept override = default;
virtual const char* what() const noexcept { virtual const char *what() const noexcept
{
return message.c_str(); return message.c_str();
} }
private: private:

View File

@ -73,7 +73,7 @@ private:
std::shared_ptr<DTE> ppp_dte; std::shared_ptr<DTE> ppp_dte;
esp_netif_t *netif; esp_netif_t *netif;
struct ppp_netif_driver driver{}; struct ppp_netif_driver driver {};
SignalGroup signal; SignalGroup signal;
static const size_t PPP_STARTED = SignalGroup::bit0; static const size_t PPP_STARTED = SignalGroup::bit0;
static const size_t PPP_EXIT = SignalGroup::bit1; static const size_t PPP_EXIT = SignalGroup::bit1;

View File

@ -24,7 +24,7 @@
#else #else
// forward declarations of FreeRTOS primitives // forward declarations of FreeRTOS primitives
struct QueueDefinition; struct QueueDefinition;
typedef void * EventGroupHandle_t; typedef void *EventGroupHandle_t;
#endif #endif
@ -32,7 +32,7 @@ namespace esp_modem {
// Forward declaration for both linux/FreeRTOS targets // Forward declaration for both linux/FreeRTOS targets
// //
using TaskFunction_t = void (*)(void*); using TaskFunction_t = void (*)(void *);
#if !defined(CONFIG_IDF_TARGET_LINUX) #if !defined(CONFIG_IDF_TARGET_LINUX)
struct Lock { struct Lock {
using MutexT = QueueHandle_t; using MutexT = QueueHandle_t;
@ -56,11 +56,17 @@ static constexpr uint32_t portMAX_DELAY = UINT32_MAX;
template<class T> template<class T>
class Scoped { class Scoped {
public: public:
explicit Scoped(T &l):lock(l) { lock.lock(); } explicit Scoped(T &l): lock(l)
~Scoped() { lock.unlock(); } {
lock.lock();
}
~Scoped()
{
lock.unlock();
}
private: private:
T& lock; T &lock;
}; };
class Task { class Task {

View File

@ -50,9 +50,15 @@ class Terminal {
public: public:
virtual ~Terminal() = default; virtual ~Terminal() = default;
void set_error_cb(std::function<void(terminal_error)> f) { on_error = std::move(f); } void set_error_cb(std::function<void(terminal_error)> f)
{
on_error = std::move(f);
}
virtual void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) { on_read = std::move(f); } virtual void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f)
{
on_read = std::move(f);
}
/** /**
* @brief Writes data to the terminal * @brief Writes data to the terminal

View File

@ -37,7 +37,7 @@
* @brief UART init struct for VFS * @brief UART init struct for VFS
*/ */
struct esp_modem_vfs_uart_creator { struct esp_modem_vfs_uart_creator {
const char* dev_name; /*!< VFS device name, e.g. /dev/uart/n */ const char *dev_name; /*!< VFS device name, e.g. /dev/uart/n */
const struct esp_modem_uart_term_config uart; /*!< UART driver init struct */ const struct esp_modem_uart_term_config uart; /*!< UART driver init struct */
}; };
@ -45,7 +45,7 @@ struct esp_modem_vfs_uart_creator {
* @brief UART init struct for VFS * @brief UART init struct for VFS
*/ */
struct esp_modem_vfs_socket_creator { struct esp_modem_vfs_socket_creator {
const char* host_name; /*!< VFS socket: host name (or IP address) */ const char *host_name; /*!< VFS socket: host name (or IP address) */
int port; /*!< VFS socket: port number */ int port; /*!< VFS socket: port number */
}; };

View File

@ -35,8 +35,7 @@ class NetifStorage;
void read_task(NetifStorage *netif); void read_task(NetifStorage *netif);
class NetifStorage: public esp_netif_obj class NetifStorage: public esp_netif_obj {
{
public: public:
explicit NetifStorage(const esp_netif_config_t *config) : esp_netif_obj(), exit(false) explicit NetifStorage(const esp_netif_config_t *config) : esp_netif_obj(), exit(false)
{ {
@ -132,5 +131,5 @@ extern "C" esp_netif_t *esp_netif_new(const esp_netif_config_t *config)
void esp_netif_destroy(esp_netif_t *netif) void esp_netif_destroy(esp_netif_t *netif)
{ {
delete static_cast<NetifStorage*>(netif); delete static_cast<NetifStorage *>(netif);
} }

View File

@ -25,7 +25,7 @@ namespace esp_modem {
* @brief Uart Resource is a platform specific struct which is implemented separately for ESP_PLATFORM and linux target * @brief Uart Resource is a platform specific struct which is implemented separately for ESP_PLATFORM and linux target
*/ */
struct uart_resource { struct uart_resource {
explicit uart_resource(const esp_modem_uart_term_config *config, QueueHandle_t* event_queue, int fd); explicit uart_resource(const esp_modem_uart_term_config *config, QueueHandle_t *event_queue, int fd);
~uart_resource(); ~uart_resource();

View File

@ -30,42 +30,49 @@ struct PdpContext;
static const char *TAG = "modem_api"; static const char *TAG = "modem_api";
#endif #endif
std::shared_ptr<DTE> create_uart_dte(const dte_config *config) { std::shared_ptr<DTE> create_uart_dte(const dte_config *config)
{
TRY_CATCH_RET_NULL( TRY_CATCH_RET_NULL(
auto term = create_uart_terminal(config); auto term = create_uart_terminal(config);
return std::make_shared<DTE>(config, std::move(term)); return std::make_shared<DTE>(config, std::move(term));
) )
} }
std::shared_ptr<DTE> create_vfs_dte(const dte_config *config) { std::shared_ptr<DTE> create_vfs_dte(const dte_config *config)
{
TRY_CATCH_RET_NULL( TRY_CATCH_RET_NULL(
auto term = create_vfs_terminal(config); auto term = create_vfs_terminal(config);
return std::make_shared<DTE>(config, std::move(term)); return std::make_shared<DTE>(config, std::move(term));
) )
} }
static inline std::unique_ptr<DCE> static inline std::unique_ptr<DCE>
create_modem_dce(dce_factory::ModemType m, const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) { create_modem_dce(dce_factory::ModemType m, const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
{
dce_factory::Factory f(m); dce_factory::Factory f(m);
TRY_CATCH_RET_NULL( TRY_CATCH_RET_NULL(
return f.build_unique(config, std::move(dte), netif); return f.build_unique(config, std::move(dte), netif);
) )
} }
std::unique_ptr<DCE> create_SIM7600_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) { std::unique_ptr<DCE> create_SIM7600_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
{
return create_modem_dce(dce_factory::ModemType::SIM7600, config, std::move(dte), netif); return create_modem_dce(dce_factory::ModemType::SIM7600, config, std::move(dte), netif);
} }
std::unique_ptr<DCE> create_SIM800_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) { std::unique_ptr<DCE> create_SIM800_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
{
return create_modem_dce(dce_factory::ModemType::SIM800, config, std::move(dte), netif); return create_modem_dce(dce_factory::ModemType::SIM800, config, std::move(dte), netif);
} }
std::unique_ptr<DCE> create_BG96_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) { std::unique_ptr<DCE> create_BG96_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
{
return create_modem_dce(dce_factory::ModemType::BG96, config, std::move(dte), netif); return create_modem_dce(dce_factory::ModemType::BG96, config, std::move(dte), netif);
} }
std::unique_ptr<DCE> create_generic_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif) { std::unique_ptr<DCE> create_generic_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
{
return create_modem_dce(dce_factory::ModemType::GenericModule, config, std::move(dte), netif); return create_modem_dce(dce_factory::ModemType::GenericModule, config, std::move(dte), netif);
} }

View File

@ -27,22 +27,21 @@
// C API definitions // C API definitions
using namespace esp_modem; using namespace esp_modem;
struct esp_modem_dce_wrap // need to mimic the polymorphic dispatch as CPP uses templated dispatch struct esp_modem_dce_wrap { // need to mimic the polymorphic dispatch as CPP uses templated dispatch
{
enum class modem_wrap_dte_type { UART, } dte_type; enum class modem_wrap_dte_type { UART, } dte_type;
dce_factory::ModemType modem_type; dce_factory::ModemType modem_type;
DCE* dce; DCE *dce;
}; };
static inline esp_err_t command_response_to_esp_err(command_result res) static inline esp_err_t command_response_to_esp_err(command_result res)
{ {
switch (res) { switch (res) {
case command_result::OK: case command_result::OK:
return ESP_OK; return ESP_OK;
case command_result::FAIL: case command_result::FAIL:
return ESP_FAIL; return ESP_FAIL;
case command_result::TIMEOUT: case command_result::TIMEOUT:
return ESP_ERR_TIMEOUT; return ESP_ERR_TIMEOUT;
} }
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
@ -50,23 +49,24 @@ static inline esp_err_t command_response_to_esp_err(command_result res)
static inline dce_factory::ModemType convert_modem_enum(esp_modem_dce_device_t module) static inline dce_factory::ModemType convert_modem_enum(esp_modem_dce_device_t module)
{ {
switch (module) { switch (module) {
case ESP_MODEM_DCE_SIM7600: case ESP_MODEM_DCE_SIM7600:
return esp_modem::dce_factory::ModemType::SIM7600; return esp_modem::dce_factory::ModemType::SIM7600;
case ESP_MODEM_DCE_BG96: case ESP_MODEM_DCE_BG96:
return esp_modem::dce_factory::ModemType::BG96; return esp_modem::dce_factory::ModemType::BG96;
case ESP_MODEM_DCE_SIM800: case ESP_MODEM_DCE_SIM800:
return esp_modem::dce_factory::ModemType::SIM800; return esp_modem::dce_factory::ModemType::SIM800;
default: default:
case ESP_MODEM_DCE_GENETIC: case ESP_MODEM_DCE_GENETIC:
return esp_modem::dce_factory::ModemType::GenericModule; return esp_modem::dce_factory::ModemType::GenericModule;
} }
} }
extern "C" esp_modem_dce_t *esp_modem_new_dev(esp_modem_dce_device_t module, const esp_modem_dte_config_t *dte_config, const esp_modem_dce_config_t *dce_config, esp_netif_t *netif) extern "C" esp_modem_dce_t *esp_modem_new_dev(esp_modem_dce_device_t module, const esp_modem_dte_config_t *dte_config, const esp_modem_dce_config_t *dce_config, esp_netif_t *netif)
{ {
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) {
return nullptr; return nullptr;
}
auto dte = create_uart_dte(dte_config); auto dte = create_uart_dte(dte_config);
if (dte == nullptr) { if (dte == nullptr) {
delete dce_wrap; delete dce_wrap;
@ -88,7 +88,7 @@ extern "C" esp_modem_dce_t *esp_modem_new(const esp_modem_dte_config_t *dte_conf
return esp_modem_new_dev(ESP_MODEM_DCE_GENETIC, dte_config, dce_config, netif); return esp_modem_new_dev(ESP_MODEM_DCE_GENETIC, dte_config, dce_config, netif);
} }
extern "C" void esp_modem_destroy(esp_modem_dce_t * dce_wrap) extern "C" void esp_modem_destroy(esp_modem_dce_t *dce_wrap)
{ {
if (dce_wrap) { if (dce_wrap) {
delete dce_wrap->dce; delete dce_wrap->dce;
@ -96,10 +96,11 @@ extern "C" void esp_modem_destroy(esp_modem_dce_t * dce_wrap)
} }
} }
extern "C" esp_err_t esp_modem_set_mode(esp_modem_dce_t * dce_wrap, esp_modem_dce_mode_t mode) extern "C" esp_err_t esp_modem_set_mode(esp_modem_dce_t *dce_wrap, esp_modem_dce_mode_t mode)
{ {
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
}
if (mode == ESP_MODEM_MODE_DATA) { if (mode == ESP_MODEM_MODE_DATA) {
dce_wrap->dce->set_data(); dce_wrap->dce->set_data();
} else if (mode == ESP_MODEM_MODE_COMMAND) { } else if (mode == ESP_MODEM_MODE_COMMAND) {
@ -110,58 +111,65 @@ extern "C" esp_err_t esp_modem_set_mode(esp_modem_dce_t * dce_wrap, esp_modem_dc
return ESP_OK; return ESP_OK;
} }
extern "C" esp_err_t esp_modem_read_pin(esp_modem_dce_t * dce_wrap, bool *pin) extern "C" esp_err_t esp_modem_read_pin(esp_modem_dce_t *dce_wrap, bool *pin)
{ {
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
}
return command_response_to_esp_err(dce_wrap->dce->read_pin(*pin)); return command_response_to_esp_err(dce_wrap->dce->read_pin(*pin));
} }
extern "C" esp_err_t esp_modem_sms_txt_mode(esp_modem_dce_t * dce_wrap, bool txt) extern "C" esp_err_t esp_modem_sms_txt_mode(esp_modem_dce_t *dce_wrap, bool txt)
{ {
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
}
return command_response_to_esp_err(dce_wrap->dce->sms_txt_mode(txt)); return command_response_to_esp_err(dce_wrap->dce->sms_txt_mode(txt));
} }
extern "C" esp_err_t esp_modem_send_sms(esp_modem_dce_t * dce_wrap, const char * number, const char * message) extern "C" esp_err_t esp_modem_send_sms(esp_modem_dce_t *dce_wrap, const char *number, const char *message)
{ {
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
}
std::string number_str(number); std::string number_str(number);
std::string message_str(message); std::string message_str(message);
return command_response_to_esp_err(dce_wrap->dce->send_sms(number_str, message_str)); return command_response_to_esp_err(dce_wrap->dce->send_sms(number_str, message_str));
} }
extern "C" esp_err_t esp_modem_sms_character_set(esp_modem_dce_t * dce_wrap) extern "C" esp_err_t esp_modem_sms_character_set(esp_modem_dce_t *dce_wrap)
{ {
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
}
return command_response_to_esp_err(dce_wrap->dce->sms_character_set()); return command_response_to_esp_err(dce_wrap->dce->sms_character_set());
} }
extern "C" esp_err_t esp_modem_set_pin(esp_modem_dce_t * dce_wrap, const char *pin) extern "C" esp_err_t esp_modem_set_pin(esp_modem_dce_t *dce_wrap, const char *pin)
{ {
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
}
std::string pin_str(pin); std::string pin_str(pin);
return command_response_to_esp_err(dce_wrap->dce->set_pin(pin_str)); return command_response_to_esp_err(dce_wrap->dce->set_pin(pin_str));
} }
extern "C" esp_err_t esp_modem_get_signal_quality(esp_modem_dce_t * dce_wrap, int *rssi, int *ber) extern "C" esp_err_t esp_modem_get_signal_quality(esp_modem_dce_t *dce_wrap, int *rssi, int *ber)
{ {
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
}
return command_response_to_esp_err(dce_wrap->dce->get_signal_quality(*rssi, *ber)); return command_response_to_esp_err(dce_wrap->dce->get_signal_quality(*rssi, *ber));
} }
extern "C" esp_err_t esp_modem_get_imsi(esp_modem_dce_t * dce_wrap, char *p_imsi) extern "C" esp_err_t esp_modem_get_imsi(esp_modem_dce_t *dce_wrap, char *p_imsi)
{ {
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
}
std::string imsi; std::string imsi;
auto ret = command_response_to_esp_err(dce_wrap->dce->get_imsi(imsi)); auto ret = command_response_to_esp_err(dce_wrap->dce->get_imsi(imsi));
if (ret == ESP_OK && !imsi.empty()) { if (ret == ESP_OK && !imsi.empty()) {

View File

@ -139,114 +139,114 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
#endif #endif
} }
ESP_LOG_BUFFER_HEXDUMP("CMUX Received", data, actual_len, ESP_LOG_DEBUG); ESP_LOG_BUFFER_HEXDUMP("CMUX Received", data, actual_len, ESP_LOG_DEBUG);
uint8_t* frame = data; uint8_t *frame = data;
uint8_t* recover_ptr; uint8_t *recover_ptr;
auto available_len = actual_len; auto available_len = actual_len;
size_t payload_offset = 0; size_t payload_offset = 0;
size_t footer_offset = 0; size_t footer_offset = 0;
while (available_len > 0) { while (available_len > 0) {
switch (state) { switch (state) {
case cmux_state::RECOVER: case cmux_state::RECOVER:
if (frame[0] == SOF_MARKER) { if (frame[0] == SOF_MARKER) {
// already init state // already init state
state = cmux_state::INIT; state = cmux_state::INIT;
break; break;
} }
recover_ptr = static_cast<uint8_t*>(memchr(frame, SOF_MARKER, available_len)); recover_ptr = static_cast<uint8_t *>(memchr(frame, SOF_MARKER, available_len));
if (recover_ptr && available_len > recover_ptr - frame) { if (recover_ptr && available_len > recover_ptr - frame) {
available_len -= (recover_ptr - frame); available_len -= (recover_ptr - frame);
frame = recover_ptr; frame = recover_ptr;
state = cmux_state::INIT; state = cmux_state::INIT;
ESP_LOGI("CMUX", "Protocol recovered"); ESP_LOGI("CMUX", "Protocol recovered");
if (available_len > 1 && frame[1] == SOF_MARKER) {
// empty frame
available_len -= 1;
frame += 1;
}
break;
}
// marker not found, continue with recovery
return false;
case cmux_state::INIT:
if (frame[0] != SOF_MARKER) {
ESP_LOGW("CMUX", "Protocol mismatch: Missed leading SOF, recovering...");
state = cmux_state::RECOVER;
break;
}
if (available_len > 1 && frame[1] == SOF_MARKER) { if (available_len > 1 && frame[1] == SOF_MARKER) {
// empty frame // empty frame
available_len -= 1; available_len -= 1;
frame += 1; frame += 1;
break;
} }
state = cmux_state::HEADER; break;
}
// marker not found, continue with recovery
return false;
case cmux_state::INIT:
if (frame[0] != SOF_MARKER) {
ESP_LOGW("CMUX", "Protocol mismatch: Missed leading SOF, recovering...");
state = cmux_state::RECOVER;
break;
}
if (available_len > 1 && frame[1] == SOF_MARKER) {
// empty frame
available_len -= 1;
frame += 1;
break;
}
state = cmux_state::HEADER;
available_len--;
frame_header_offset = 1;
frame++;
break;
case cmux_state::HEADER:
if (available_len > 0 && frame_header_offset == 1 && frame[0] == SOF_MARKER) {
// Previously trailing SOF interpreted as heading SOF, remove it and restart HEADER
available_len--; available_len--;
frame_header_offset = 1;
frame++; frame++;
break; break;
case cmux_state::HEADER: }
if (available_len > 0 && frame_header_offset == 1 && frame[0] == SOF_MARKER) { if (available_len + frame_header_offset < 4) {
// Previously trailing SOF interpreted as heading SOF, remove it and restart HEADER memcpy(frame_header + frame_header_offset, frame, available_len);
available_len--; frame_header_offset += available_len;
frame++; return false; // need read more
break; }
} payload_offset = std::min(available_len, 4 - frame_header_offset);
if (available_len + frame_header_offset < 4) { memcpy(frame_header + frame_header_offset, frame, payload_offset);
memcpy(frame_header + frame_header_offset, frame, available_len); frame_header_offset += payload_offset;
frame_header_offset += available_len; dlci = frame_header[1] >> 2;
return false; // need read more type = frame_header[2];
} payload_len = (frame_header[3] >> 1);
payload_offset = std::min(available_len, 4 - frame_header_offset); frame += payload_offset;
memcpy(frame_header + frame_header_offset, frame, payload_offset); available_len -= payload_offset;
frame_header_offset += payload_offset; state = cmux_state::PAYLOAD;
dlci = frame_header[1] >> 2; break;
type = frame_header[2]; case cmux_state::PAYLOAD:
payload_len = (frame_header[3] >> 1); ESP_LOGD("CMUX", "Payload frame: dlci:%02x type:%02x payload:%d available:%d", dlci, type, payload_len, available_len);
frame += payload_offset; if (available_len < payload_len) { // payload
available_len -= payload_offset;
state = cmux_state::PAYLOAD; state = cmux_state::PAYLOAD;
break; data_available(frame, available_len); // partial read
case cmux_state::PAYLOAD: payload_len -= available_len;
ESP_LOGD("CMUX", "Payload frame: dlci:%02x type:%02x payload:%d available:%d", dlci, type, payload_len, available_len); return false;
if (available_len < payload_len) { // payload } else { // complete
state = cmux_state::PAYLOAD; if (payload_len > 0) {
data_available(frame, available_len); // partial read data_available(&frame[0], payload_len); // rest read
payload_len -= available_len;
return false;
} else { // complete
if (payload_len > 0) {
data_available(&frame[0], payload_len); // rest read
}
available_len -= payload_len;
frame += payload_len;
state = cmux_state::FOOTER;
payload_len = 0;
} }
break; available_len -= payload_len;
case cmux_state::FOOTER: frame += payload_len;
if (available_len + frame_header_offset < 6) { state = cmux_state::FOOTER;
memcpy(frame_header + frame_header_offset, frame, available_len); payload_len = 0;
frame_header_offset += available_len; }
return false; // need read more break;
} else { case cmux_state::FOOTER:
footer_offset = std::min(available_len, 6 - frame_header_offset); if (available_len + frame_header_offset < 6) {
memcpy(frame_header + frame_header_offset, frame, footer_offset); memcpy(frame_header + frame_header_offset, frame, available_len);
if (frame_header[5] != SOF_MARKER) { frame_header_offset += available_len;
ESP_LOGW("CMUX", "Protocol mismatch: Missed trailing SOF, recovering..."); return false; // need read more
payload_start = nullptr; } else {
total_payload_size = 0; footer_offset = std::min(available_len, 6 - frame_header_offset);
state = cmux_state::RECOVER; memcpy(frame_header + frame_header_offset, frame, footer_offset);
break; if (frame_header[5] != SOF_MARKER) {
} ESP_LOGW("CMUX", "Protocol mismatch: Missed trailing SOF, recovering...");
frame += footer_offset;
available_len -= footer_offset;
state = cmux_state::INIT;
frame_header_offset = 0;
data_available(nullptr, 0);
payload_start = nullptr; payload_start = nullptr;
total_payload_size = 0; total_payload_size = 0;
state = cmux_state::RECOVER;
break;
} }
break; frame += footer_offset;
available_len -= footer_offset;
state = cmux_state::INIT;
frame_header_offset = 0;
data_available(nullptr, 0);
payload_start = nullptr;
total_payload_size = 0;
}
break;
} }
} }
return true; return true;
@ -262,8 +262,7 @@ bool CMux::init()
}); });
sabm_ack = -1; sabm_ack = -1;
for (size_t i = 0; i < 3; i++) for (size_t i = 0; i < 3; i++) {
{
int timeout = 0; int timeout = 0;
send_sabm(i); send_sabm(i);
while (true) { while (true) {
@ -273,8 +272,9 @@ bool CMux::init()
sabm_ack = -1; sabm_ack = -1;
break; break;
} }
if (timeout++ > 100) if (timeout++ > 100) {
return false; return false;
}
} }
} }
return true; return true;
@ -288,8 +288,9 @@ int CMux::write(int virtual_term, uint8_t *data, size_t len)
size_t need_write = len; size_t need_write = len;
while (need_write > 0) { while (need_write > 0) {
size_t batch_len = need_write; size_t batch_len = need_write;
if (batch_len > cmux_max_len) if (batch_len > cmux_max_len) {
batch_len = cmux_max_len; batch_len = cmux_max_len;
}
uint8_t frame[6]; uint8_t frame[6];
frame[0] = SOF_MARKER; frame[0] = SOF_MARKER;
frame[1] = (i << 2) + 1; frame[1] = (i << 2) + 1;
@ -303,14 +304,16 @@ int CMux::write(int virtual_term, uint8_t *data, size_t len)
term->write(frame + 4, 2); term->write(frame + 4, 2);
ESP_LOG_BUFFER_HEXDUMP("Send", frame, 4, ESP_LOG_VERBOSE); ESP_LOG_BUFFER_HEXDUMP("Send", frame, 4, ESP_LOG_VERBOSE);
ESP_LOG_BUFFER_HEXDUMP("Send", data, batch_len, ESP_LOG_VERBOSE); ESP_LOG_BUFFER_HEXDUMP("Send", data, batch_len, ESP_LOG_VERBOSE);
ESP_LOG_BUFFER_HEXDUMP("Send", frame+4, 2, ESP_LOG_VERBOSE); ESP_LOG_BUFFER_HEXDUMP("Send", frame + 4, 2, ESP_LOG_VERBOSE);
need_write -= batch_len; need_write -= batch_len;
data += batch_len; data += batch_len;
} }
return len; return len;
} }
void CMux::set_read_cb(int inst, std::function<bool(uint8_t *, size_t)> f) { void CMux::set_read_cb(int inst, std::function<bool(uint8_t *, size_t)> f)
if (inst < max_terms) {
if (inst < max_terms) {
read_cb[inst] = std::move(f); read_cb[inst] = std::move(f);
}
} }

View File

@ -23,49 +23,53 @@ namespace esp_modem::dce_commands {
static const char *TAG = "command_lib"; static const char *TAG = "command_lib";
command_result generic_command(CommandableIf* t, const std::string &command, command_result generic_command(CommandableIf *t, const std::string &command,
const std::list<std::string_view>& pass_phrase, const std::list<std::string_view> &pass_phrase,
const std::list<std::string_view>& fail_phrase, const std::list<std::string_view> &fail_phrase,
uint32_t timeout_ms) uint32_t timeout_ms)
{ {
ESP_LOGD(TAG, "%s command %s\n", __func__, command.c_str()); ESP_LOGD(TAG, "%s command %s\n", __func__, command.c_str());
return t->command(command, [&](uint8_t *data, size_t len) { return t->command(command, [&](uint8_t *data, size_t len) {
std::string_view response((char*)data, len); std::string_view response((char *)data, len);
if (data == nullptr || len == 0 || response.empty()) if (data == nullptr || len == 0 || response.empty()) {
return command_result::TIMEOUT; return command_result::TIMEOUT;
}
ESP_LOGD(TAG, "Response: %.*s\n", (int)response.length(), response.data()); ESP_LOGD(TAG, "Response: %.*s\n", (int)response.length(), response.data());
for (auto &it : pass_phrase) for (auto &it : pass_phrase)
if (response.find(it) != std::string::npos) if (response.find(it) != std::string::npos) {
return command_result::OK; return command_result::OK;
}
for (auto &it : fail_phrase) for (auto &it : fail_phrase)
if (response.find(it) != std::string::npos) if (response.find(it) != std::string::npos) {
return command_result::FAIL; return command_result::FAIL;
}
return command_result::TIMEOUT; return command_result::TIMEOUT;
}, timeout_ms); }, timeout_ms);
} }
static inline command_result generic_command(CommandableIf* t, const std::string& command, static inline command_result generic_command(CommandableIf *t, const std::string &command,
const std::string& pass_phrase, const std::string &pass_phrase,
const std::string& fail_phrase, uint32_t timeout_ms) const std::string &fail_phrase, uint32_t timeout_ms)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
const auto pass = std::list<std::string_view>({pass_phrase}); const auto pass = std::list<std::string_view>({pass_phrase});
const auto fail = std::list<std::string_view>({fail_phrase}); const auto fail = std::list<std::string_view>({fail_phrase});
return generic_command(t, command, pass, fail, timeout_ms); return generic_command(t, command, pass, fail, timeout_ms);
} }
static inline command_result generic_get_string(CommandableIf* t, const std::string& command, std::string_view& output, uint32_t timeout_ms = 500) static inline command_result generic_get_string(CommandableIf *t, const std::string &command, std::string_view &output, uint32_t timeout_ms = 500)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return t->command(command, [&](uint8_t *data, size_t len) { return t->command(command, [&](uint8_t *data, size_t len) {
size_t pos = 0; size_t pos = 0;
std::string_view response((char*)data, len); std::string_view response((char *)data, len);
while ((pos = response.find('\n')) != std::string::npos) { while ((pos = response.find('\n')) != std::string::npos) {
std::string_view token = response.substr(0, pos); std::string_view token = response.substr(0, pos);
for (auto it = token.end() - 1; it > token.begin(); it--) // strip trailing CR or LF for (auto it = token.end() - 1; it > token.begin(); it--) // strip trailing CR or LF
if (*it == '\r' || *it == '\n') if (*it == '\r' || *it == '\n') {
token.remove_suffix(1); token.remove_suffix(1);
}
ESP_LOGV(TAG, "Token: {%.*s}\n", static_cast<int>(token.size()), token.data()); ESP_LOGV(TAG, "Token: {%.*s}\n", static_cast<int>(token.size()), token.data());
if (token.find("OK") != std::string::npos) { if (token.find("OK") != std::string::npos) {
@ -75,147 +79,157 @@ static inline command_result generic_get_string(CommandableIf* t, const std::str
} else if (token.size() > 2) { } else if (token.size() > 2) {
output = token; output = token;
} }
response = response.substr(pos+1); response = response.substr(pos + 1);
} }
return command_result::TIMEOUT; return command_result::TIMEOUT;
}, timeout_ms); }, timeout_ms);
} }
static inline command_result generic_get_string(CommandableIf* t, const std::string& command, std::string& output, uint32_t timeout_ms = 500) static inline command_result generic_get_string(CommandableIf *t, const std::string &command, std::string &output, uint32_t timeout_ms = 500)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
std::string_view out; std::string_view out;
auto ret = generic_get_string(t, command, out, timeout_ms); auto ret = generic_get_string(t, command, out, timeout_ms);
if (ret == command_result::OK) if (ret == command_result::OK) {
output = out; output = out;
}
return ret; return ret;
} }
static inline command_result generic_command_common(CommandableIf* t, const std::string &command, uint32_t timeout = 500) static inline command_result generic_command_common(CommandableIf *t, const std::string &command, uint32_t timeout = 500)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command(t, command, "OK", "ERROR", timeout); return generic_command(t, command, "OK", "ERROR", timeout);
} }
command_result sync(CommandableIf* t) command_result sync(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command_common(t, "AT\r"); return generic_command_common(t, "AT\r");
} }
command_result store_profile(CommandableIf* t) command_result store_profile(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command_common(t, "AT&W\r"); return generic_command_common(t, "AT&W\r");
} }
command_result power_down(CommandableIf* t) command_result power_down(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command(t, "AT+QPOWD=1\r", "POWERED DOWN", "ERROR", 1000); return generic_command(t, "AT+QPOWD=1\r", "POWERED DOWN", "ERROR", 1000);
} }
command_result power_down_sim7xxx(CommandableIf* t) command_result power_down_sim7xxx(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command_common(t, "AT+CPOF\r", 1000); return generic_command_common(t, "AT+CPOF\r", 1000);
} }
command_result power_down_sim8xx(CommandableIf* t) command_result power_down_sim8xx(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command(t, "AT+CPOWD=1\r", "POWER DOWN", "ERROR", 1000); return generic_command(t, "AT+CPOWD=1\r", "POWER DOWN", "ERROR", 1000);
} }
command_result reset(CommandableIf* t) command_result reset(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command(t, "AT+CRESET\r", "PB DONE", "ERROR", 60000); return generic_command(t, "AT+CRESET\r", "PB DONE", "ERROR", 60000);
} }
command_result set_baud(CommandableIf* t, int baud) command_result set_baud(CommandableIf *t, int baud)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command_common(t, "AT+IPR=" + std::to_string(baud) + "\r"); return generic_command_common(t, "AT+IPR=" + std::to_string(baud) + "\r");
} }
command_result hang_up(CommandableIf* t) command_result hang_up(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command_common(t, "ATH\r", 90000); return generic_command_common(t, "ATH\r", 90000);
} }
command_result get_battery_status(CommandableIf* t, int& voltage, int &bcs, int &bcl) command_result get_battery_status(CommandableIf *t, int &voltage, int &bcs, int &bcl)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
std::string_view out; std::string_view out;
auto ret = generic_get_string(t, "AT+CBC\r", out); auto ret = generic_get_string(t, "AT+CBC\r", out);
if (ret != command_result::OK) if (ret != command_result::OK) {
return ret; return ret;
}
constexpr std::string_view pattern = "+CBC: "; constexpr std::string_view pattern = "+CBC: ";
if (out.find(pattern) == std::string_view::npos) if (out.find(pattern) == std::string_view::npos) {
return command_result::FAIL; return command_result::FAIL;
}
// Parsing +CBC: <bcs>,<bcl>,<voltage> // Parsing +CBC: <bcs>,<bcl>,<voltage>
out = out.substr(pattern.size()); out = out.substr(pattern.size());
int pos, value, property = 0; int pos, value, property = 0;
while ((pos = out.find(',') != std::string::npos)) { while ((pos = out.find(',') != std::string::npos)) {
if (std::from_chars(out.data(), out.data() + pos, value).ec == std::errc::invalid_argument) if (std::from_chars(out.data(), out.data() + pos, value).ec == std::errc::invalid_argument) {
return command_result::FAIL; return command_result::FAIL;
}
switch (property++) { switch (property++) {
case 0: bcs = value; case 0: bcs = value;
break; break;
case 1: bcl = value; case 1: bcl = value;
break; break;
default: default:
return command_result::FAIL; return command_result::FAIL;
} }
out = out.substr(pos + 1); out = out.substr(pos + 1);
} }
if (std::from_chars(out.data(), out.data() + out.size(), voltage).ec == std::errc::invalid_argument) if (std::from_chars(out.data(), out.data() + out.size(), voltage).ec == std::errc::invalid_argument) {
return command_result::FAIL; return command_result::FAIL;
}
return command_result::OK; return command_result::OK;
} }
command_result get_battery_status_sim7xxx(CommandableIf* t, int& voltage, int &bcs, int &bcl) command_result get_battery_status_sim7xxx(CommandableIf *t, int &voltage, int &bcs, int &bcl)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
std::string_view out; std::string_view out;
auto ret = generic_get_string(t, "AT+CBC\r", out); auto ret = generic_get_string(t, "AT+CBC\r", out);
if (ret != command_result::OK) if (ret != command_result::OK) {
return ret; return ret;
}
// Parsing +CBC: <voltage in Volts> V // Parsing +CBC: <voltage in Volts> V
constexpr std::string_view pattern = "+CBC: "; constexpr std::string_view pattern = "+CBC: ";
constexpr int num_pos = pattern.size(); constexpr int num_pos = pattern.size();
int dot_pos; int dot_pos;
if (out.find(pattern) == std::string::npos || if (out.find(pattern) == std::string::npos ||
(dot_pos = out.find('.')) == std::string::npos) (dot_pos = out.find('.')) == std::string::npos) {
return command_result::FAIL; return command_result::FAIL;
}
int volt, fraction; int volt, fraction;
if (std::from_chars(out.data() + num_pos, out.data() + dot_pos, volt).ec == std::errc::invalid_argument) if (std::from_chars(out.data() + num_pos, out.data() + dot_pos, volt).ec == std::errc::invalid_argument) {
return command_result::FAIL; return command_result::FAIL;
if (std::from_chars(out.data() + dot_pos + 1, out.data() + out.size() - 1, fraction).ec == std::errc::invalid_argument) }
if (std::from_chars(out.data() + dot_pos + 1, out.data() + out.size() - 1, fraction).ec == std::errc::invalid_argument) {
return command_result::FAIL; return command_result::FAIL;
}
bcl = bcs = -1; // not available for these models bcl = bcs = -1; // not available for these models
voltage = 1000*volt + fraction; voltage = 1000 * volt + fraction;
return command_result::OK; return command_result::OK;
} }
command_result set_flow_control(CommandableIf* t, int dce_flow, int dte_flow) command_result set_flow_control(CommandableIf *t, int dce_flow, int dte_flow)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command_common(t, "AT+IFC=" + std::to_string(dce_flow) + ", " + std::to_string(dte_flow) + "\r"); return generic_command_common(t, "AT+IFC=" + std::to_string(dce_flow) + ", " + std::to_string(dte_flow) + "\r");
} }
command_result get_operator_name(CommandableIf* t, std::string& operator_name) command_result get_operator_name(CommandableIf *t, std::string &operator_name)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
std::string_view out; std::string_view out;
auto ret = generic_get_string(t, "AT+COPS?\r", out, 75000); auto ret = generic_get_string(t, "AT+COPS?\r", out, 75000);
if (ret != command_result::OK) if (ret != command_result::OK) {
return ret; return ret;
}
auto pos = out.find("+COPS"); auto pos = out.find("+COPS");
auto property = 0; auto property = 0;
while (pos != std::string::npos) { while (pos != std::string::npos) {
@ -229,113 +243,118 @@ command_result get_operator_name(CommandableIf* t, std::string& operator_name)
return command_result::FAIL; return command_result::FAIL;
} }
command_result set_echo(CommandableIf* t, bool on) command_result set_echo(CommandableIf *t, bool on)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
if (on) if (on) {
return generic_command_common(t, "ATE1\r"); return generic_command_common(t, "ATE1\r");
}
return generic_command_common(t, "ATE0\r"); return generic_command_common(t, "ATE0\r");
} }
command_result set_pdp_context(CommandableIf* t, PdpContext& pdp) command_result set_pdp_context(CommandableIf *t, PdpContext &pdp)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
std::string pdp_command = "AT+CGDCONT=" + std::to_string(pdp.context_id) + std::string pdp_command = "AT+CGDCONT=" + std::to_string(pdp.context_id) +
",\"" + pdp.protocol_type + "\",\"" + pdp.apn + "\"\r"; ",\"" + pdp.protocol_type + "\",\"" + pdp.apn + "\"\r";
return generic_command_common(t, pdp_command); return generic_command_common(t, pdp_command);
} }
command_result set_data_mode(CommandableIf* t) command_result set_data_mode(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000); return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000);
} }
command_result set_data_mode_sim8xx(CommandableIf* t) command_result set_data_mode_sim8xx(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000); return generic_command(t, "ATD*99##\r", "CONNECT", "ERROR", 5000);
} }
command_result resume_data_mode(CommandableIf* t) command_result resume_data_mode(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command(t, "ATO\r", "CONNECT", "ERROR", 5000); return generic_command(t, "ATO\r", "CONNECT", "ERROR", 5000);
} }
command_result set_command_mode(CommandableIf* t) command_result set_command_mode(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
const auto pass = std::list<std::string_view>({"NO CARRIER", "OK"}); const auto pass = std::list<std::string_view>({"NO CARRIER", "OK"});
const auto fail = std::list<std::string_view>({"ERROR"}); const auto fail = std::list<std::string_view>({"ERROR"});
return generic_command(t, "+++", pass, fail, 5000); return generic_command(t, "+++", pass, fail, 5000);
} }
command_result get_imsi(CommandableIf* t, std::string& imsi_number) command_result get_imsi(CommandableIf *t, std::string &imsi_number)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_get_string(t, "AT+CIMI\r", imsi_number, 5000); return generic_get_string(t, "AT+CIMI\r", imsi_number, 5000);
} }
command_result get_imei(CommandableIf* t, std::string& out) command_result get_imei(CommandableIf *t, std::string &out)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_get_string(t, "AT+CGSN\r", out, 5000); return generic_get_string(t, "AT+CGSN\r", out, 5000);
} }
command_result get_module_name(CommandableIf* t, std::string& out) command_result get_module_name(CommandableIf *t, std::string &out)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_get_string(t, "AT+CGMM\r", out, 5000); return generic_get_string(t, "AT+CGMM\r", out, 5000);
} }
command_result sms_txt_mode(CommandableIf* t, bool txt = true) command_result sms_txt_mode(CommandableIf *t, bool txt = true)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
if (txt) if (txt) {
return generic_command_common(t, "AT+CMGF=1\r"); // Text mode (default) return generic_command_common(t, "AT+CMGF=1\r"); // Text mode (default)
}
return generic_command_common(t, "AT+CMGF=0\r"); // PDU mode return generic_command_common(t, "AT+CMGF=0\r"); // PDU mode
} }
command_result sms_character_set(CommandableIf* t) command_result sms_character_set(CommandableIf *t)
{ {
// Sets the default GSM character set // Sets the default GSM character set
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command_common(t, "AT+CSCS=\"GSM\"\r"); return generic_command_common(t, "AT+CSCS=\"GSM\"\r");
} }
command_result send_sms(CommandableIf* t, const std::string& number, const std::string& message) command_result send_sms(CommandableIf *t, const std::string &number, const std::string &message)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
auto ret = t->command("AT+CMGS=\"" + number + "\"\r", [&](uint8_t *data, size_t len) { auto ret = t->command("AT+CMGS=\"" + number + "\"\r", [&](uint8_t *data, size_t len) {
std::string_view response((char*)data, len); std::string_view response((char *)data, len);
ESP_LOGD(TAG,"Send SMS response %.*s", static_cast<int>(response.size()), response.data()); ESP_LOGD(TAG, "Send SMS response %.*s", static_cast<int>(response.size()), response.data());
if (response.find('>') != std::string::npos) { if (response.find('>') != std::string::npos) {
return command_result::OK; return command_result::OK;
} }
return command_result::TIMEOUT; return command_result::TIMEOUT;
}, 5000, ' '); }, 5000, ' ');
if (ret != command_result::OK) if (ret != command_result::OK) {
return ret; return ret;
return generic_command_common(t, message +"\x1A", 120000); }
return generic_command_common(t, message + "\x1A", 120000);
} }
command_result set_cmux(CommandableIf* t) command_result set_cmux(CommandableIf *t)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command_common(t, "AT+CMUX=0\r"); return generic_command_common(t, "AT+CMUX=0\r");
} }
command_result read_pin(CommandableIf* t, bool& pin_ok) command_result read_pin(CommandableIf *t, bool &pin_ok)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
std::string_view out; std::string_view out;
auto ret = generic_get_string(t, "AT+CPIN?\r", out); auto ret = generic_get_string(t, "AT+CPIN?\r", out);
if (ret != command_result::OK) if (ret != command_result::OK) {
return ret; return ret;
if (out.find("+CPIN:") == std::string::npos) }
if (out.find("+CPIN:") == std::string::npos) {
return command_result::FAIL; return command_result::FAIL;
}
if (out.find("SIM PIN") != std::string::npos || out.find("SIM PUK") != std::string::npos) { if (out.find("SIM PIN") != std::string::npos || out.find("SIM PUK") != std::string::npos) {
pin_ok = false; pin_ok = false;
return command_result::OK; return command_result::OK;
@ -347,32 +366,36 @@ command_result read_pin(CommandableIf* t, bool& pin_ok)
return command_result::FAIL; // Neither pin-ok, nor waiting for pin/puk -> mark as error return command_result::FAIL; // Neither pin-ok, nor waiting for pin/puk -> mark as error
} }
command_result set_pin(CommandableIf* t, const std::string& pin) command_result set_pin(CommandableIf *t, const std::string &pin)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
std::string set_pin_command = "AT+CPIN=" + pin + "\r"; std::string set_pin_command = "AT+CPIN=" + pin + "\r";
return generic_command_common(t, set_pin_command); return generic_command_common(t, set_pin_command);
} }
command_result get_signal_quality(CommandableIf* t, int &rssi, int &ber) command_result get_signal_quality(CommandableIf *t, int &rssi, int &ber)
{ {
ESP_LOGV(TAG,"%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
std::string_view out; std::string_view out;
auto ret = generic_get_string(t, "AT+CSQ\r", out); auto ret = generic_get_string(t, "AT+CSQ\r", out);
if (ret != command_result::OK) if (ret != command_result::OK) {
return ret; return ret;
}
constexpr std::string_view pattern = "+CSQ: "; constexpr std::string_view pattern = "+CSQ: ";
constexpr int rssi_pos = pattern.size(); constexpr int rssi_pos = pattern.size();
int ber_pos; int ber_pos;
if (out.find(pattern) == std::string::npos || if (out.find(pattern) == std::string::npos ||
(ber_pos = out.find(',')) == std::string::npos) (ber_pos = out.find(',')) == std::string::npos) {
return command_result::FAIL; return command_result::FAIL;
}
if (std::from_chars(out.data() + rssi_pos, out.data() + ber_pos, rssi).ec == std::errc::invalid_argument) if (std::from_chars(out.data() + rssi_pos, out.data() + ber_pos, rssi).ec == std::errc::invalid_argument) {
return command_result::FAIL; return command_result::FAIL;
if (std::from_chars(out.data() + ber_pos + 1, out.data() + out.size(), ber).ec == std::errc::invalid_argument) }
if (std::from_chars(out.data() + ber_pos + 1, out.data() + out.size(), ber).ec == std::errc::invalid_argument) {
return command_result::FAIL; return command_result::FAIL;
}
return command_result::OK; return command_result::OK;
} }

View File

@ -22,44 +22,53 @@ namespace esp_modem {
bool DCE_Mode::set(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m) bool DCE_Mode::set(DTE *dte, ModuleIf *device, Netif &netif, modem_mode m)
{ {
switch (m) { switch (m) {
case modem_mode::UNDEF: case modem_mode::UNDEF:
break; break;
case modem_mode::COMMAND_MODE: case modem_mode::COMMAND_MODE:
if (mode == modem_mode::COMMAND_MODE) if (mode == modem_mode::COMMAND_MODE) {
return false; return false;
netif.stop(); }
if (!device->set_mode(modem_mode::COMMAND_MODE)) netif.stop();
return false; if (!device->set_mode(modem_mode::COMMAND_MODE)) {
dte->set_read_cb([&](uint8_t *data, size_t len) -> bool { return false;
ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data", data, len, ESP_LOG_INFO); }
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);
netif.wait_until_ppp_exits(); return false;
dte->set_read_cb(nullptr); });
if (!dte->set_mode(modem_mode::COMMAND_MODE)) netif.wait_until_ppp_exits();
return false; dte->set_read_cb(nullptr);
mode = m; if (!dte->set_mode(modem_mode::COMMAND_MODE)) {
return true; return false;
case modem_mode::DATA_MODE: }
if (mode == modem_mode::DATA_MODE) mode = m;
return false; return true;
if (!device->setup_data_mode()) case modem_mode::DATA_MODE:
return false; if (mode == modem_mode::DATA_MODE) {
if (!device->set_mode(modem_mode::DATA_MODE)) return false;
return false; }
if (!dte->set_mode(modem_mode::DATA_MODE)) if (!device->setup_data_mode()) {
return false; return false;
netif.start(); }
mode = m; if (!device->set_mode(modem_mode::DATA_MODE)) {
return true; return false;
case modem_mode::CMUX_MODE: }
if (mode == modem_mode::DATA_MODE || mode == modem_mode::CMUX_MODE) if (!dte->set_mode(modem_mode::DATA_MODE)) {
return false; return false;
device->set_mode(modem_mode::CMUX_MODE); }
if (!dte->set_mode(modem_mode::CMUX_MODE)) netif.start();
return false; mode = m;
mode = modem_mode::COMMAND_MODE; return true;
return true; case modem_mode::CMUX_MODE:
if (mode == modem_mode::DATA_MODE || mode == modem_mode::CMUX_MODE) {
return false;
}
device->set_mode(modem_mode::CMUX_MODE);
if (!dte->set_mode(modem_mode::CMUX_MODE)) {
return false;
}
mode = modem_mode::COMMAND_MODE;
return true;
} }
return false; return false;
} }

View File

@ -22,10 +22,10 @@ using namespace esp_modem;
static const size_t dte_default_buffer_size = 1000; static const size_t dte_default_buffer_size = 1000;
DTE::DTE(const esp_modem_dte_config *config, std::unique_ptr<Terminal> terminal): DTE::DTE(const esp_modem_dte_config *config, std::unique_ptr<Terminal> terminal):
buffer_size(config->dte_buffer_size), consumed(0), buffer_size(config->dte_buffer_size), consumed(0),
buffer(std::make_unique<uint8_t[]>(buffer_size)), buffer(std::make_unique<uint8_t[]>(buffer_size)),
term(std::move(terminal)), command_term(term.get()), other_term(nullptr), term(std::move(terminal)), command_term(term.get()), other_term(nullptr),
mode(modem_mode::UNDEF) {} mode(modem_mode::UNDEF) {}
DTE::DTE(std::unique_ptr<Terminal> terminal): DTE::DTE(std::unique_ptr<Terminal> terminal):
buffer_size(dte_default_buffer_size), consumed(0), buffer_size(dte_default_buffer_size), consumed(0),
@ -72,17 +72,21 @@ command_result DTE::command(const std::string &cmd, got_line_cb got_line, uint32
bool DTE::setup_cmux() bool DTE::setup_cmux()
{ {
auto original_term = std::move(term); auto original_term = std::move(term);
if (original_term == nullptr) if (original_term == nullptr) {
return false; return false;
}
auto cmux_term = std::make_shared<CMux>(std::move(original_term), std::move(buffer), buffer_size); auto cmux_term = std::make_shared<CMux>(std::move(original_term), std::move(buffer), buffer_size);
if (cmux_term == nullptr) if (cmux_term == nullptr) {
return false; return false;
}
buffer_size = 0; buffer_size = 0;
if (!cmux_term->init()) if (!cmux_term->init()) {
return false; return false;
}
term = std::make_unique<CMuxInstance>(cmux_term, 0); term = std::make_unique<CMuxInstance>(cmux_term, 0);
if (term == nullptr) if (term == nullptr) {
return false; return false;
}
command_term = term.get(); // use command terminal as previously command_term = term.get(); // use command terminal as previously
other_term = std::make_unique<CMuxInstance>(cmux_term, 1); other_term = std::make_unique<CMuxInstance>(cmux_term, 1);
return true; return true;
@ -110,8 +114,9 @@ void DTE::set_read_cb(std::function<bool(uint8_t *, size_t)> f)
data = buffer.get(); data = buffer.get();
len = term->read(buffer.get(), buffer_size); len = term->read(buffer.get(), buffer_size);
} }
if (on_data) if (on_data) {
return on_data(data, len); return on_data(data, len);
}
return false; return false;
}); });
} }

View File

@ -20,18 +20,18 @@
namespace esp_modem { namespace esp_modem {
template<typename T> template<typename T>
std::shared_ptr<T> create_device(const std::shared_ptr<DTE>& dte, std::string &apn) std::shared_ptr<T> create_device(const std::shared_ptr<DTE> &dte, std::string &apn)
{ {
auto pdp = std::make_unique<PdpContext>(apn); auto pdp = std::make_unique<PdpContext>(apn);
return std::make_shared<T>(dte, std::move(pdp)); return std::make_shared<T>(dte, std::move(pdp));
} }
std::shared_ptr<GenericModule> create_generic_module(const std::shared_ptr<DTE>& dte, std::string &apn) std::shared_ptr<GenericModule> create_generic_module(const std::shared_ptr<DTE> &dte, std::string &apn)
{ {
return create_device<GenericModule>(dte, apn); return create_device<GenericModule>(dte, apn);
} }
std::shared_ptr<SIM7600> create_SIM7600_module(const std::shared_ptr<DTE>& dte, std::string &apn) std::shared_ptr<SIM7600> create_SIM7600_module(const std::shared_ptr<DTE> &dte, std::string &apn)
{ {
return create_device<SIM7600>(dte, apn); return create_device<SIM7600>(dte, apn);
} }
@ -42,7 +42,8 @@ std::shared_ptr<SIM7600> create_SIM7600_module(const std::shared_ptr<DTE>& dte,
#include "cxx_include/esp_modem_dce_factory.hpp" #include "cxx_include/esp_modem_dce_factory.hpp"
namespace esp_modem::dce_factory { namespace esp_modem::dce_factory {
std::unique_ptr<PdpContext> FactoryHelper::create_pdp_context(std::string &apn) { std::unique_ptr<PdpContext> FactoryHelper::create_pdp_context(std::string &apn)
{
return std::unique_ptr<PdpContext>(); return std::unique_ptr<PdpContext>();
} }

View File

@ -19,7 +19,7 @@
namespace esp_modem { namespace esp_modem {
GenericModule::GenericModule(std::shared_ptr<DTE> dte, const dce_config *config) : GenericModule::GenericModule(std::shared_ptr<DTE> dte, const dce_config *config) :
dte(std::move(dte)), pdp(std::make_unique<PdpContext>(config->apn)) {} dte(std::move(dte)), pdp(std::make_unique<PdpContext>(config->apn)) {}
// //
// Define preprocessor's forwarding to dce_commands definitions // Define preprocessor's forwarding to dce_commands definitions
@ -50,33 +50,40 @@ DECLARE_ALL_COMMAND_APIS(return_type name(...) )
// //
// Handle specific commands for specific supported modems // Handle specific commands for specific supported modems
// //
command_result SIM7600::get_module_name(std::string &name) { command_result SIM7600::get_module_name(std::string &name)
{
name = "7600"; name = "7600";
return command_result::OK; return command_result::OK;
} }
command_result SIM7600::get_battery_status(int& voltage, int &bcs, int &bcl) { command_result SIM7600::get_battery_status(int &voltage, int &bcs, int &bcl)
{
return dce_commands::get_battery_status_sim7xxx(dte.get(), voltage, bcs, bcl); return dce_commands::get_battery_status_sim7xxx(dte.get(), voltage, bcs, bcl);
} }
command_result SIM7600::power_down() { command_result SIM7600::power_down()
{
return dce_commands::power_down_sim7xxx(dte.get()); return dce_commands::power_down_sim7xxx(dte.get());
} }
command_result SIM800::get_module_name(std::string &name) { command_result SIM800::get_module_name(std::string &name)
{
name = "800L"; name = "800L";
return command_result::OK; return command_result::OK;
} }
command_result SIM800::power_down() { command_result SIM800::power_down()
{
return dce_commands::power_down_sim8xx(dte.get()); return dce_commands::power_down_sim8xx(dte.get());
} }
command_result SIM800::set_data_mode() { command_result SIM800::set_data_mode()
{
return dce_commands::set_data_mode_sim8xx(dte.get()); return dce_commands::set_data_mode_sim8xx(dte.get());
} }
command_result BG96::get_module_name(std::string &name) { command_result BG96::get_module_name(std::string &name)
{
name = "BG96"; name = "BG96";
return command_result::OK; return command_result::OK;
} }

View File

@ -24,7 +24,8 @@
namespace esp_modem { namespace esp_modem {
void Netif::on_ppp_changed(void *arg, esp_event_base_t event_base, void Netif::on_ppp_changed(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data) { int32_t event_id, void *event_data)
{
auto *ppp = static_cast<Netif *>(arg); auto *ppp = static_cast<Netif *>(arg);
if (event_id < NETIF_PP_PHASE_OFFSET) { if (event_id < NETIF_PP_PHASE_OFFSET) {
ESP_LOGI("esp_modem_netif", "PPP state changed event %d", event_id); ESP_LOGI("esp_modem_netif", "PPP state changed event %d", event_id);
@ -33,7 +34,8 @@ void Netif::on_ppp_changed(void *arg, esp_event_base_t event_base,
} }
} }
esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len) { esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len)
{
auto *ppp = static_cast<Netif *>(h); auto *ppp = static_cast<Netif *>(h);
if (ppp->signal.is_any(PPP_STARTED)) { if (ppp->signal.is_any(PPP_STARTED)) {
if (ppp->ppp_dte && ppp->ppp_dte->write((uint8_t *) buffer, len) > 0) { if (ppp->ppp_dte && ppp->ppp_dte->write((uint8_t *) buffer, len) > 0) {
@ -43,7 +45,8 @@ esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len) {
return ESP_FAIL; return ESP_FAIL;
} }
esp_err_t Netif::esp_modem_post_attach(esp_netif_t *esp_netif, void *args) { esp_err_t Netif::esp_modem_post_attach(esp_netif_t *esp_netif, void *args)
{
auto d = (ppp_netif_driver *) args; auto d = (ppp_netif_driver *) args;
esp_netif_driver_ifconfig_t driver_ifconfig = {}; esp_netif_driver_ifconfig_t driver_ifconfig = {};
driver_ifconfig.transmit = Netif::esp_modem_dte_transmit; driver_ifconfig.transmit = Netif::esp_modem_dte_transmit;
@ -53,7 +56,8 @@ esp_err_t Netif::esp_modem_post_attach(esp_netif_t *esp_netif, void *args) {
// check if PPP error events are enabled, if not, do enable the error occurred/state changed // check if PPP error events are enabled, if not, do enable the error occurred/state changed
// to notify the modem layer when switching modes // to notify the modem layer when switching modes
esp_netif_ppp_config_t ppp_config = { .ppp_phase_event_enabled = true, // assuming phase enabled, as earlier IDFs esp_netif_ppp_config_t ppp_config = { .ppp_phase_event_enabled = true, // assuming phase enabled, as earlier IDFs
.ppp_error_event_enabled = false }; // don't provide cfg getters so we enable both events .ppp_error_event_enabled = false
}; // don't provide cfg getters so we enable both events
#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 4 #if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 4
esp_netif_ppp_get_params(esp_netif, &ppp_config); esp_netif_ppp_get_params(esp_netif, &ppp_config);
#endif // ESP-IDF >= v4.4 #endif // ESP-IDF >= v4.4
@ -65,25 +69,28 @@ esp_err_t Netif::esp_modem_post_attach(esp_netif_t *esp_netif, void *args) {
return ESP_OK; return ESP_OK;
} }
void Netif::receive(uint8_t *data, size_t len) { void Netif::receive(uint8_t *data, size_t len)
{
if (signal.is_any(PPP_STARTED)) { if (signal.is_any(PPP_STARTED)) {
esp_netif_receive(driver.base.netif, data, len, nullptr); esp_netif_receive(driver.base.netif, data, len, nullptr);
} }
} }
Netif::Netif(std::shared_ptr<DTE> e, esp_netif_t *ppp_netif) : Netif::Netif(std::shared_ptr<DTE> e, esp_netif_t *ppp_netif) :
ppp_dte(std::move(e)), netif(ppp_netif) { ppp_dte(std::move(e)), netif(ppp_netif)
{
driver.base.netif = ppp_netif; driver.base.netif = ppp_netif;
driver.ppp = this; driver.ppp = this;
driver.base.post_attach = esp_modem_post_attach; driver.base.post_attach = esp_modem_post_attach;
throw_if_esp_fail(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, (void *) this)); throw_if_esp_fail(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, (void *) this));
throw_if_esp_fail(esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected, ppp_netif)); throw_if_esp_fail(esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected, ppp_netif));
throw_if_esp_fail( throw_if_esp_fail(
esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected, ppp_netif)); esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected, ppp_netif));
throw_if_esp_fail(esp_netif_attach(ppp_netif, &driver)); throw_if_esp_fail(esp_netif_attach(ppp_netif, &driver));
} }
void Netif::start() { void Netif::start()
{
ppp_dte->set_read_cb([this](uint8_t *data, size_t len) -> bool { ppp_dte->set_read_cb([this](uint8_t *data, size_t len) -> bool {
receive(data, len); receive(data, len);
return false; return false;
@ -92,12 +99,14 @@ void Netif::start() {
signal.set(PPP_STARTED); signal.set(PPP_STARTED);
} }
void Netif::stop() { void Netif::stop()
{
esp_netif_action_stop(driver.base.netif, nullptr, 0, nullptr); esp_netif_action_stop(driver.base.netif, nullptr, 0, nullptr);
signal.clear(PPP_STARTED); signal.clear(PPP_STARTED);
} }
Netif::~Netif() { Netif::~Netif()
{
if (signal.is_any(PPP_STARTED)) { if (signal.is_any(PPP_STARTED)) {
esp_netif_action_stop(driver.base.netif, nullptr, 0, nullptr); esp_netif_action_stop(driver.base.netif, nullptr, 0, nullptr);
signal.clear(PPP_STARTED); signal.clear(PPP_STARTED);
@ -108,7 +117,8 @@ Netif::~Netif() {
esp_event_handler_unregister(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected); esp_event_handler_unregister(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected);
} }
void Netif::wait_until_ppp_exits() { void Netif::wait_until_ppp_exits()
{
signal.wait(PPP_EXIT, 30000); signal.wait(PPP_EXIT, 30000);
} }

View File

@ -19,7 +19,8 @@
namespace esp_modem { namespace esp_modem {
void Netif::on_ppp_changed(void *arg, esp_event_base_t event_base, void Netif::on_ppp_changed(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data) { int32_t event_id, void *event_data)
{
} }
esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len) esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len)
@ -29,7 +30,8 @@ esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len)
return len; return len;
} }
esp_err_t Netif::esp_modem_post_attach(esp_netif_t *esp_netif, void *args) { esp_err_t Netif::esp_modem_post_attach(esp_netif_t *esp_netif, void *args)
{
return ESP_OK; return ESP_OK;
} }
@ -39,7 +41,7 @@ void Netif::receive(uint8_t *data, size_t len)
} }
Netif::Netif(std::shared_ptr<DTE> e, esp_netif_t *ppp_netif) : Netif::Netif(std::shared_ptr<DTE> e, esp_netif_t *ppp_netif) :
ppp_dte(std::move(e)), netif(ppp_netif) {} ppp_dte(std::move(e)), netif(ppp_netif) {}
void Netif::start() void Netif::start()
{ {
@ -48,7 +50,7 @@ void Netif::start()
return false; return false;
}); });
netif->transmit = esp_modem_dte_transmit; netif->transmit = esp_modem_dte_transmit;
netif->ctx = (void*)this; netif->ctx = (void *)this;
signal.set(PPP_STARTED); signal.set(PPP_STARTED);
} }
@ -56,7 +58,8 @@ void Netif::stop() {}
Netif::~Netif() = default; Netif::~Netif() = default;
void Netif::wait_until_ppp_exits() { void Netif::wait_until_ppp_exits()
{
} }

View File

@ -20,7 +20,8 @@
namespace esp_modem { namespace esp_modem {
void Lock::unlock() { void Lock::unlock()
{
xSemaphoreGiveRecursive(m); xSemaphoreGiveRecursive(m);
} }
@ -30,11 +31,13 @@ Lock::Lock(): m(nullptr)
throw_if_false(m != nullptr, "create signal event group failed"); throw_if_false(m != nullptr, "create signal event group failed");
} }
Lock::~Lock() { Lock::~Lock()
{
vSemaphoreDelete(m); vSemaphoreDelete(m);
} }
void Lock::lock() { void Lock::lock()
{
xSemaphoreTakeRecursive(m, portMAX_DELAY); xSemaphoreTakeRecursive(m, portMAX_DELAY);
} }
@ -74,12 +77,13 @@ bool SignalGroup::wait_any(uint32_t flags, uint32_t time_ms)
SignalGroup::~SignalGroup() SignalGroup::~SignalGroup()
{ {
if (event_group) if (event_group) {
vEventGroupDelete(event_group); vEventGroupDelete(event_group);
}
} }
Task::Task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t task_function) Task::Task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t task_function)
:task_handle(nullptr) : task_handle(nullptr)
{ {
BaseType_t ret = xTaskCreate(task_function, "vfs_task", stack_size, task_param, priority, &task_handle); BaseType_t ret = xTaskCreate(task_function, "vfs_task", stack_size, task_param, priority, &task_handle);
throw_if_false(ret == pdTRUE, "create vfs task failed"); throw_if_false(ret == pdTRUE, "create vfs task failed");
@ -87,8 +91,9 @@ Task::Task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t
Task::~Task() Task::~Task()
{ {
if (task_handle) if (task_handle) {
vTaskDelete(task_handle); vTaskDelete(task_handle);
}
} }
void Task::Delete() void Task::Delete()

View File

@ -46,8 +46,9 @@ void SignalGroup::clear(uint32_t bits)
bool SignalGroup::wait(uint32_t flags, uint32_t time_ms) bool SignalGroup::wait(uint32_t flags, uint32_t time_ms)
{ {
std::unique_lock<std::mutex> lock(event_group->m); std::unique_lock<std::mutex> lock(event_group->m);
return event_group->notify.wait_for(lock, std::chrono::milliseconds(time_ms), [&]{ return event_group->notify.wait_for(lock, std::chrono::milliseconds(time_ms), [&] {
if ((flags&event_group->flags) == flags) { if ((flags & event_group->flags) == flags)
{
event_group->flags &= ~flags; event_group->flags &= ~flags;
return true; return true;
} }
@ -60,13 +61,13 @@ bool SignalGroup::wait(uint32_t flags, uint32_t time_ms)
bool SignalGroup::is_any(uint32_t flags) bool SignalGroup::is_any(uint32_t flags)
{ {
std::unique_lock<std::mutex> lock(event_group->m); std::unique_lock<std::mutex> lock(event_group->m);
return flags&event_group->flags; return flags & event_group->flags;
} }
bool SignalGroup::wait_any(uint32_t flags, uint32_t time_ms) bool SignalGroup::wait_any(uint32_t flags, uint32_t time_ms)
{ {
std::unique_lock<std::mutex> lock(event_group->m); std::unique_lock<std::mutex> lock(event_group->m);
return event_group->notify.wait_for(lock, std::chrono::milliseconds(time_ms), [&]{ return flags&event_group->flags; }); return event_group->notify.wait_for(lock, std::chrono::milliseconds(time_ms), [&] { return flags & event_group->flags; });
} }
SignalGroup::~SignalGroup() = default; SignalGroup::~SignalGroup() = default;

View File

@ -29,7 +29,8 @@ struct File {
fd(config->vfs_config.fd), deleter(config->vfs_config.deleter), resource(config->vfs_config.resource) fd(config->vfs_config.fd), deleter(config->vfs_config.deleter), resource(config->vfs_config.resource)
{} {}
~File() { ~File()
{
if (deleter) { if (deleter) {
deleter(fd, resource); deleter(fd, resource);
} }
@ -45,11 +46,13 @@ public:
~FdTerminal() override; ~FdTerminal() override;
void start() override { void start() override
{
signal.set(TASK_START); signal.set(TASK_START);
} }
void stop() override { void stop() override
{
signal.clear(TASK_START); signal.clear(TASK_START);
} }
@ -57,7 +60,8 @@ public:
int read(uint8_t *data, size_t len) override; int read(uint8_t *data, size_t len) override;
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override { void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override
{
on_read = std::move(f); on_read = std::move(f);
signal.set(TASK_PARAMS); signal.set(TASK_PARAMS);
} }
@ -75,22 +79,24 @@ private:
Task task_handle; Task task_handle;
}; };
std::unique_ptr<Terminal> create_vfs_terminal(const esp_modem_dte_config *config) { std::unique_ptr<Terminal> create_vfs_terminal(const esp_modem_dte_config *config)
{
TRY_CATCH_RET_NULL( TRY_CATCH_RET_NULL(
auto term = std::make_unique<FdTerminal>(config); auto term = std::make_unique<FdTerminal>(config);
term->start(); term->start();
return term; return term;
) )
} }
FdTerminal::FdTerminal(const esp_modem_dte_config *config) : FdTerminal::FdTerminal(const esp_modem_dte_config *config) :
f(config), signal(), f(config), signal(),
task_handle(config->task_stack_size, config->task_priority, this, [](void* p){ task_handle(config->task_stack_size, config->task_priority, this, [](void *p)
auto t = static_cast<FdTerminal *>(p); {
t->task(); auto t = static_cast<FdTerminal *>(p);
Task::Delete(); t->task();
}) Task::Delete();
{} })
{}
void FdTerminal::task() void FdTerminal::task()
{ {
@ -105,8 +111,8 @@ void FdTerminal::task()
int s; int s;
fd_set rfds; fd_set rfds;
struct timeval tv = { struct timeval tv = {
.tv_sec = 1, .tv_sec = 1,
.tv_usec = 0, .tv_usec = 0,
}; };
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(f.fd, &rfds); FD_SET(f.fd, &rfds);

View File

@ -25,8 +25,8 @@ uart_resource::~uart_resource()
} }
} }
uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHandle_t* event_queue, int fd) uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHandle_t *event_queue, int fd)
:port(-1) : port(-1)
{ {
esp_err_t res; esp_err_t res;
@ -37,7 +37,7 @@ uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHand
uart_config.parity = config->parity; uart_config.parity = config->parity;
uart_config.stop_bits = config->stop_bits; uart_config.stop_bits = config->stop_bits;
uart_config.flow_ctrl = (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS uart_config.flow_ctrl = (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS
: UART_HW_FLOWCTRL_DISABLE; : UART_HW_FLOWCTRL_DISABLE;
uart_config.source_clk = UART_SCLK_APB; uart_config.source_clk = UART_SCLK_APB;
throw_if_esp_fail(uart_param_config(config->port_num, &uart_config), "config uart parameter failed"); throw_if_esp_fail(uart_param_config(config->port_num, &uart_config), "config uart parameter failed");

View File

@ -30,13 +30,17 @@ namespace esp_modem {
struct uart_task { struct uart_task {
explicit uart_task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t task_function) : explicit uart_task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t task_function) :
task_handle(nullptr) { task_handle(nullptr)
{
BaseType_t ret = xTaskCreate(task_function, "uart_task", stack_size, task_param, priority, &task_handle); BaseType_t ret = xTaskCreate(task_function, "uart_task", stack_size, task_param, priority, &task_handle);
throw_if_false(ret == pdTRUE, "create uart event task failed"); throw_if_false(ret == pdTRUE, "create uart event task failed");
} }
~uart_task() { ~uart_task()
if (task_handle) vTaskDelete(task_handle); {
if (task_handle) {
vTaskDelete(task_handle);
}
} }
TaskHandle_t task_handle; /*!< UART event task handle */ TaskHandle_t task_handle; /*!< UART event task handle */
@ -47,16 +51,18 @@ struct uart_task {
class UartTerminal : public Terminal { class UartTerminal : public Terminal {
public: public:
explicit UartTerminal(const esp_modem_dte_config *config) : explicit UartTerminal(const esp_modem_dte_config *config) :
event_queue(), uart(&config->uart_config, &event_queue, -1), signal(), event_queue(), uart(&config->uart_config, &event_queue, -1), signal(),
task_handle(config->task_stack_size, config->task_priority, this, s_task) {} task_handle(config->task_stack_size, config->task_priority, this, s_task) {}
~UartTerminal() override = default; ~UartTerminal() override = default;
void start() override { void start() override
{
signal.set(TASK_START); signal.set(TASK_START);
} }
void stop() override { void stop() override
{
signal.set(TASK_STOP); signal.set(TASK_STOP);
} }
@ -64,24 +70,28 @@ public:
int read(uint8_t *data, size_t len) override; int read(uint8_t *data, size_t len) override;
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override { void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override
{
on_read = std::move(f); on_read = std::move(f);
signal.set(TASK_PARAMS); signal.set(TASK_PARAMS);
} }
private: private:
static void s_task(void *task_param) { static void s_task(void *task_param)
{
auto t = static_cast<UartTerminal *>(task_param); auto t = static_cast<UartTerminal *>(task_param);
t->task(); t->task();
vTaskDelete(nullptr); vTaskDelete(nullptr);
} }
void task(); void task();
bool get_event(uart_event_t &event, uint32_t time_ms) { bool get_event(uart_event_t &event, uint32_t time_ms)
{
return xQueueReceive(event_queue, &event, pdMS_TO_TICKS(time_ms)); return xQueueReceive(event_queue, &event, pdMS_TO_TICKS(time_ms));
} }
void reset_events() { void reset_events()
{
uart_flush_input(uart.port); uart_flush_input(uart.port);
xQueueReset(event_queue); xQueueReset(event_queue);
} }
@ -97,15 +107,17 @@ private:
uart_task task_handle; uart_task task_handle;
}; };
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_CATCH_RET_NULL( TRY_CATCH_RET_NULL(
auto term = std::make_unique<UartTerminal>(config); auto term = std::make_unique<UartTerminal>(config);
term->start(); term->start();
return term; return term;
) )
} }
void UartTerminal::task() { void UartTerminal::task()
{
std::function<bool(uint8_t *data, size_t len)> on_read_priv = nullptr; std::function<bool(uint8_t *data, size_t len)> on_read_priv = nullptr;
uart_event_t event; uart_event_t event;
size_t len; size_t len;
@ -121,44 +133,49 @@ void UartTerminal::task() {
signal.clear(TASK_PARAMS); signal.clear(TASK_PARAMS);
} }
switch (event.type) { switch (event.type) {
case UART_DATA: case UART_DATA:
uart_get_buffered_data_len(uart.port, &len); uart_get_buffered_data_len(uart.port, &len);
if (len && on_read_priv) { if (len && on_read_priv) {
if (on_read_priv(nullptr, len)) { if (on_read_priv(nullptr, len)) {
on_read_priv = nullptr; on_read_priv = nullptr;
}
} }
break; }
case UART_FIFO_OVF: break;
ESP_LOGW(TAG, "HW FIFO Overflow"); case UART_FIFO_OVF:
if (on_error) ESP_LOGW(TAG, "HW FIFO Overflow");
on_error(terminal_error::BUFFER_OVERFLOW); if (on_error) {
reset_events(); on_error(terminal_error::BUFFER_OVERFLOW);
break; }
case UART_BUFFER_FULL: reset_events();
ESP_LOGW(TAG, "Ring Buffer Full"); break;
if (on_error) case UART_BUFFER_FULL:
on_error(terminal_error::BUFFER_OVERFLOW); ESP_LOGW(TAG, "Ring Buffer Full");
reset_events(); if (on_error) {
break; on_error(terminal_error::BUFFER_OVERFLOW);
case UART_BREAK: }
ESP_LOGW(TAG, "Rx Break"); reset_events();
if (on_error) break;
on_error(terminal_error::UNEXPECTED_CONTROL_FLOW); case UART_BREAK:
break; ESP_LOGW(TAG, "Rx Break");
case UART_PARITY_ERR: if (on_error) {
ESP_LOGE(TAG, "Parity Error"); on_error(terminal_error::UNEXPECTED_CONTROL_FLOW);
if (on_error) }
on_error(terminal_error::CHECKSUM_ERROR); break;
break; case UART_PARITY_ERR:
case UART_FRAME_ERR: ESP_LOGE(TAG, "Parity Error");
ESP_LOGE(TAG, "Frame Error"); if (on_error) {
if (on_error) on_error(terminal_error::CHECKSUM_ERROR);
on_error(terminal_error::UNEXPECTED_CONTROL_FLOW); }
break; break;
default: case UART_FRAME_ERR:
ESP_LOGW(TAG, "unknown uart event type: %d", event.type); ESP_LOGE(TAG, "Frame Error");
break; if (on_error) {
on_error(terminal_error::UNEXPECTED_CONTROL_FLOW);
}
break;
default:
ESP_LOGW(TAG, "unknown uart event type: %d", event.type);
break;
} }
} }
} }

View File

@ -23,7 +23,7 @@ namespace esp_modem {
constexpr const char *TAG = "uart_resource"; constexpr const char *TAG = "uart_resource";
uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHandle_t* event_queue, int fd): port(-1) uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHandle_t *event_queue, int fd): port(-1)
{ {
ESP_LOGD(TAG, "Creating uart resource" ); ESP_LOGD(TAG, "Creating uart resource" );
struct termios tty = {}; struct termios tty = {};
@ -39,7 +39,7 @@ uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHand
tty.c_lflag &= ~ECHO; // Disable echo tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // Disable any special handling of received bytes
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars) tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_cc[VTIME] = 0; tty.c_cc[VTIME] = 0;

View File

@ -34,7 +34,7 @@ constexpr const char *TAG = "vfs_socket_creator";
* @note: Remote command: * @note: Remote command:
* socat TCP-L:2222 GOPEN:/dev/ttyS0,ispeed=115200,ospeed=1152000,b115200,raw,echo=0 * socat TCP-L:2222 GOPEN:/dev/ttyS0,ispeed=115200,ospeed=1152000,b115200,raw,echo=0
*/ */
static esp_err_t hostname_to_fd(const char *host, int port, int* fd) static esp_err_t hostname_to_fd(const char *host, int port, int *fd)
{ {
struct sockaddr_storage address = {}; struct sockaddr_storage address = {};
struct addrinfo *address_info; struct addrinfo *address_info;
@ -46,7 +46,7 @@ static esp_err_t hostname_to_fd(const char *host, int port, int* fd)
int res = getaddrinfo(host, nullptr, &hints, &address_info); int res = getaddrinfo(host, nullptr, &hints, &address_info);
if (res != 0 || address_info == nullptr) { if (res != 0 || address_info == nullptr) {
ESP_LOGE(TAG, "couldn't get hostname for :%s: " ESP_LOGE(TAG, "couldn't get hostname for :%s: "
"getaddrinfo() returns %d, addrinfo=%p", host, res, address_info); "getaddrinfo() returns %d, addrinfo=%p", host, res, address_info);
return ESP_FAIL; return ESP_FAIL;
} }
*fd = socket(address_info->ai_family, address_info->ai_socktype, address_info->ai_protocol); *fd = socket(address_info->ai_family, address_info->ai_socktype, address_info->ai_protocol);
@ -77,7 +77,7 @@ static esp_err_t hostname_to_fd(const char *host, int port, int* fd)
} }
static void vfs_destroy_socket(int fd, struct esp_modem_vfs_resource * resource) static void vfs_destroy_socket(int fd, struct esp_modem_vfs_resource *resource)
{ {
if (fd >= 0) { if (fd >= 0) {
close(fd); close(fd);

View File

@ -27,13 +27,13 @@ constexpr const char *TAG = "vfs_uart_creator";
struct esp_modem_vfs_resource { struct esp_modem_vfs_resource {
explicit esp_modem_vfs_resource(const esp_modem_uart_term_config *config, int fd) explicit esp_modem_vfs_resource(const esp_modem_uart_term_config *config, int fd)
: internal(config, nullptr, fd) {} : internal(config, nullptr, fd) {}
esp_modem::uart_resource internal; esp_modem::uart_resource internal;
}; };
static void vfs_destroy_uart(int fd, struct esp_modem_vfs_resource * resource) static void vfs_destroy_uart(int fd, struct esp_modem_vfs_resource *resource)
{ {
if (fd >= 0) { if (fd >= 0) {
close(fd); close(fd);
@ -58,7 +58,7 @@ bool vfs_create_uart(struct esp_modem_vfs_uart_creator *config, struct esp_modem
int flags = fcntl(fd, F_GETFL, nullptr) | O_NONBLOCK; int flags = fcntl(fd, F_GETFL, nullptr) | O_NONBLOCK;
fcntl(fd, F_SETFL, flags); fcntl(fd, F_SETFL, flags);
, return false) , return false)
return true; return true;
} }

View File

@ -15,8 +15,8 @@ void LoopbackTerm::stop()
int LoopbackTerm::write(uint8_t *data, size_t len) int LoopbackTerm::write(uint8_t *data, size_t len)
{ {
if (len > 2 && (data[len-1] == '\r' || data[len-1] == '+') ) { // Simple AT responder if (len > 2 && (data[len - 1] == '\r' || data[len - 1] == '+') ) { // Simple AT responder
std::string command((char*)data, len); std::string command((char *)data, len);
std::string response; std::string response;
if (command == "+++") { if (command == "+++") {
response = "NO CARRIER\r\n"; response = "NO CARRIER\r\n";
@ -29,13 +29,13 @@ int LoopbackTerm::write(uint8_t *data, size_t len)
} else if (command.find("AT+CSQ\r") != std::string::npos) { } else if (command.find("AT+CSQ\r") != std::string::npos) {
response = "+CSQ: 123,456\n\r\nOK\r\n"; response = "+CSQ: 123,456\n\r\nOK\r\n";
} else if (command.find("AT+CBC\r") != std::string::npos) { } else if (command.find("AT+CBC\r") != std::string::npos) {
response = is_bg96 ? "+CBC: 1,2,123456V\r\r\n\r\nOK\r\n\n\r\n": response = is_bg96 ? "+CBC: 1,2,123456V\r\r\n\r\nOK\r\n\n\r\n" :
"+CBC: 123.456V\r\r\n\r\nOK\r\n\n\r\n"; "+CBC: 123.456V\r\r\n\r\nOK\r\n\n\r\n";
} else if (command.find("AT+CPIN=1234\r") != std::string::npos) { } else if (command.find("AT+CPIN=1234\r") != std::string::npos) {
response = "OK\r\n"; response = "OK\r\n";
pin_ok = true; pin_ok = true;
} else if (command.find("AT+CPIN?\r") != std::string::npos) { } else if (command.find("AT+CPIN?\r") != std::string::npos) {
response = pin_ok?"+CPIN: READY\r\nOK\r\n":"+CPIN: SIM PIN\r\nOK\r\n"; response = pin_ok ? "+CPIN: READY\r\nOK\r\n" : "+CPIN: SIM PIN\r\nOK\r\n";
} else if (command.find("AT") != std::string::npos) { } else if (command.find("AT") != std::string::npos) {
response = "OK\r\n"; response = "OK\r\n";
} }
@ -49,9 +49,9 @@ int LoopbackTerm::write(uint8_t *data, size_t len)
} }
if (len > 2 && data[0] == 0xf9) { // Simple CMUX responder if (len > 2 && data[0] == 0xf9) { // Simple CMUX responder
// turn the request into a reply -> implements CMUX loopback // turn the request into a reply -> implements CMUX loopback
if (data[2] == 0x3f) // SABM command if (data[2] == 0x3f) { // SABM command
data[2] = 0x73; data[2] = 0x73;
else if (data[2] == 0xef) { // Generic request } else if (data[2] == 0xef) { // Generic request
data[2] = 0xff; // generic reply data[2] = 0xff; // generic reply
} }
} }
@ -66,8 +66,9 @@ int LoopbackTerm::read(uint8_t *data, size_t len)
{ {
size_t read_len = std::min(data_len, len); size_t read_len = std::min(data_len, len);
if (read_len) { if (read_len) {
if (loopback_data.capacity() < len) if (loopback_data.capacity() < len) {
loopback_data.reserve(len); loopback_data.reserve(len);
}
memcpy(data, &loopback_data[0], read_len); memcpy(data, &loopback_data[0], read_len);
loopback_data.erase(loopback_data.begin(), loopback_data.begin() + read_len); loopback_data.erase(loopback_data.begin(), loopback_data.begin() + read_len);
data_len -= read_len; data_len -= read_len;

View File

@ -51,7 +51,7 @@ TEST_CASE("DTE send/receive command", "[esp_modem]")
CHECK(dte->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true); CHECK(dte->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true);
auto ret = dte->command(test_command, [&](uint8_t *data, size_t len) { auto ret = dte->command(test_command, [&](uint8_t *data, size_t len) {
std::string response((char*)data, len); std::string response((char *)data, len);
CHECK(response == test_command); CHECK(response == test_command);
return command_result::OK; return command_result::OK;
}, 1000); }, 1000);
@ -71,7 +71,7 @@ TEST_CASE("DCE commands", "[esp_modem]")
const auto test_command = "Test\n"; const auto test_command = "Test\n";
auto ret = dce->command(test_command, [&](uint8_t *data, size_t len) { auto ret = dce->command(test_command, [&](uint8_t *data, size_t len) {
std::string response((char*)data, len); std::string response((char *)data, len);
CHECK(response == test_command); CHECK(response == test_command);
return command_result::OK; return command_result::OK;
}, 1000); }, 1000);
@ -114,7 +114,8 @@ TEST_CASE("DCE modes", "[esp_modem]")
CHECK(dce->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true); CHECK(dce->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true);
} }
TEST_CASE("DCE CMUX test", "[esp_modem]") { TEST_CASE("DCE CMUX test", "[esp_modem]")
{
auto term = std::make_unique<LoopbackTerm>(); auto term = std::make_unique<LoopbackTerm>();
auto dte = std::make_shared<DTE>(std::move(term)); auto dte = std::make_shared<DTE>(std::move(term));
CHECK(term == nullptr); CHECK(term == nullptr);

View File

@ -26,7 +26,7 @@ typedef DCE_T<NetModule> NetDCE;
class NetDCE_Factory: public Factory { class NetDCE_Factory: public Factory {
public: public:
template <typename T, typename ...Args> template <typename T, typename ...Args>
static DCE_T<T>* create(const config *cfg, Args&&... 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)...);
} }
@ -38,7 +38,7 @@ public:
class NetModule: public ModuleIf { class NetModule: public ModuleIf {
public: public:
explicit NetModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config *cfg): explicit NetModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config *cfg):
dte(std::move(dte)) {} dte(std::move(dte)) {}
bool setup_data_mode() override bool setup_data_mode() override
{ {
@ -62,9 +62,18 @@ public:
return dce == nullptr ? ESP_FAIL : ESP_OK; return dce == nullptr ? ESP_FAIL : ESP_OK;
} }
static void deinit() { delete dce; } static void deinit()
static void start() { dce->set_data(); } {
static void stop() { dce->exit_data(); } delete dce;
}
static void start()
{
dce->set_data();
}
static void stop()
{
dce->exit_data();
}
private: private:
static NetDCE *dce; static NetDCE *dce;

View File

@ -120,15 +120,15 @@ TEST_CASE("Disconnection test", "[esp_modem]")
extern "C" { extern "C" {
static void handle(int nr) static void handle(int nr)
{ {
ESP_LOGE(TAG, "Signal handler %d", nr); ESP_LOGE(TAG, "Signal handler %d", nr);
} }
_sig_func_ptr signal (int nr, _sig_func_ptr) _sig_func_ptr signal (int nr, _sig_func_ptr)
{ {
return handle; return handle;
} }
} }