From d3f7ea67fb1a62f92a187521ec36701eeb23ff1b Mon Sep 17 00:00:00 2001 From: "Sjur G. Wroldsen" Date: Wed, 13 Apr 2022 13:41:56 +0200 Subject: [PATCH] Add: Expanded modem_command_library with more "standard" commands --- .../generate/esp_modem_command_declare.inc | 90 +++++++++++++- components/esp_modem/src/esp_modem_c_api.cpp | 97 +++++++++++++++ .../src/esp_modem_command_library.cpp | 112 ++++++++++++++++++ 3 files changed, 298 insertions(+), 1 deletion(-) diff --git a/components/esp_modem/include/generate/esp_modem_command_declare.inc b/components/esp_modem/include/generate/esp_modem_command_declare.inc index 0c1a6bdbb..20862594d 100644 --- a/components/esp_modem/include/generate/esp_modem_command_declare.inc +++ b/components/esp_modem/include/generate/esp_modem_command_declare.inc @@ -28,6 +28,7 @@ #define BOOL_IN(param, name) const bool _ARG(param, name) #define BOOL_OUT(param, name) bool& _ARG(param, name) #define INT_OUT(param, name) int& _ARG(param, name) +#define LIST_IN(param, name) const int* _ARG(param, name) #define STRUCT_OUT(struct_name, p1) struct_name& p1 #else @@ -36,6 +37,7 @@ #define BOOL_IN(param, name) const bool _ARG(param, name) #define BOOL_OUT(param, name) bool* _ARG(param, name) #define INT_OUT(param, name) int* _ARG(param, name) +#define LIST_IN(param, name) const int* _ARG(param, name) #define STRUCT_OUT(struct_name, p1) struct struct_name* p1 #endif @@ -200,7 +202,93 @@ ESP_MODEM_DECLARE_DCE_COMMAND(reset, command_result, 0) \ * @param[in] baud Desired baud rate of the DTE * @return OK, FAIL or TIMEOUT */ \ -ESP_MODEM_DECLARE_DCE_COMMAND(set_baud, command_result, 1, INT_IN(p1, baud)) +ESP_MODEM_DECLARE_DCE_COMMAND(set_baud, command_result, 1, INT_IN(p1, baud)) \ + \ +/** + * @brief Force an attempt to connect to a specific operator + * @param[in] mode mode of attempt + * mode=0 - automatic + * mode=1 - manual + * mode=2 - deregister + * mode=3 - set format for read operation + * mode=4 - manual with fallback to automatic + * @param[in] format what format the operator is given in + * format=0 - long format + * format=1 - short format + * format=2 - numeric + * @param[in] oper the operator to connect to + * @return OK, FAIL or TIMEOUT + */ \ +ESP_MODEM_DECLARE_DCE_COMMAND(set_operator, command_result, 3, INT_IN(p1, mode), INT_IN(p2, format), STRING_IN(p3, oper)) \ + \ +/** + * @brief Attach or detach from the GPRS service + * @param[in] state 1-attach 0-detach + * @return OK, FAIL or TIMEOUT + */ \ +ESP_MODEM_DECLARE_DCE_COMMAND(set_network_attachment_state, command_result, 1, INT_IN(p1, state)) \ + \ +/** + * @brief Get network attachment state + * @param[out] state 1-attached 0-detached + * @return OK, FAIL or TIMEOUT + */ \ +ESP_MODEM_DECLARE_DCE_COMMAND(get_network_attachment_state, command_result, 1, INT_OUT(p1, state)) \ + \ +/** + * @brief What mode the radio should be set to + * @param[in] state state 1-full 0-minimum ... + * @return OK, FAIL or TIMEOUT + */ \ +ESP_MODEM_DECLARE_DCE_COMMAND(set_radio_state, command_result, 1, INT_IN(p1, state)) \ + \ +/** + * @brief Get current radio state + * @param[out] state 1-full 0-minimum ... + * @return OK, FAIL or TIMEOUT + */ \ +ESP_MODEM_DECLARE_DCE_COMMAND(get_radio_state, command_result, 1, INT_OUT(p1, state)) \ + \ +/** + * @brief Set network mode + * @param[in] mode preferred mode + * -- SIM7xxx -- + * mode=2 - Automatic + * mode=13 - GSM only + * mode=38 - LTE only + * mode=51 - GSM and LTE only + * @return OK, FAIL or TIMEOUT + */ \ +ESP_MODEM_DECLARE_DCE_COMMAND(set_network_mode, command_result, 1, INT_IN(p1, mode)) \ + \ +/** + * @brief Preferred network mode (CAT-M and/or NB-IoT) + * @param[in] mode preferred selection + * @return OK, FAIL or TIMEOUT + */ \ +ESP_MODEM_DECLARE_DCE_COMMAND(set_preferred_mode, command_result, 1, INT_IN(p1, mode)) \ + \ +/** + * @brief Set network bands for CAT-M or NB-IoT + * @param[in] mode CAT-M or NB-IoT + * @return OK, FAIL or TIMEOUT + */ \ +ESP_MODEM_DECLARE_DCE_COMMAND(set_network_bands, command_result, 3, STRING_IN(p1, mode), LIST_IN(p2, bands), INT_IN(p3, size)) \ + \ +/** + * @brief Show network system mode + * @param[out] mode current network mode + * @return OK, FAIL or TIMEOUT + */ \ +ESP_MODEM_DECLARE_DCE_COMMAND(get_network_system_mode, command_result, 1, INT_OUT(p1, mode)) \ + \ +/** + * @brief GNSS power control + * @param[out] mode power mode (0 - off, 1 - on) + * @return OK, FAIL or TIMEOUT + */ \ +ESP_MODEM_DECLARE_DCE_COMMAND(set_gnss_power_mode, command_result, 1, INT_IN(p1, mode)) \ + \ #ifdef GENERATE_DOCS diff --git a/components/esp_modem/src/esp_modem_c_api.cpp b/components/esp_modem/src/esp_modem_c_api.cpp index 0753c7f30..afe90616d 100644 --- a/components/esp_modem/src/esp_modem_c_api.cpp +++ b/components/esp_modem/src/esp_modem_c_api.cpp @@ -271,3 +271,100 @@ extern "C" esp_err_t esp_modem_power_down(esp_modem_dce_t *dce_wrap) } return command_response_to_esp_err(dce_wrap->dce->power_down()); } + +extern "C" esp_err_t esp_modem_set_operator(esp_modem_dce_t *dce_wrap, int mode, int format, const char* oper) +{ + if (dce_wrap == nullptr || dce_wrap->dce == nullptr) { + return ESP_ERR_INVALID_ARG; + } + std::string operator_str = std::string(oper); + return command_response_to_esp_err(dce_wrap->dce->set_operator(mode, format, operator_str)); +} + +extern "C" esp_err_t esp_modem_set_network_attachment_state(esp_modem_dce_t *dce_wrap, int state) +{ + if (dce_wrap == nullptr || dce_wrap->dce == nullptr) { + return ESP_ERR_INVALID_ARG; + } + return command_response_to_esp_err(dce_wrap->dce->set_network_attachment_state(state)); +} + +extern "C" esp_err_t esp_modem_get_network_attachment_state(esp_modem_dce_t *dce_wrap, int *p_state) +{ + if (dce_wrap == nullptr || dce_wrap->dce == nullptr) { + return ESP_ERR_INVALID_ARG; + } + int state; + auto ret = command_response_to_esp_err(dce_wrap->dce->get_network_attachment_state(state)); + if (ret == ESP_OK) { + *p_state = state; + } + return ret; +} + +extern "C" esp_err_t esp_modem_set_radio_state(esp_modem_dce_t *dce_wrap, int state) +{ + if (dce_wrap == nullptr || dce_wrap->dce == nullptr) { + return ESP_ERR_INVALID_ARG; + } + return command_response_to_esp_err(dce_wrap->dce->set_radio_state(state)); +} + +extern "C" esp_err_t esp_modem_get_radio_state(esp_modem_dce_t *dce_wrap, int *p_state) +{ + if (dce_wrap == nullptr || dce_wrap->dce == nullptr) { + return ESP_ERR_INVALID_ARG; + } + int state; + auto ret = command_response_to_esp_err(dce_wrap->dce->get_radio_state(state)); + if (ret == ESP_OK) { + *p_state = state; + } + return ret; +} + +extern "C" esp_err_t esp_modem_set_network_mode(esp_modem_dce_t *dce_wrap, int mode) +{ + if (dce_wrap == nullptr || dce_wrap->dce == nullptr) { + return ESP_ERR_INVALID_ARG; + } + return command_response_to_esp_err(dce_wrap->dce->set_network_mode(mode)); +} + +extern "C" esp_err_t esp_modem_set_preferred_mode(esp_modem_dce_t *dce_wrap, int mode) +{ + if (dce_wrap == nullptr || dce_wrap->dce == nullptr) { + return ESP_ERR_INVALID_ARG; + } + return command_response_to_esp_err(dce_wrap->dce->set_preferred_mode(mode)); +} + +extern "C" esp_err_t esp_modem_set_network_bands(esp_modem_dce_t *dce_wrap, const char* mode, const int* bands, int size) +{ + if (dce_wrap == nullptr || dce_wrap->dce == nullptr) { + return ESP_ERR_INVALID_ARG; + } + std::string mode_str = std::string(mode); + return command_response_to_esp_err(dce_wrap->dce->set_network_bands(mode, bands, size)); +} + +extern "C" esp_err_t esp_modem_get_network_system_mode(esp_modem_dce_t *dce_wrap, int* p_mode) +{ + if (dce_wrap == nullptr || dce_wrap->dce == nullptr) { + return ESP_ERR_INVALID_ARG; + } + int mode; + auto ret = command_response_to_esp_err(dce_wrap->dce->get_network_system_mode(mode)); + if (ret == ESP_OK) { + *p_mode = mode; + } + return ret; +} + +extern "C" esp_err_t esp_modem_set_gnss_power_mode(esp_modem_dce_t *dce_wrap, int mode) +{ + if (dce_wrap == nullptr || dce_wrap->dce == nullptr) { + return ESP_ERR_INVALID_ARG; + } + return command_response_to_esp_err(dce_wrap->dce->set_gnss_power_mode(mode)); +} diff --git a/components/esp_modem/src/esp_modem_command_library.cpp b/components/esp_modem/src/esp_modem_command_library.cpp index 450ede273..2c67d14d6 100644 --- a/components/esp_modem/src/esp_modem_command_library.cpp +++ b/components/esp_modem/src/esp_modem_command_library.cpp @@ -399,4 +399,116 @@ command_result get_signal_quality(CommandableIf *t, int &rssi, int &ber) return command_result::OK; } +command_result set_operator(CommandableIf *t, int mode, int format, const std::string& oper) +{ + ESP_LOGV(TAG, "%s", __func__ ); + return generic_command_common(t, "AT+COPS=" + std::to_string(mode) + "," + std::to_string(format) + ",\"" + oper + "\"\r", 90000); +} + +command_result set_network_attachment_state(CommandableIf *t, int state) +{ + ESP_LOGV(TAG, "%s", __func__ ); + return generic_command_common(t, "AT+CGATT=" + std::to_string(state) + "\r"); +} + +command_result get_network_attachment_state(CommandableIf *t, int &state) +{ + ESP_LOGV(TAG, "%s", __func__ ); + std::string_view out; + auto ret = generic_get_string(t, "AT+CGATT?\r", out); + if (ret != command_result::OK) { + return ret; + } + constexpr std::string_view pattern = "+CGATT: "; + constexpr int pos = pattern.size(); + if (out.find(pattern) == std::string::npos) { + return command_result::FAIL; + } + + if (std::from_chars(out.data() + pos, out.data() + out.size(), state).ec == std::errc::invalid_argument) { + return command_result::FAIL; + } + + return command_result::OK; +} + +command_result set_radio_state(CommandableIf *t, int state) +{ + ESP_LOGV(TAG, "%s", __func__ ); + return generic_command_common(t, "AT+CFUN=" + std::to_string(state) + "\r"); +} + +command_result get_radio_state(CommandableIf *t, int &state) +{ + ESP_LOGV(TAG, "%s", __func__ ); + std::string_view out; + auto ret = generic_get_string(t, "AT+CFUN?\r", out); + if (ret != command_result::OK) { + return ret; + } + constexpr std::string_view pattern = "+CFUN: "; + constexpr int pos = pattern.size(); + if (out.find(pattern) == std::string::npos) { + return command_result::FAIL; + } + + if (std::from_chars(out.data() + pos, out.data() + out.size(), state).ec == std::errc::invalid_argument) { + return command_result::FAIL; + } + + return command_result::OK; +} + +command_result set_network_mode(CommandableIf *t, int mode) +{ + ESP_LOGV(TAG, "%s", __func__ ); + return generic_command_common(t, "AT+CNMP=" + std::to_string(mode) + "\r"); +} + +command_result set_preferred_mode(CommandableIf *t, int mode) +{ + ESP_LOGV(TAG, "%s", __func__ ); + return generic_command_common(t, "AT+CMNB=" + std::to_string(mode) + "\r"); +} + +command_result set_network_bands(CommandableIf *t, const std::string& mode, const int* bands, int size) +{ + ESP_LOGV(TAG, "%s", __func__ ); + std::string band_string = ""; + for (int i = 0; i," + if (out.find(pattern) == std::string::npos) { + return command_result::FAIL; + } + + if (std::from_chars(out.data() + mode_pos, out.data() + out.size(), mode).ec == std::errc::invalid_argument) { + return command_result::FAIL; + } + + return command_result::OK; +} + +command_result set_gnss_power_mode(CommandableIf *t, int mode) +{ + ESP_LOGV(TAG, "%s", __func__ ); + return generic_command_common(t, "AT+CGNSPWR=" + std::to_string(mode) + "\r"); +} + } // esp_modem::dce_commands \ No newline at end of file