mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-18 13:02:21 +02:00
C API cleanup, add SMS support
This commit is contained in:
@ -16,6 +16,7 @@ set(srcs ${platform_srcs}
|
|||||||
"src/esp_modem_dte.cpp"
|
"src/esp_modem_dte.cpp"
|
||||||
"src/esp_modem_dce.cpp"
|
"src/esp_modem_dce.cpp"
|
||||||
"src/esp_modem_api.cpp"
|
"src/esp_modem_api.cpp"
|
||||||
|
"src/esp_modem_c_api.cpp"
|
||||||
"src/esp_modem_factory.cpp"
|
"src/esp_modem_factory.cpp"
|
||||||
"src/esp_modem_cmux.cpp"
|
"src/esp_modem_cmux.cpp"
|
||||||
"src/esp_modem_command_library.cpp"
|
"src/esp_modem_command_library.cpp"
|
||||||
|
@ -147,6 +147,16 @@ void app_main(void)
|
|||||||
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
|
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
|
||||||
assert(esp_netif);
|
assert(esp_netif);
|
||||||
esp_modem_dce_t *dce = esp_modem_new(&dte_config, &dce_config, esp_netif);
|
esp_modem_dce_t *dce = esp_modem_new(&dte_config, &dce_config, esp_netif);
|
||||||
|
|
||||||
|
// check if PIN needed
|
||||||
|
bool pin_ok = false;
|
||||||
|
if (esp_modem_read_pin(dce, &pin_ok) == ESP_OK && pin_ok == false) {
|
||||||
|
if (esp_modem_set_pin(dce, "1234") == ESP_OK) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
int rssi, ber;
|
int rssi, ber;
|
||||||
esp_err_t err = esp_modem_get_signal_quality(dce, &rssi, &ber);
|
esp_err_t err = esp_modem_get_signal_quality(dce, &rssi, &ber);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
@ -155,6 +165,20 @@ void app_main(void)
|
|||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber);
|
ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber);
|
||||||
|
|
||||||
|
#if CONFIG_EXAMPLE_SEND_MSG
|
||||||
|
if (esp_modem_sms_txt_mode(dce, true) != ESP_OK || esp_modem_sms_character_set(dce) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Setting text mode or GSM character set failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = esp_modem_send_sms(dce, CONFIG_EXAMPLE_SEND_MSG_PEER_PHONE_NUMBER, "Text message from esp-modem");
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_modem_send_sms() failed with %d", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
err = esp_modem_set_mode(dce, ESP_MODEM_MODE_DATA);
|
err = esp_modem_set_mode(dce, ESP_MODEM_MODE_DATA);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "esp_modem_set_mode(ESP_MODEM_MODE_DATA) failed with %d", err);
|
ESP_LOGE(TAG, "esp_modem_set_mode(ESP_MODEM_MODE_DATA) failed with %d", err);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
version: "0.0.6"
|
version: "0.1.1"
|
||||||
name: esp_modem
|
targets:
|
||||||
|
- esp32
|
||||||
description: esp modem
|
description: esp modem
|
||||||
|
@ -109,9 +109,9 @@ private:
|
|||||||
*/
|
*/
|
||||||
enum class Modem {
|
enum class Modem {
|
||||||
GenericModule, /*!< Default generic module with the most common commands */
|
GenericModule, /*!< Default generic module with the most common commands */
|
||||||
SIM800, /*!< Derived from the GenericModule with specifics applied to SIM800 model */
|
|
||||||
SIM7600, /*!< Derived from the GenericModule, specifics applied to SIM7600 model */
|
SIM7600, /*!< Derived from the GenericModule, specifics applied to SIM7600 model */
|
||||||
BG96, /*!< Derived from the GenericModule, specifics applied to BG69 model */
|
BG96, /*!< Derived from the GenericModule, specifics applied to BG69 model */
|
||||||
|
SIM800, /*!< Derived from the GenericModule with specifics applied to SIM800 model */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,6 +201,24 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ...Args>
|
||||||
|
DCE* build(const config *cfg, Args&&... args)
|
||||||
|
{
|
||||||
|
switch (m) {
|
||||||
|
case Modem::SIM800:
|
||||||
|
return build<SIM800>(cfg, std::forward<Args>(args)...);
|
||||||
|
case Modem::SIM7600:
|
||||||
|
return build<SIM7600>(cfg, std::forward<Args>(args)...);
|
||||||
|
case Modem::BG96:
|
||||||
|
return build<BG96>(cfg, std::forward<Args>(args)...);
|
||||||
|
case Modem::GenericModule:
|
||||||
|
return build<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Modem m;
|
Modem m;
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms) override;
|
command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms) override;
|
||||||
|
command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms, const char separator) override;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -75,6 +75,7 @@ public:
|
|||||||
* @param time_ms timeout in milliseconds
|
* @param time_ms timeout in milliseconds
|
||||||
* @return OK, FAIL or TIMEOUT
|
* @return OK, FAIL or TIMEOUT
|
||||||
*/
|
*/
|
||||||
|
virtual command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms, const char separator) = 0;
|
||||||
virtual command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms) = 0;
|
virtual command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,7 +43,18 @@ typedef enum esp_modem_dce_mode
|
|||||||
} esp_modem_dce_mode_t;
|
} esp_modem_dce_mode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a DCE handle for new modem API
|
* @brief DCE devices: Enum list of supported devices
|
||||||
|
*/
|
||||||
|
typedef enum esp_modem_dce_device
|
||||||
|
{
|
||||||
|
ESP_MODEM_DCE_GENETIC, /**< The most generic device */
|
||||||
|
ESP_MODEM_DCE_SIM7600,
|
||||||
|
ESP_MODEM_DCE_BG96,
|
||||||
|
ESP_MODEM_DCE_SIM800,
|
||||||
|
} esp_modem_dce_device_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a generic DCE handle for new modem API
|
||||||
*
|
*
|
||||||
* @param dte_config DTE configuration (UART config for now)
|
* @param dte_config DTE configuration (UART config for now)
|
||||||
* @param dce_config DCE configuration
|
* @param dce_config DCE configuration
|
||||||
@ -53,6 +64,18 @@ typedef enum esp_modem_dce_mode
|
|||||||
*/
|
*/
|
||||||
esp_modem_dce_t *esp_modem_new(const esp_modem_dte_config_t *dte_config, const esp_modem_dce_config_t *dce_config, esp_netif_t *netif);
|
esp_modem_dce_t *esp_modem_new(const esp_modem_dte_config_t *dte_config, const esp_modem_dce_config_t *dce_config, esp_netif_t *netif);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a DCE handle using the supplied device
|
||||||
|
*
|
||||||
|
* @param module Specific device for creating this DCE
|
||||||
|
* @param dte_config DTE configuration (UART config for now)
|
||||||
|
* @param dce_config DCE configuration
|
||||||
|
* @param netif Network interface handle for the data mode
|
||||||
|
*
|
||||||
|
* @return DCE pointer on success, NULL on failure
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroys modem's DCE handle
|
* @brief Destroys modem's DCE handle
|
||||||
*
|
*
|
||||||
|
@ -16,26 +16,26 @@
|
|||||||
#define _ESP_MODEM_COMMAND_DECLARE_INC_
|
#define _ESP_MODEM_COMMAND_DECLARE_INC_
|
||||||
|
|
||||||
#if GENERATE_DOCS
|
#if GENERATE_DOCS
|
||||||
#define _ARG(arg) arg
|
#define _ARG(param, name) name
|
||||||
#else
|
#else
|
||||||
#define _ARG(arg) x
|
#define _ARG(param, name) param
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include <string>
|
#include <string>
|
||||||
#define STRING_IN(x) const std::string& _ARG(x)
|
#define STRING_IN(param, name) const std::string& _ARG(param, name)
|
||||||
#define STRING_OUT(x) std::string& _ARG(x)
|
#define STRING_OUT(param, name) std::string& _ARG(param, name)
|
||||||
#define BOOL_IN(x) const bool x
|
#define BOOL_IN(param, name) const bool _ARG(param, name)
|
||||||
#define BOOL_OUT(x) bool& _ARG(x)
|
#define BOOL_OUT(param, name) bool& _ARG(param, name)
|
||||||
#define INT_OUT(x) int& x
|
#define INT_OUT(param, name) int& _ARG(param, name)
|
||||||
|
|
||||||
#define STRUCT_OUT(struct_name, x) struct_name& x
|
#define STRUCT_OUT(struct_name, x) struct_name& x
|
||||||
#else
|
#else
|
||||||
#define STRING_IN(x) const char* x
|
#define STRING_IN(param, name) const char* _ARG(param, name)
|
||||||
#define STRING_OUT(x) char* x
|
#define STRING_OUT(param, name) char* _ARG(param, name)
|
||||||
#define BOOL_IN(x) const bool x
|
#define BOOL_IN(param, name) const bool _ARG(param, name)
|
||||||
#define BOOL_OUT(x) bool* x
|
#define BOOL_OUT(param, name) bool* _ARG(param, name)
|
||||||
#define INT_OUT(x) int* x
|
#define INT_OUT(param, name) int* _ARG(param, name)
|
||||||
#define STRUCT_OUT(struct_name, x) struct struct_name* x
|
#define STRUCT_OUT(struct_name, x) struct struct_name* x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -51,7 +51,7 @@
|
|||||||
*
|
*
|
||||||
*/ \
|
*/ \
|
||||||
\
|
\
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, MUX_ARG, STRING_IN(pin)) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, MUX_ARG, STRING_IN(x, pin)) \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
/**
|
/**
|
||||||
@ -59,14 +59,18 @@ ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, MUX_ARG, STRING_IN(pi
|
|||||||
*
|
*
|
||||||
* @param[out] pin_ok Pin
|
* @param[out] pin_ok Pin
|
||||||
*/ \
|
*/ \
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, 1, MUX_ARG, BOOL_OUT(pin_ok)) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, 1, MUX_ARG, BOOL_OUT(x, pin_ok)) \
|
||||||
\
|
\
|
||||||
/**
|
/**
|
||||||
* @brief Reads the module name
|
* @brief Reads the module name
|
||||||
*
|
*
|
||||||
* @param[out] name module name
|
* @param[out] name module name
|
||||||
*/ \
|
*/ \
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, MUX_ARG, BOOL_IN(x)) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, MUX_ARG, BOOL_IN(x, echo_on)) \
|
||||||
|
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
|
* @brief Reads the module name
|
||||||
@ -101,21 +105,21 @@ ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, 0, MUX_ARG) \
|
|||||||
*
|
*
|
||||||
* @param[out] name module name
|
* @param[out] name module name
|
||||||
*/ \
|
*/ \
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, 1, MUX_ARG, STRING_OUT(x)) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, 1, MUX_ARG, STRING_OUT(x, imsi)) \
|
||||||
\
|
\
|
||||||
/**
|
/**
|
||||||
* @brief Reads the module name
|
* @brief Reads the module name
|
||||||
*
|
*
|
||||||
* @param[out] name module name
|
* @param[out] name module name
|
||||||
*/ \
|
*/ \
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, MUX_ARG, STRING_OUT(x)) \
|
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, MUX_ARG, STRING_OUT(x, name)) \
|
||||||
\
|
\
|
||||||
/**
|
/**
|
||||||
* @brief Reads the module name
|
* @brief Reads the module name
|
||||||
*
|
*
|
||||||
* @param[out] name module name
|
* @param[out] name module name
|
||||||
*/ \
|
*/ \
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, 1, MUX_ARG, STRING_OUT(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
|
||||||
@ -127,7 +131,7 @@ ESP_MODEM_DECLARE_DCE_COMMAND(set_data_mode, command_result, 0, MUX_ARG) \
|
|||||||
* @brief Get Signal quality
|
* @brief Get Signal quality
|
||||||
*
|
*
|
||||||
*/ \
|
*/ \
|
||||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, MUX_ARG, INT_OUT(x), INT_OUT(y))
|
ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, MUX_ARG, 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'
|
||||||
|
@ -23,12 +23,13 @@
|
|||||||
#include "exception_stub.hpp"
|
#include "exception_stub.hpp"
|
||||||
#include "cstring"
|
#include "cstring"
|
||||||
|
|
||||||
|
|
||||||
namespace esp_modem {
|
namespace esp_modem {
|
||||||
|
|
||||||
struct PdpContext;
|
struct PdpContext;
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||||
static const char *TAG = "modem_api";
|
static const char *TAG = "modem_api";
|
||||||
|
#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(
|
||||||
@ -58,86 +59,3 @@ std::unique_ptr<DCE> create_BG96_dce(const dce_config *config, std::shared_ptr<D
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace esp_modem
|
} // namespace esp_modem
|
||||||
|
|
||||||
//
|
|
||||||
// C API definitions
|
|
||||||
using namespace esp_modem;
|
|
||||||
|
|
||||||
struct esp_modem_dce_wrap // need to mimic the polymorphic dispatch as CPP uses templated dispatch
|
|
||||||
{
|
|
||||||
enum esp_modem_t { MODEM_SIM7600, MODEM_SIM800, MODEM_BG96 } modem_type;
|
|
||||||
void * dce_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline esp_err_t command_response_to_esp_err(command_result res)
|
|
||||||
{
|
|
||||||
switch (res) {
|
|
||||||
case command_result::OK:
|
|
||||||
return ESP_OK;
|
|
||||||
case command_result::FAIL:
|
|
||||||
return ESP_FAIL;
|
|
||||||
case command_result::TIMEOUT:
|
|
||||||
return ESP_ERR_TIMEOUT;
|
|
||||||
}
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" esp_modem_dce_t *esp_modem_new(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;
|
|
||||||
if (dce_wrap == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
auto dte = create_uart_dte(dte_config);
|
|
||||||
auto dce = create_SIM7600_dce(dce_config, dte, netif);
|
|
||||||
dce_wrap->modem_type = esp_modem_dce_wrap::MODEM_SIM7600;
|
|
||||||
dce_wrap->dce_ptr = dce.release();
|
|
||||||
return dce_wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
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*>(dce->dce_ptr);
|
|
||||||
delete dce_sim7600;
|
|
||||||
delete 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*>(dce->dce_ptr);
|
|
||||||
if (mode == ESP_MODEM_MODE_DATA) {
|
|
||||||
dce_sim7600->set_data();
|
|
||||||
} else if (mode == ESP_MODEM_MODE_COMMAND) {
|
|
||||||
dce_sim7600->exit_data();
|
|
||||||
} else {
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
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*>(dce->dce_ptr);
|
|
||||||
return command_response_to_esp_err(dce_sim7600->read_pin(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" esp_err_t esp_modem_get_signal_quality(esp_modem_dce_t * dce, int *rssi, int *ber)
|
|
||||||
{
|
|
||||||
assert(dce->modem_type == esp_modem_dce_wrap::MODEM_SIM7600);
|
|
||||||
auto dce_sim7600 = static_cast<DCE*>(dce->dce_ptr);
|
|
||||||
return command_response_to_esp_err(dce_sim7600->get_signal_quality(*rssi, *ber));
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" esp_err_t esp_modem_get_imsi(esp_modem_dce_t * dce, char *p_imsi)
|
|
||||||
{
|
|
||||||
assert(dce->modem_type == esp_modem_dce_wrap::MODEM_SIM7600);
|
|
||||||
auto dce_sim7600 = static_cast<DCE*>(dce->dce_ptr);
|
|
||||||
std::string imsi;
|
|
||||||
auto ret = command_response_to_esp_err(dce_sim7600->get_imsi(imsi));
|
|
||||||
if (ret == ESP_OK && !imsi.empty()) {
|
|
||||||
strcpy(p_imsi, imsi.c_str());
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
171
esp_modem/src/esp_modem_c_api.cpp
Normal file
171
esp_modem/src/esp_modem_c_api.cpp
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include "cxx_include/esp_modem_dte.hpp"
|
||||||
|
#include "uart_terminal.hpp"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "cxx_include/esp_modem_api.hpp"
|
||||||
|
#include "cxx_include/esp_modem_dce_factory.hpp"
|
||||||
|
#include "esp_modem_c_api_types.h"
|
||||||
|
#include "esp_modem_config.h"
|
||||||
|
#include "exception_stub.hpp"
|
||||||
|
#include "cstring"
|
||||||
|
|
||||||
|
//
|
||||||
|
// C API definitions
|
||||||
|
using namespace esp_modem;
|
||||||
|
|
||||||
|
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;
|
||||||
|
dce_factory::Modem modem_type;
|
||||||
|
DCE* dce;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline esp_err_t command_response_to_esp_err(command_result res)
|
||||||
|
{
|
||||||
|
switch (res) {
|
||||||
|
case command_result::OK:
|
||||||
|
return ESP_OK;
|
||||||
|
case command_result::FAIL:
|
||||||
|
return ESP_FAIL;
|
||||||
|
case command_result::TIMEOUT:
|
||||||
|
return ESP_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline dce_factory::Modem convert_modem_enum(esp_modem_dce_device_t module)
|
||||||
|
{
|
||||||
|
switch (module) {
|
||||||
|
case ESP_MODEM_DCE_SIM7600:
|
||||||
|
return esp_modem::dce_factory::Modem::SIM7600;
|
||||||
|
case ESP_MODEM_DCE_BG96:
|
||||||
|
return esp_modem::dce_factory::Modem::BG96;
|
||||||
|
case ESP_MODEM_DCE_SIM800:
|
||||||
|
return esp_modem::dce_factory::Modem::SIM800;
|
||||||
|
default:
|
||||||
|
case ESP_MODEM_DCE_GENETIC:
|
||||||
|
return esp_modem::dce_factory::Modem::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)
|
||||||
|
{
|
||||||
|
auto dce_wrap = new (std::nothrow) esp_modem_dce_wrap;
|
||||||
|
if (dce_wrap == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
auto dte = create_uart_dte(dte_config);
|
||||||
|
if (dte == nullptr) {
|
||||||
|
delete dce_wrap;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
dce_factory::Factory f(convert_modem_enum(module));
|
||||||
|
dce_wrap->dce = f.build(dce_config, std::move(dte), netif);
|
||||||
|
if (dce_wrap->dce == nullptr) {
|
||||||
|
delete dce_wrap;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
dce_wrap->modem_type = convert_modem_enum(module);
|
||||||
|
dce_wrap->dte_type = esp_modem_dce_wrap::modem_wrap_dte_type::UART;
|
||||||
|
return dce_wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" esp_modem_dce_t *esp_modem_new(const esp_modem_dte_config_t *dte_config, const esp_modem_dce_config_t *dce_config, esp_netif_t *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)
|
||||||
|
{
|
||||||
|
if (dce_wrap) {
|
||||||
|
delete dce_wrap->dce;
|
||||||
|
delete dce_wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
if (mode == ESP_MODEM_MODE_DATA) {
|
||||||
|
dce_wrap->dce->set_data();
|
||||||
|
} else if (mode == ESP_MODEM_MODE_COMMAND) {
|
||||||
|
dce_wrap->dce->exit_data();
|
||||||
|
} else {
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (dce_wrap == nullptr || dce_wrap->dce == nullptr)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (dce_wrap == nullptr || dce_wrap->dce == nullptr)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
std::string number_str(number);
|
||||||
|
std::string message_str(message);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (dce_wrap == nullptr || dce_wrap->dce == nullptr)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (dce_wrap == nullptr || dce_wrap->dce == nullptr)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
std::string pin_str(pin);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (dce_wrap == nullptr || dce_wrap->dce == nullptr)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (dce_wrap == nullptr || dce_wrap->dce == nullptr)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
std::string imsi;
|
||||||
|
auto ret = command_response_to_esp_err(dce_wrap->dce->get_imsi(imsi));
|
||||||
|
if (ret == ESP_OK && !imsi.empty()) {
|
||||||
|
strcpy(p_imsi, imsi.c_str());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
@ -64,9 +64,9 @@ static inline command_result generic_get_string(CommandableIf* t, const std::str
|
|||||||
}, timeout_ms);
|
}, timeout_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline command_result generic_command_common(CommandableIf* t, std::string command)
|
static inline command_result generic_command_common(CommandableIf* t, std::string command, uint32_t timeout = 500)
|
||||||
{
|
{
|
||||||
return generic_command(t, command, "OK", "ERROR", 500);
|
return generic_command(t, command, "OK", "ERROR", timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -131,6 +131,35 @@ command_result get_module_name(CommandableIf* t, std::string& out)
|
|||||||
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)
|
||||||
|
{
|
||||||
|
if (txt)
|
||||||
|
return generic_command_common(t, "AT+CMGF=1\r"); // Text mode (default)
|
||||||
|
return generic_command_common(t, "AT+CMGF=0\r"); // PDU mode
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result sms_character_set(CommandableIf* t)
|
||||||
|
{
|
||||||
|
// Sets the default GSM character set
|
||||||
|
return generic_command_common(t, "AT+CSCS=\"GSM\"\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result send_sms(CommandableIf* t, const std::string& number, const std::string& message)
|
||||||
|
{
|
||||||
|
auto ret = t->command("AT+CMGS=\"" + number + "\"\r", [&](uint8_t *data, size_t len) {
|
||||||
|
std::string response((char*)data, len);
|
||||||
|
std::cout << response << std::endl;
|
||||||
|
if (response.find('>') != std::string::npos) {
|
||||||
|
return command_result::OK;
|
||||||
|
}
|
||||||
|
return command_result::TIMEOUT;
|
||||||
|
}, 5000, ' ');
|
||||||
|
if (ret != command_result::OK)
|
||||||
|
return ret;
|
||||||
|
return generic_command_common(t, message +"\x1A", 120000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
command_result set_cmux(CommandableIf* t)
|
command_result set_cmux(CommandableIf* t)
|
||||||
{
|
{
|
||||||
return generic_command_common(t, "AT+CMUX=0\r");
|
return generic_command_common(t, "AT+CMUX=0\r");
|
||||||
|
@ -26,7 +26,7 @@ DTE::DTE(std::unique_ptr<Terminal> terminal):
|
|||||||
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) {}
|
||||||
|
|
||||||
command_result DTE::command(const std::string &command, got_line_cb got_line, uint32_t time_ms)
|
command_result DTE::command(const std::string &command, got_line_cb got_line, uint32_t time_ms, const char separator)
|
||||||
{
|
{
|
||||||
Scoped<Lock> l(lock);
|
Scoped<Lock> l(lock);
|
||||||
command_result res = command_result::TIMEOUT;
|
command_result res = command_result::TIMEOUT;
|
||||||
@ -37,7 +37,7 @@ command_result DTE::command(const std::string &command, got_line_cb got_line, ui
|
|||||||
len = command_term->read(data, data_to_read);
|
len = command_term->read(data, data_to_read);
|
||||||
}
|
}
|
||||||
consumed += len;
|
consumed += len;
|
||||||
if (memchr(data, '\n', len)) {
|
if (memchr(data, separator, len)) {
|
||||||
res = got_line(data, consumed);
|
res = got_line(data, consumed);
|
||||||
if (res == command_result::OK || res == command_result::FAIL) {
|
if (res == command_result::OK || res == command_result::FAIL) {
|
||||||
signal.set(GOT_LINE);
|
signal.set(GOT_LINE);
|
||||||
@ -65,4 +65,9 @@ void DTE::setup_cmux()
|
|||||||
term = std::make_unique<CMuxInstance>(cmux_term, 0);
|
term = std::make_unique<CMuxInstance>(cmux_term, 0);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
command_result DTE::command(const std::string &cmd, got_line_cb got_line, uint32_t time_ms)
|
||||||
|
{
|
||||||
|
return command(cmd, got_line, time_ms, '\n');
|
||||||
|
}
|
||||||
|
@ -27,7 +27,7 @@ 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("TAG", "PPP state changed event %d", event_id);
|
ESP_LOGI("esp_modem_netif", "PPP state changed event %d", event_id);
|
||||||
// only notify the modem on state/error events, ignoring phase transitions
|
// only notify the modem on state/error events, ignoring phase transitions
|
||||||
ppp->signal.set(PPP_EXIT);
|
ppp->signal.set(PPP_EXIT);
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ 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;
|
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) {
|
if (!ppp_config.ppp_error_event_enabled) {
|
||||||
ppp_config.ppp_error_event_enabled = true;
|
ppp_config.ppp_error_event_enabled = true;
|
||||||
esp_netif_ppp_set_params(esp_netif, &ppp_config);
|
esp_netif_ppp_set_params(esp_netif, &ppp_config);
|
||||||
|
Reference in New Issue
Block a user