update per design review

This commit is contained in:
David Cermak
2021-03-24 21:06:27 +01:00
parent a93cb68078
commit 8314e163fa
12 changed files with 228 additions and 94 deletions

View File

@ -1,4 +1,5 @@
set(srcs "src/esp_modem_dte.cpp"
"src/esp_modem_dce.cpp"
"src/esp_modem_netif.cpp"
"src/esp_modem_api.cpp"
"src/esp_modem_factory.cpp"

View File

@ -33,6 +33,9 @@ void ConsoleCommand::RegisterCommand(const char* command, const char* help, std:
case INT1:
common_arg = arg_int1(it.shortopts, it.longopts, it.datatype, it.glossary);
break;
case LIT0:
common_arg = arg_lit0(it.shortopts, it.longopts, it.glossary);
break;
}
if (common_arg) {
arg_table.emplace_back(common_arg);
@ -67,6 +70,13 @@ std::string ConsoleCommand::get_string(int index)
return std::string();
}
int ConsoleCommand::get_int(int index)
{
if (get_count(index) > 0) {
return *((struct arg_int *)arg_table[index])->ival;
}
return -1;
}
std::vector<ConsoleCommand*> ConsoleCommand::console_commands;

View File

@ -19,12 +19,16 @@ enum arg_type {
STR1,
INT0,
INT1,
LIT0,
ARG_END,
};
struct CommandArgs {
CommandArgs(arg_type t, const char * shopts, const char * lopts, const char * data, const char * glos):
type(t), shortopts(shopts), longopts(lopts), datatype(data), glossary(glos) {}
CommandArgs(arg_type t, const char * shopts, const char * lopts, const char * glos):
type(t), shortopts(shopts), longopts(lopts), datatype(nullptr), glossary(glos) {}
arg_type type;
const char *shortopts;
const char *longopts;
@ -48,8 +52,10 @@ public:
int get_count(int index);
template<typename T> int get_count_of(CommandArgs T::*member) { return get_count(index_arg(member)); }
template<typename T> std::string get_string_of(CommandArgs T::*member) { return get_string(index_arg(member)); }
template<typename T> int get_int_of(CommandArgs T::*member) { return get_int(index_arg(member)); }
std::string get_string(int index);
int get_int(int index);
private:
void RegisterCommand(const char* command, const char* help, std::vector<CommandArgs>& args);

View File

@ -323,6 +323,15 @@ static esp_console_repl_t *s_repl = NULL;
// return (char*)&((T*)nullptr->*member) - (char*)nullptr;
//}
#define CHECK_ERR(cmd, success_action) do { \
auto err = cmd; \
if (err == command_result::OK) { \
success_action; \
return 0; \
} else { \
ESP_LOGE(TAG, "Failed with %s", err == command_result::TIMEOUT ? "TIMEOUT":"ERROR"); \
return 1; \
} } while (0)
extern "C" void app_main(void)
{
@ -395,6 +404,7 @@ extern "C" void app_main(void)
}
return 0;
});
std::vector<CommandArgs> no_args;
ConsoleCommand ReadPinArgs("read_pin", "checks if SIM is unlocked", no_args, [&](ConsoleCommand *c){
bool pin_ok;
@ -409,10 +419,35 @@ extern "C" void app_main(void)
return 0;
});
ConsoleCommand GetModuleName("get_module_name", "reads the module name", no_args, [&](ConsoleCommand *c){
std::string 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()));
});
const struct GenericCommandArgs {
GenericCommandArgs():
cmd(STR1, nullptr, nullptr, "<command>", "AT command to send to the modem"),
timeout(INT1, "t", "timeout", "<timeout>", "command timeout"),
pattern(STR0, "p", "pattern", "<pattern>", "command response to wait for"),
no_cr(LIT0, "n", "no-cr", "not add trailing CR to the command") {}
CommandArgs cmd;
CommandArgs timeout;
CommandArgs pattern;
CommandArgs no_cr;
} send_cmd_args;
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 timeout = c->get_int_of(&GenericCommandArgs::timeout);
ESP_LOGI(TAG, "Sending command %s with timeout %d", cmd.c_str(), timeout);
CHECK_ERR(dce->command(cmd, nullptr, timeout),
ESP_LOGI(TAG, "OK"));
});
// start console REPL
ESP_ERROR_CHECK(esp_console_start_repl(s_repl));
ESP_LOGE(TAG, "Exit console!!!");
ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %d bytes)", __LINE__, esp_get_free_heap_size());
while(1) {
vTaskDelay(pdMS_TO_TICKS(50000));
ESP_LOGI(TAG, "working!");

View File

@ -18,8 +18,8 @@ std::shared_ptr<DTE> create_uart_dte(const esp_modem_dte_config *config);
std::shared_ptr<GenericModule> create_generic_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);
std::unique_ptr<DCE<GenericModule>> create_generic_dce_from_module(const std::shared_ptr<DTE>& dte, const std::shared_ptr<GenericModule>& dev, esp_netif_t *netif);
std::unique_ptr<DCE<SIM7600>> create_SIM7600_dce_from_module(const std::shared_ptr<DTE>& dte, const std::shared_ptr<SIM7600>& dev, esp_netif_t *netif);
std::unique_ptr<DCE> create_generic_dce_from_module(const std::shared_ptr<DTE>& dte, const std::shared_ptr<GenericModule>& dev, esp_netif_t *netif);
std::unique_ptr<DCE> create_SIM7600_dce_from_module(const std::shared_ptr<DTE>& dte, const std::shared_ptr<SIM7600>& dev, esp_netif_t *netif);
std::unique_ptr<DCE<SIM7600>> create_SIM7600_dce(const std::shared_ptr<DTE>& dte, esp_netif_t *netif, std::string &apn);
std::unique_ptr<DCE> create_SIM7600_dce(const std::shared_ptr<DTE>& dte, esp_netif_t *netif, std::string &apn);

View File

@ -1,65 +1,72 @@
#pragma once
#include <utility>
#include "cxx_include/esp_modem_netif.hpp"
#include "cxx_include/esp_modem_dce_module.hpp"
#include "generate/esp_modem_command_declare.inc"
template<class SpecificModule>
class DCE {
static_assert(std::is_base_of<ModuleIf, SpecificModule>::value, "DCE must be instantiated with Module class only");
namespace esp_modem::DCE {
class Modes {
public:
explicit DCE(const std::shared_ptr<DTE>& dte, std::shared_ptr<SpecificModule> device, esp_netif_t * netif):
dce_dte(dte), device(std::move(device)), ppp_netif(dte, netif)
{ }
void set_data() {
device->setup_data_mode();
device->set_mode(modem_mode::DATA_MODE);
dce_dte->set_mode(modem_mode::DATA_MODE);
ppp_netif.start();
}
void exit_data() {
ppp_netif.stop();
device->set_mode(modem_mode::COMMAND_MODE);
// uint8_t* data;
dce_dte->set_data_cb([&](size_t len) -> bool {
// auto actual_len = dce_dte->read(&data, 64);
// ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data", data, actual_len, ESP_LOG_INFO);
return false;
});
ppp_netif.wait_until_ppp_exits();
dce_dte->set_data_cb(nullptr);
dce_dte->set_mode(modem_mode::COMMAND_MODE);
Modes(): mode(modem_mode::COMMAND_MODE) {}
~Modes() = default;
bool set(DTE *dte, ModuleIf *module, PPP &netif, modem_mode m);
modem_mode get();
private:
modem_mode mode;
};
}
template<class SpecificModule>
class DCE_T {
static_assert(std::is_base_of<ModuleIf, SpecificModule>::value, "DCE must be instantiated with Module class only");
public:
explicit DCE_T(const std::shared_ptr<DTE>& dte, std::shared_ptr<SpecificModule> device, esp_netif_t * netif):
dte(dte), module(std::move(device)), netif(dte, netif)
{ }
~DCE_T() = default;
void set_data() { set_mode(modem_mode::DATA_MODE); }
void exit_data() { set_mode(modem_mode::COMMAND_MODE); }
void set_cmux() { set_mode(modem_mode::CMUX_MODE); }
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);
}
protected:
bool set_mode(modem_mode m) { return mode.set(dte.get(), module.get(), netif, m); }
std::shared_ptr<DTE> dte;
std::shared_ptr<SpecificModule> module;
PPP netif;
esp_modem::DCE::Modes mode;
};
class DCE: public DCE_T<GenericModule> {
public:
using DCE_T<GenericModule>::DCE_T;
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \
template <typename ...Agrs> \
return_type name(Agrs&&... args) \
{ \
return device->name(std::forward<Agrs>(args)...); \
return module->name(std::forward<Agrs>(args)...); \
}
DECLARE_ALL_COMMAND_APIS(forwards name(...) { device->name(...); } )
#undef ESP_MODEM_DECLARE_DCE_COMMAND
// template <typename ...Params>
// command_result get_module_name(Params&&... params)
// {
// return device->get_module_name(std::forward<Params>(params)...);
// }
// template <typename ...Params>
// command_result set_data_mode(Params&&... params)
// {
// return device->set_data_mode(std::forward<Params>(params)...);
// }
command_result command(const std::string& command, got_line_cb got_line, uint32_t time_ms) {
return dce_dte->command(command, got_line, time_ms);
}
void set_cmux() { device->set_mode(modem_mode::CMUX_MODE);
dce_dte->set_mode(modem_mode::CMUX_MODE); }
private:
std::shared_ptr<DTE> dce_dte;
std::shared_ptr<SpecificModule> device;
PPP ppp_netif;
};

View File

@ -38,10 +38,9 @@ public:
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \
template <typename ...Agrs> \
return_type name(Agrs&&... args) { return esp_modem::dce_commands::name(dte.get(), std::forward<Agrs>(args)...); }
virtual return_type name(__VA_ARGS__);
DECLARE_ALL_COMMAND_APIS(return_type name(...); )
DECLARE_ALL_COMMAND_APIS(virtual return_type name(...); )
#undef ESP_MODEM_DECLARE_DCE_COMMAND
@ -55,16 +54,16 @@ protected:
class SIM7600: public GenericModule {
using GenericModule::GenericModule;
public:
command_result get_module_name(std::string& name);
// command_result get_module_name(std::string& name) override;
};
class SIM800: public GenericModule {
using GenericModule::GenericModule;
public:
command_result get_module_name(std::string& name);
command_result get_module_name(std::string& name) override;
};
class BG96: public GenericModule {
public:
command_result get_module_name(std::string& name);
command_result get_module_name(std::string& name) override;
};

View File

@ -7,19 +7,19 @@
#ifdef __cplusplus
#include <string>
#define STRING_IN const std::string& string_in
#define STRING_OUT std::string& string_out
#define BOOL_IN const bool bool_in
#define BOOL_OUT bool& bool_out
#define STRUCT_OUT(struct_name) struct_name& struct_out
#define STRING_IN(x) const std::string& x
#define STRING_OUT(x) std::string& x
#define BOOL_IN(x) const bool x
#define BOOL_OUT(x) bool& x
#define STRUCT_OUT(struct_name, x) struct_name& x
#else
struct PdpContext;
#define STRING_IN const char* string_in
#define STRING_OUT char* string_out
#define BOOL_IN const bool bool_in
#define BOOL_OUT bool* bool_out
#define STRUCT_OUT(struct_name) struct struct_name* struct_out
#define STRING_IN(x) const char* x
#define STRING_OUT(x) char* x
#define BOOL_IN(x) const bool x
#define BOOL_OUT(x) bool* x
#define STRUCT_OUT(struct_name, x) struct struct_name* x
#endif
@ -33,40 +33,40 @@ struct PdpContext;
* @param pin Pin
*/ \
\
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, TEMPLATE_ARG, MUX_ARG, STRING_IN) \
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, MUX_ARG, STRING_IN(x)) \
/**
* @brief Checks if the SIM needs a PIN
*
* @param[out] pin_ok Pin
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, TEMPLATE_ARG, MUX_ARG, BOOL_OUT) \
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, 1, MUX_ARG, BOOL_OUT(x)) \
\
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, TEMPLATE_ARG, MUX_ARG, BOOL_IN) \
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, MUX_ARG, BOOL_IN(x)) \
\
ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, TEMPLATE_ARG, MUX_ARG) \
ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, 0, MUX_ARG) \
\
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, TEMPLATE_ARG, MUX_ARG, STRUCT_OUT(PdpContext)) \
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, 1, MUX_ARG, STRUCT_OUT(PdpContext, x)) \
\
ESP_MODEM_DECLARE_DCE_COMMAND(set_command_mode, command_result, TEMPLATE_ARG, MUX_ARG) \
ESP_MODEM_DECLARE_DCE_COMMAND(set_command_mode, command_result, 0, MUX_ARG) \
\
ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, TEMPLATE_ARG, MUX_ARG) \
ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, 0, MUX_ARG) \
\
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, TEMPLATE_ARG, MUX_ARG, STRING_OUT) \
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, 1, MUX_ARG, STRING_OUT(x)) \
\
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, TEMPLATE_ARG, MUX_ARG, STRING_OUT) \
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, MUX_ARG, STRING_OUT(x)) \
\
/**
* @brief Reads the module name
*
* @param[out] module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, TEMPLATE_ARG, MUX_ARG, STRING_OUT) \
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, 1, MUX_ARG, STRING_OUT(x)) \
\
/**
* @brief Sets the modem to data mode
*
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_data_mode, command_result, TEMPLATE_ARG, MUX_ARG)
ESP_MODEM_DECLARE_DCE_COMMAND(set_data_mode, command_result, 0, MUX_ARG)
// --- DCE command documentation starts here ---
#ifdef GENERATE_DOCS

View File

@ -22,29 +22,31 @@ std::shared_ptr<DTE> create_uart_dte(const esp_modem_dte_config *config)
}
template<typename SpecificModule>
std::unique_ptr<DCE<SpecificModule>> create_dce(const std::shared_ptr<DTE>& dte, const std::shared_ptr<SpecificModule>& dev, esp_netif_t *netif)
std::unique_ptr<DCE_T<SpecificModule>> create_dce(const std::shared_ptr<DTE>& dte, const std::shared_ptr<SpecificModule>& dev, esp_netif_t *netif)
{
TRY_CATCH_RET_NULL(
return std::make_unique<DCE<SpecificModule>>(dte, dev, netif);
return std::make_unique<DCE_T<SpecificModule>>(dte, dev, netif);
)
}
std::unique_ptr<DCE<GenericModule>> create_generic_dce_from_module(const std::shared_ptr<DTE>& dte, const std::shared_ptr<GenericModule>& dev, esp_netif_t *netif)
std::unique_ptr<DCE> create_generic_dce_from_module(const std::shared_ptr<DTE>& dte, const std::shared_ptr<GenericModule>& dev, esp_netif_t *netif)
{
return create_dce<GenericModule>(dte, dev, netif);
TRY_CATCH_RET_NULL(
return std::make_unique<DCE>(dte, dev, netif);
)
}
std::unique_ptr<DCE<SIM7600>> create_SIM7600_dce_from_module(const std::shared_ptr<DTE>& dte, const std::shared_ptr<SIM7600>& dev, esp_netif_t *netif)
{
return create_dce<SIM7600>(dte, dev, netif);
}
//std::unique_ptr<DCE<SIM7600>> create_SIM7600_dce_from_module(const std::shared_ptr<DTE>& dte, const std::shared_ptr<SIM7600>& dev, esp_netif_t *netif)
//{
// return create_dce<SIM7600>(dte, dev, netif);
//}
std::unique_ptr<DCE<SIM7600>> create_SIM7600_dce(const std::shared_ptr<DTE>& dte, esp_netif_t *netif, std::string &apn)
std::unique_ptr<DCE> create_SIM7600_dce(const std::shared_ptr<DTE>& dte, esp_netif_t *netif, std::string &apn)
{
auto pdp = std::make_unique<PdpContext>(apn);
auto dev = std::make_shared<SIM7600>(dte, std::move(pdp));
return create_dce<SIM7600>(dte, std::move(dev), netif);
return create_generic_dce_from_module(dte, std::move(dev), netif);
}
@ -87,7 +89,7 @@ extern "C" esp_modem_dce_t *esp_modem_new(const esp_modem_dte_config_t *config,
extern "C" void esp_modem_destroy(esp_modem_dce_t * dce)
{
assert(dce->modem_type == esp_modem_dce_wrap::MODEM_SIM7600);
auto dce_sim7600 = static_cast<DCE<SIM7600>*>(dce->dce_ptr);
auto dce_sim7600 = static_cast<DCE*>(dce->dce_ptr);
delete dce_sim7600;
delete dce;
}
@ -95,7 +97,7 @@ extern "C" void esp_modem_destroy(esp_modem_dce_t * dce)
extern "C" esp_err_t esp_modem_set_mode(esp_modem_dce_t * dce, esp_modem_dce_mode_t mode)
{
assert(dce->modem_type == esp_modem_dce_wrap::MODEM_SIM7600);
auto dce_sim7600 = static_cast<DCE<SIM7600>*>(dce->dce_ptr);
auto dce_sim7600 = static_cast<DCE*>(dce->dce_ptr);
if (mode == ESP_MODEM_MODE_DATA) {
dce_sim7600->set_data();
} else if (mode == ESP_MODEM_MODE_COMMAND) {
@ -109,7 +111,7 @@ extern "C" esp_err_t esp_modem_set_mode(esp_modem_dce_t * dce, esp_modem_dce_mod
extern "C" esp_err_t esp_modem_read_pin(esp_modem_dce_t * dce, bool &x)
{
assert(dce->modem_type == esp_modem_dce_wrap::MODEM_SIM7600);
auto dce_sim7600 = static_cast<DCE<SIM7600>*>(dce->dce_ptr);
auto dce_sim7600 = static_cast<DCE*>(dce->dce_ptr);
return command_response_to_esp_err(dce_sim7600->read_pin(x));
}

View File

@ -0,0 +1,60 @@
//
// Created by david on 3/24/21.
//
#include "cxx_include/esp_modem_dte.hpp"
#include "cxx_include/esp_modem_dce.hpp"
#include "esp_log.h"
namespace esp_modem::DCE {
bool Modes::set(DTE *dte, ModuleIf *device, PPP &netif, modem_mode m)
{
switch (m) {
case modem_mode::UNDEF:
break;
case modem_mode::COMMAND_MODE:
if (mode == modem_mode::COMMAND_MODE)
return false;
netif.stop();
device->set_mode(modem_mode::COMMAND_MODE);
uint8_t* data;
dte->set_data_cb([&](size_t len) -> bool {
auto actual_len = dte->read(&data, 64);
ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data", data, actual_len, ESP_LOG_INFO);
return false;
});
netif.wait_until_ppp_exits();
dte->set_data_cb(nullptr);
dte->set_mode(modem_mode::COMMAND_MODE);
mode = m;
return true;
case modem_mode::DATA_MODE:
if (mode == modem_mode::DATA_MODE)
return false;
device->setup_data_mode();
device->set_mode(modem_mode::DATA_MODE);
dte->set_mode(modem_mode::DATA_MODE);
netif.start();
mode = m;
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);
dte->set_mode(modem_mode::CMUX_MODE);
mode = modem_mode::COMMAND_MODE;
return true;
}
return false;
}
modem_mode Modes::get()
{
return mode;
}
}

View File

@ -3,12 +3,26 @@
//
#include "cxx_include/esp_modem_dce_module.hpp"
#include "generate/esp_modem_command_declare.inc"
command_result SIM7600::get_module_name(std::string& name)
{
name = "7600";
return command_result::OK;
}
#define ARGS0
#define ARGS1 , x
#define _ARGS(x) ARGS ## x
#define ARGS(x) _ARGS(x)
#define TEMPLATE_ARG
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, arg_nr, MUX_ARG, ...) \
return_type GenericModule::name(__VA_ARGS__) { return esp_modem::dce_commands::name(dte.get() ARGS(arg_nr) ); }
DECLARE_ALL_COMMAND_APIS(return_type name(...) { forwards to esp_modem::dce_commands::name(...) } )
#undef ESP_MODEM_DECLARE_DCE_COMMAND
//command_result SIM7600::get_module_name(std::string& name)
//{
// name = "7600";
// return command_result::OK;
//}
command_result SIM800::get_module_name(std::string& name)
{

View File

@ -53,7 +53,7 @@ esp_err_t PPP::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
// to notify the modem layer when switching modes
esp_netif_ppp_config_t ppp_config;
esp_netif_ppp_get_params(esp_netif, &ppp_config);
// esp_netif_ppp_get_params(esp_netif, &ppp_config);
if (!ppp_config.ppp_error_event_enabled) {
ppp_config.ppp_error_event_enabled = true;
esp_netif_ppp_set_params(esp_netif, &ppp_config);