CMUX: Fix batch write, add recovery

This commit is contained in:
David Cermak
2021-04-15 14:59:30 +02:00
parent d47cb69b20
commit 6065d89e18
13 changed files with 275 additions and 190 deletions

View File

@ -2,6 +2,9 @@
- :cpp:func:`esp_modem::DCE::set_pin` - :cpp:func:`esp_modem::DCE::set_pin`
- :cpp:func:`esp_modem::DCE::read_pin` - :cpp:func:`esp_modem::DCE::read_pin`
- :cpp:func:`esp_modem::DCE::set_echo` - :cpp:func:`esp_modem::DCE::set_echo`
- :cpp:func:`esp_modem::DCE::sms_txt_mode`
- :cpp:func:`esp_modem::DCE::sms_character_set`
- :cpp:func:`esp_modem::DCE::send_sms`
- :cpp:func:`esp_modem::DCE::resume_data_mode` - :cpp:func:`esp_modem::DCE::resume_data_mode`
- :cpp:func:`esp_modem::DCE::set_pdp_context` - :cpp:func:`esp_modem::DCE::set_pdp_context`
- :cpp:func:`esp_modem::DCE::set_command_mode` - :cpp:func:`esp_modem::DCE::set_command_mode`

View File

@ -1,51 +1,65 @@
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h // cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst // cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
// call parametrs by names for documentation
// --- DCE command documentation starts here --- // --- DCE command documentation starts here ---
/** /**
* @brief Sends the supplied PIN code * @brief Sets the supplied PIN code
* * @param[in] pin Pin
* @param pin Pin * @return OK, FAIL or TIMEOUT
* */command_result esp_modem_set_pin (const char* pin); /**
*/ command_result esp_modem_set_pin (const char* pin); /**
* @brief Checks if the SIM needs a PIN * @brief Checks if the SIM needs a PIN
* * @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
* @param[out] pin_ok Pin * @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_read_pin (bool* pin_ok); /** */ command_result esp_modem_read_pin (bool* pin_ok); /**
* @brief Reads the module name * @brief Sets echo mode
* * @param[in] echo_on true if echo mode on (repeats the commands)
* @param[out] name module name * @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_set_echo (const bool x); /** */ command_result esp_modem_set_echo (const bool echo_on); /**
* @brief Reads the module name * @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
* * @param[in] txt true if txt mode
* @param[out] name module name * @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_sms_txt_mode (const bool txt); /**
* @brief Sets the default (GSM) charater set
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_sms_character_set (); /**
* @brief Sends SMS message in txt mode
* @param[in] number Phone number to send the message to
* @param[in] message Text message to be sent
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_send_sms (const char* number, const char* message); /**
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_resume_data_mode (); /** */ command_result esp_modem_resume_data_mode (); /**
* @brief Reads the module name * @brief Sets php context
* * @param[in] x PdP context struct to setup modem cellular connection
* @param[out] name module name * @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_set_pdp_context (struct PdpContext* x); /** */ command_result esp_modem_set_pdp_context (struct PdpContext* x); /**
* @brief Reads the module name * @brief Switches to the command mode
* * @return OK, FAIL or TIMEOUT
* @param[out] name module name
*/ command_result esp_modem_set_command_mode (); /** */ command_result esp_modem_set_command_mode (); /**
* @brief Reads the module name * @brief Switches to the CMUX mode
* * @return OK, FAIL or TIMEOUT
* @param[out] name module name
*/ command_result esp_modem_set_cmux (); /** */ command_result esp_modem_set_cmux (); /**
* @brief Reads the IMSI number
* @param[out] imsi Module's IMSI number
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_get_imsi (char* imsi); /**
* @brief Reads the IMEI number
* @param[out] imei Module's IMEI number
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_get_imei (char* imei); /**
* @brief Reads the module name * @brief Reads the module name
*
* @param[out] name module name
*/ command_result esp_modem_get_imsi (char* x); /**
* @brief Reads the module name
*
* @param[out] name module name
*/ command_result esp_modem_get_imei (char* x); /**
* @brief Reads the module name
*
* @param[out] name module name * @param[out] name module name
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_get_module_name (char* name); /** */ command_result esp_modem_get_module_name (char* name); /**
* @brief Sets the modem to data mode * @brief Sets the modem to data mode
* * @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_set_data_mode (); /** */ command_result esp_modem_set_data_mode (); /**
* @brief Get Signal quality * @brief Get Signal quality
* * @param[out] rssi signal strength indication
*/ command_result esp_modem_get_signal_quality (int* x, int* y); * @param[out] ber channel bit error rate
* @return OK, FAIL or TIMEOUT
*/ command_result esp_modem_get_signal_quality (int* rssi, int* ber);

View File

@ -1,5 +1,9 @@
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h // cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst // cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
// call parametrs by names for documentation
// --- DCE command documentation starts here --- // --- DCE command documentation starts here ---
class esp_modem::DCE: public DCE_T<GenericModule> { class esp_modem::DCE: public DCE_T<GenericModule> {
@ -13,51 +17,61 @@ public:
/** /**
* @brief Sends the supplied PIN code * @brief Sets the supplied PIN code
* * @param[in] pin Pin
* @param pin Pin * @return OK, FAIL or TIMEOUT
* */command_result set_pin (const std::string& pin); /**
*/ command_result set_pin (const std::string& pin); /**
* @brief Checks if the SIM needs a PIN * @brief Checks if the SIM needs a PIN
* * @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
* @param[out] pin_ok Pin * @return OK, FAIL or TIMEOUT
*/ command_result read_pin (bool& pin_ok); /** */ command_result read_pin (bool& pin_ok); /**
* @brief Reads the module name * @brief Sets echo mode
* * @param[in] echo_on true if echo mode on (repeats the commands)
* @param[out] name module name * @return OK, FAIL or TIMEOUT
*/ command_result set_echo (const bool x); /** */ command_result set_echo (const bool echo_on); /**
* @brief Reads the module name * @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
* * @param[in] txt true if txt mode
* @param[out] name module name * @return OK, FAIL or TIMEOUT
*/ command_result sms_txt_mode (const bool txt); /**
* @brief Sets the default (GSM) charater set
* @return OK, FAIL or TIMEOUT
*/ command_result sms_character_set (); /**
* @brief Sends SMS message in txt mode
* @param[in] number Phone number to send the message to
* @param[in] message Text message to be sent
* @return OK, FAIL or TIMEOUT
*/ command_result send_sms (const std::string& number, const std::string& message); /**
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
* @return OK, FAIL or TIMEOUT
*/ command_result resume_data_mode (); /** */ command_result resume_data_mode (); /**
* @brief Reads the module name * @brief Sets php context
* * @param[in] x PdP context struct to setup modem cellular connection
* @param[out] name module name * @return OK, FAIL or TIMEOUT
*/ command_result set_pdp_context (PdpContext& x); /** */ command_result set_pdp_context (PdpContext& x); /**
* @brief Reads the module name * @brief Switches to the command mode
* * @return OK, FAIL or TIMEOUT
* @param[out] name module name
*/ command_result set_command_mode (); /** */ command_result set_command_mode (); /**
* @brief Reads the module name * @brief Switches to the CMUX mode
* * @return OK, FAIL or TIMEOUT
* @param[out] name module name
*/ command_result set_cmux (); /** */ command_result set_cmux (); /**
* @brief Reads the IMSI number
* @param[out] imsi Module's IMSI number
* @return OK, FAIL or TIMEOUT
*/ command_result get_imsi (std::string& imsi); /**
* @brief Reads the IMEI number
* @param[out] imei Module's IMEI number
* @return OK, FAIL or TIMEOUT
*/ command_result get_imei (std::string& imei); /**
* @brief Reads the module name * @brief Reads the module name
*
* @param[out] name module name
*/ command_result get_imsi (std::string& x); /**
* @brief Reads the module name
*
* @param[out] name module name
*/ command_result get_imei (std::string& x); /**
* @brief Reads the module name
*
* @param[out] name module name * @param[out] name module name
* @return OK, FAIL or TIMEOUT
*/ command_result get_module_name (std::string& name); /** */ command_result get_module_name (std::string& name); /**
* @brief Sets the modem to data mode * @brief Sets the modem to data mode
* * @return OK, FAIL or TIMEOUT
*/ command_result set_data_mode (); /** */ command_result set_data_mode (); /**
* @brief Get Signal quality * @brief Get Signal quality
* * @param[out] rssi signal strength indication
*/ command_result get_signal_quality (int& x, int& y); * @param[out] ber channel bit error rate
* @return OK, FAIL or TIMEOUT
*/ command_result get_signal_quality (int& rssi, int& ber);
}; };

View File

@ -24,7 +24,7 @@ using namespace esp_modem;
static const char *TAG = "cmux_example"; static const char *TAG = "cmux_example";
static EventGroupHandle_t event_group = NULL; static EventGroupHandle_t event_group = nullptr;
static const int CONNECT_BIT = BIT0; static const int CONNECT_BIT = BIT0;
static const int STOP_BIT = BIT1; static const int STOP_BIT = BIT1;
static const int GOT_DATA_BIT = BIT2; static const int GOT_DATA_BIT = BIT2;
@ -141,6 +141,17 @@ extern "C" void app_main(void)
assert(esp_netif); assert(esp_netif);
auto dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif); auto dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif);
/// TEST
{
// std::string str;
// dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
// while (1) {
// dce->get_imsi(str);
// std::cout << "Modem IMSI number:" << str << "|" << std::endl;
// }
}
// return;
//// TEST
dce->set_command_mode(); dce->set_command_mode();
std::string str; std::string str;
@ -163,7 +174,7 @@ extern "C" void app_main(void)
esp_mqtt_client_config_t mqtt_config = { }; esp_mqtt_client_config_t mqtt_config = { };
mqtt_config.uri = BROKER_URL; mqtt_config.uri = BROKER_URL;
esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config); esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config);
esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, NULL); esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, nullptr);
esp_mqtt_client_start(mqtt_client); esp_mqtt_client_start(mqtt_client);
EventBits_t got_data = 0; EventBits_t got_data = 0;
@ -173,13 +184,11 @@ extern "C" void app_main(void)
got_data = xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(500)); got_data = xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(500));
} }
esp_mqtt_client_destroy(mqtt_client); esp_mqtt_client_destroy(mqtt_client);
dce->get_imsi(str);
std::cout << "Modem IMSI number:" << str << "|" << std::endl;
vTaskDelay(pdMS_TO_TICKS(1000));
while (true) { // reading IMSI number after ESP_LOGI(TAG, "Example finished");
dce->get_imsi(str);
std::cout << "Modem IMSI number:" << str << "|" << std::endl;
vTaskDelay(pdMS_TO_TICKS(1000));
}
} }

View File

@ -34,7 +34,7 @@ namespace dce_commands {
/** /**
* @brief Declaration of all commands is generated from esp_modem_command_declare.inc * @brief Declaration of all commands is generated from esp_modem_command_declare.inc
*/ */
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \ #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, ...);)

View File

@ -95,7 +95,7 @@ class DCE: public DCE_T<GenericModule> {
public: public:
using DCE_T<GenericModule>::DCE_T; using DCE_T<GenericModule>::DCE_T;
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \ #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
template <typename ...Agrs> \ template <typename ...Agrs> \
return_type name(Agrs&&... args) \ return_type name(Agrs&&... args) \
{ \ { \

View File

@ -71,7 +71,7 @@ public:
} }
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \ #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
virtual return_type name(__VA_ARGS__); virtual return_type name(__VA_ARGS__);
DECLARE_ALL_COMMAND_APIS(virtual return_type name(...); ) DECLARE_ALL_COMMAND_APIS(virtual return_type name(...); )

View File

@ -23,7 +23,7 @@ extern "C" {
#endif #endif
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \ #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
esp_err_t esp_modem_ ## name(esp_modem_dce_t *dce, ##__VA_ARGS__); esp_err_t esp_modem_ ## name(esp_modem_dce_t *dce, ##__VA_ARGS__);
DECLARE_ALL_COMMAND_APIS(declares esp_modem_<API>(esp_modem_t * dce, ...);) DECLARE_ALL_COMMAND_APIS(declares esp_modem_<API>(esp_modem_t * dce, ...);)

View File

@ -15,12 +15,11 @@
#ifndef _ESP_MODEM_COMMAND_DECLARE_INC_ #ifndef _ESP_MODEM_COMMAND_DECLARE_INC_
#define _ESP_MODEM_COMMAND_DECLARE_INC_ #define _ESP_MODEM_COMMAND_DECLARE_INC_
#if GENERATE_DOCS
#define _ARG(param, name) name
#else
#define _ARG(param, name) param
#endif
// Parameters
// * handle different parameters for C++ and C API
// * make parameter unique names, so they could be easily referenced and forwarded
#define _ARG(param, name) param
#ifdef __cplusplus #ifdef __cplusplus
#include <string> #include <string>
#define STRING_IN(param, name) const std::string& _ARG(param, name) #define STRING_IN(param, name) const std::string& _ARG(param, name)
@ -39,114 +38,127 @@
#define STRUCT_OUT(struct_name, x) struct struct_name* x #define STRUCT_OUT(struct_name, x) struct struct_name* x
#endif #endif
#define _ESP_MODEM_COMMAND_DECLARE_INC_
#define ESP_MODEM_DEFINE_DCE_COMMAND(...) ESP_MODEM_DECLARE_DCE_COMMAND(##__VA_ARGS__)
#define DEFINE_ALL_COMMAND_APIS() DECLARE_ALL_COMMAND_APIS()
#define DECLARE_ALL_COMMAND_APIS(...) \ #define DECLARE_ALL_COMMAND_APIS(...) \
/** /**
* @brief Sends the supplied PIN code * @brief Sets the supplied PIN code
* * @param[in] pin Pin
* @param pin Pin * @return OK, FAIL or TIMEOUT
* */\
*/ \ ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, STRING_IN(x, pin)) \
\
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, MUX_ARG, STRING_IN(x, pin)) \
\
\ \
/** /**
* @brief Checks if the SIM needs a PIN * @brief Checks if the SIM needs a PIN
* * @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
* @param[out] pin_ok Pin * @return OK, FAIL or TIMEOUT
*/ \ */ \
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, 1, MUX_ARG, BOOL_OUT(x, pin_ok)) \ ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, 1, BOOL_OUT(x, pin_ok)) \
\
/**
* @brief Sets echo mode
* @param[in] echo_on true if echo mode on (repeats the commands)
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, BOOL_IN(x, echo_on)) \
\
/**
* @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
* @param[in] txt true if txt mode
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(sms_txt_mode, command_result, 1, BOOL_IN(x, txt)) \
\
/**
* @brief Sets the default (GSM) charater set
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(sms_character_set, command_result, 0) \
\
/**
* @brief Sends SMS message in txt mode
* @param[in] number Phone number to send the message to
* @param[in] message Text message to be sent
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(send_sms, command_result, 2, STRING_IN(x, number), STRING_IN(y, message)) \
\
/**
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, 0) \
\
/**
* @brief Sets php context
* @param[in] x PdP context struct to setup modem cellular connection
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, 1, STRUCT_OUT(PdpContext, x)) \
\
/**
* @brief Switches to the command mode
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_command_mode, command_result, 0) \
\
/**
* @brief Switches to the CMUX mode
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, 0) \
\
/**
* @brief Reads the IMSI number
* @param[out] imsi Module's IMSI number
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, 1, STRING_OUT(x, imsi)) \
\
/**
* @brief Reads the IMEI number
* @param[out] imei Module's IMEI number
* @return OK, FAIL or TIMEOUT
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, STRING_OUT(x, imei)) \
\ \
/** /**
* @brief Reads the module name * @brief Reads the module name
*
* @param[out] name module name * @param[out] name module name
* @return OK, FAIL or TIMEOUT
*/ \ */ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, MUX_ARG, BOOL_IN(x, echo_on)) \ ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, 1, STRING_OUT(x, name)) \
ESP_MODEM_DECLARE_DCE_COMMAND(sms_txt_mode, command_result, 1, MUX_ARG, BOOL_IN(x, txt)) \
ESP_MODEM_DECLARE_DCE_COMMAND(sms_character_set, command_result, 0, MUX_ARG) \
ESP_MODEM_DECLARE_DCE_COMMAND(send_sms, command_result, 2, MUX_ARG, STRING_IN(x, number), STRING_IN(y, message)) \
\
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, 0, MUX_ARG) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, 1, MUX_ARG, STRUCT_OUT(PdpContext, x)) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_command_mode, command_result, 0, MUX_ARG) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, 0, MUX_ARG) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, 1, MUX_ARG, STRING_OUT(x, imsi)) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, MUX_ARG, STRING_OUT(x, name)) \
\
/**
* @brief Reads the module name
*
* @param[out] name module name
*/ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, 1, MUX_ARG, STRING_OUT(x, name)) \
\ \
/** /**
* @brief Sets the modem to data mode * @brief Sets the modem to data mode
* * @return OK, FAIL or TIMEOUT
*/ \ */ \
ESP_MODEM_DECLARE_DCE_COMMAND(set_data_mode, command_result, 0, MUX_ARG) \ ESP_MODEM_DECLARE_DCE_COMMAND(set_data_mode, command_result, 0) \
\ \
/** /**
* @brief Get Signal quality * @brief Get Signal quality
* * @param[out] rssi signal strength indication
* @param[out] ber channel bit error rate
* @return OK, FAIL or TIMEOUT
*/ \ */ \
ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, MUX_ARG, INT_OUT(x, rssi), INT_OUT(y, ber)) ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, INT_OUT(x, rssi), INT_OUT(y, ber))
#ifdef GENERATE_DOCS #ifdef GENERATE_DOCS
// cat ../include/generate/esp_modem_command_declare.inc | clang++ -E -P -CC -xc++ -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' // cat ../include/generate/esp_modem_command_declare.inc | clang++ -E -P -CC -xc++ -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p'
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h // cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst // cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
// call parametrs by names for documentation
#undef _ARG
#define _ARG(param, name) name
// --- DCE command documentation starts here --- // --- DCE command documentation starts here ---
#ifdef __cplusplus #ifdef __cplusplus
class esp_modem::DCE: public DCE_T<GenericModule> { class esp_modem::DCE: public DCE_T<GenericModule> {
public: public:
using DCE_T<GenericModule>::DCE_T; using DCE_T<GenericModule>::DCE_T;
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) return_type name (__VA_ARGS__); #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, ...) return_type name (__VA_ARGS__);
#elif defined(GENERATE_RST_LINKS) #elif defined(GENERATE_RST_LINKS)
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) NL- :cpp:func:`esp_modem::DCE::name` #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, ...) NL- :cpp:func:`esp_modem::DCE::name`
#else #else
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) return_type esp_modem_ ## name (__VA_ARGS__); #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, ...) return_type esp_modem_ ## name (__VA_ARGS__);
#endif #endif
DECLARE_ALL_COMMAND_APIS() DECLARE_ALL_COMMAND_APIS()

View File

@ -18,10 +18,8 @@
#include "esp_log.h" #include "esp_log.h"
#include "cxx_include/esp_modem_api.hpp" #include "cxx_include/esp_modem_api.hpp"
#include "cxx_include/esp_modem_dce_factory.hpp" #include "cxx_include/esp_modem_dce_factory.hpp"
#include "esp_modem_c_api_types.h"
#include "esp_modem_config.h" #include "esp_modem_config.h"
#include "exception_stub.hpp" #include "exception_stub.hpp"
#include "cstring"
namespace esp_modem { namespace esp_modem {

View File

@ -103,24 +103,43 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
} }
ESP_LOG_BUFFER_HEXDUMP("Received", data, actual_len, ESP_LOG_DEBUG); ESP_LOG_BUFFER_HEXDUMP("Received", data, actual_len, ESP_LOG_DEBUG);
uint8_t* frame = data; uint8_t* frame = data;
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:
// TODO: Implement recovery, looking for SOF_MARKER's if (frame[0] == SOF_MARKER) {
break; // already init state
state = cmux_state::INIT;
break;
}
recover_ptr = static_cast<uint8_t*>(memchr(frame, SOF_MARKER, available_len));
if (recover_ptr && available_len > recover_ptr - frame) {
available_len -= (recover_ptr - frame);
frame = recover_ptr;
state = cmux_state::INIT;
ESP_LOGD("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: case cmux_state::INIT:
if (frame[0] != SOF_MARKER) { if (frame[0] != SOF_MARKER) {
ESP_LOGW("CMUX", "TODO: Recover!"); ESP_LOGI("CMUX", "Protocol mismatch!");
return true; state = cmux_state::RECOVER;
break;
} }
if (available_len > 1 && frame[1] == SOF_MARKER) { if (available_len > 1 && frame[1] == SOF_MARKER) {
ESP_LOGI("CMUX", "Empty frame");
// empty frame // empty frame
available_len -= 2; available_len -= 1;
frame += 2; frame += 1;
break; break;
} }
state = cmux_state::HEADER; state = cmux_state::HEADER;
@ -140,7 +159,7 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
dlci = frame_header[1] >> 2; dlci = frame_header[1] >> 2;
type = frame_header[2]; type = frame_header[2];
payload_len = (frame_header[3] >> 1); payload_len = (frame_header[3] >> 1);
ESP_LOGI("CMUX", "CMUX FR: A:%02x T:%02x L:%d", dlci, type, payload_len); ESP_LOGD("CMUX", "CMUX FR: A:%02x T:%02x L:%d", dlci, type, payload_len);
frame += payload_offset; frame += payload_offset;
available_len -= payload_offset; available_len -= payload_offset;
state = cmux_state::PAYLOAD; state = cmux_state::PAYLOAD;
@ -169,8 +188,9 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
footer_offset = std::min(available_len, 6 - frame_header_offset); footer_offset = std::min(available_len, 6 - frame_header_offset);
memcpy(frame_header + frame_header_offset, frame, footer_offset); memcpy(frame_header + frame_header_offset, frame, footer_offset);
if (frame_header[5] != SOF_MARKER) { if (frame_header[5] != SOF_MARKER) {
ESP_LOGW("CMUX", "TODO: Recover!"); ESP_LOGI("CMUX", "Protocol mismatch!");
return true; state = cmux_state::RECOVER;
break;
} }
if (payload_len == 0) { if (payload_len == 0) {
data_available(frame_header, 0); // Null payload data_available(frame_header, 0); // Null payload
@ -190,6 +210,7 @@ void CMux::init()
frame_header_offset = 0; frame_header_offset = 0;
state = cmux_state::INIT; state = cmux_state::INIT;
term->set_read_cb([this](uint8_t *data, size_t len) { term->set_read_cb([this](uint8_t *data, size_t len) {
Scoped<Lock> l(lock);
this->on_cmux(data, len); this->on_cmux(data, len);
return false; return false;
}); });
@ -203,22 +224,31 @@ void CMux::init()
int CMux::write(int virtual_term, uint8_t *data, size_t len) int CMux::write(int virtual_term, uint8_t *data, size_t len)
{ {
const size_t cmux_max_len = 127;
Scoped<Lock> l(lock); Scoped<Lock> l(lock);
int i = virtual_term + 1; int i = virtual_term + 1;
uint8_t frame[6]; size_t need_write = len;
frame[0] = SOF_MARKER; while (need_write > 0) {
frame[1] = (i << 2) + 1; size_t batch_len = need_write;
frame[2] = FT_UIH; if (batch_len > cmux_max_len)
frame[3] = (len << 1) + 1; batch_len = cmux_max_len;
frame[4] = 0xFF - fcs_crc(frame); uint8_t frame[6];
frame[5] = SOF_MARKER; frame[0] = SOF_MARKER;
frame[1] = (i << 2) + 1;
frame[2] = FT_UIH;
frame[3] = (batch_len << 1) + 1;
frame[4] = 0xFF - fcs_crc(frame);
frame[5] = SOF_MARKER;
term->write(frame, 4); term->write(frame, 4);
term->write(data, len); term->write(data, batch_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, 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;
data += batch_len;
}
return len; return len;
} }

View File

@ -28,7 +28,7 @@ GenericModule::GenericModule(std::shared_ptr<DTE> dte, const dce_config *config)
#define _ARGS(x) ARGS ## x #define _ARGS(x) ARGS ## x
#define ARGS(x) _ARGS(x) #define ARGS(x) _ARGS(x)
#define TEMPLATE_ARG #define TEMPLATE_ARG
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, arg_nr, MUX_ARG, ...) \ #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, arg_nr, ...) \
return_type GenericModule::name(__VA_ARGS__) { return esp_modem::dce_commands::name(dte.get() ARGS(arg_nr) ); } return_type GenericModule::name(__VA_ARGS__) { return esp_modem::dce_commands::name(dte.get() ARGS(arg_nr) ); }
DECLARE_ALL_COMMAND_APIS(return_type name(...) { DECLARE_ALL_COMMAND_APIS(return_type name(...) {

View File

@ -95,6 +95,11 @@ void Netif::stop() {
} }
Netif::~Netif() { Netif::~Netif() {
if (signal.is_any(PPP_STARTED)) {
esp_netif_action_stop(driver.base.netif, nullptr, 0, nullptr);
signal.clear(PPP_STARTED);
signal.wait(PPP_EXIT, 30000);
}
esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed); esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed);
esp_event_handler_unregister(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected); esp_event_handler_unregister(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected);
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);