From 65c0e0e195c2fa5bb93e8f7220faaeedffbaa782 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 18 Oct 2022 16:57:42 +0200 Subject: [PATCH] fix(esp_modem): Cleanup custom lib-commands and factory --- .../pppos_client/main/Kconfig.projbuild | 29 ++++++------ .../pppos_client/main/pppos_client_main.c | 22 ++++----- .../components/SIM7070_gnss/SIM7070_gnss.cpp | 41 ++++++++--------- .../components/SIM7070_gnss/SIM7070_gnss.hpp | 16 ++++--- .../components/SIM7070_gnss/nmea_parser.h | 8 +--- .../main/simple_cmux_client_main.cpp | 2 +- .../include/cxx_include/command_library.hpp | 27 ----------- .../esp_modem_command_library_utils.hpp | 45 +++++++++++++++++++ .../src/esp_modem_command_library.cpp | 17 ++++--- 9 files changed, 113 insertions(+), 94 deletions(-) delete mode 100644 components/esp_modem/include/cxx_include/command_library.hpp create mode 100644 components/esp_modem/include/cxx_include/esp_modem_command_library_utils.hpp diff --git a/components/esp_modem/examples/pppos_client/main/Kconfig.projbuild b/components/esp_modem/examples/pppos_client/main/Kconfig.projbuild index 4a0e0dbd5..65243a0b5 100644 --- a/components/esp_modem/examples/pppos_client/main/Kconfig.projbuild +++ b/components/esp_modem/examples/pppos_client/main/Kconfig.projbuild @@ -96,20 +96,6 @@ menu "Example Configuration" help Pin to unlock the SIM - choice EXAMPLE_FLOW_CONTROL - bool "Set preferred modem control flow" - default EXAMPLE_FLOW_CONTROL_NONE - help - Set the modem's preferred control flow - - config EXAMPLE_FLOW_CONTROL_NONE - bool "No control flow" - config EXAMPLE_FLOW_CONTROL_SW - bool "SW control flow" - config EXAMPLE_FLOW_CONTROL_HW - bool "HW control flow" - endchoice - menu "UART Configuration" depends on EXAMPLE_SERIAL_CONFIG_UART config EXAMPLE_MODEM_UART_TX_PIN @@ -181,6 +167,21 @@ menu "Example Configuration" default 1024 help Buffer size of UART RX buffer. + + choice EXAMPLE_FLOW_CONTROL + bool "Set preferred modem control flow" + default EXAMPLE_FLOW_CONTROL_NONE + help + Set the modem's preferred control flow + + config EXAMPLE_FLOW_CONTROL_NONE + bool "No control flow" + config EXAMPLE_FLOW_CONTROL_SW + bool "SW control flow" + config EXAMPLE_FLOW_CONTROL_HW + bool "HW control flow" + endchoice + endmenu endmenu diff --git a/components/esp_modem/examples/pppos_client/main/pppos_client_main.c b/components/esp_modem/examples/pppos_client/main/pppos_client_main.c index 81e6cf2bc..99f669efe 100644 --- a/components/esp_modem/examples/pppos_client/main/pppos_client_main.c +++ b/components/esp_modem/examples/pppos_client/main/pppos_client_main.c @@ -197,6 +197,15 @@ void app_main(void) ESP_LOGI(TAG, "Initializing esp_modem for a generic module..."); esp_modem_dce_t *dce = esp_modem_new(&dte_config, &dce_config, esp_netif); #endif + assert(dce); + if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) { + esp_err_t err = esp_modem_set_flow_control(dce, 2, 2); //2/2 means HW Flow Control. + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set the set_flow_control mode"); + return; + } + ESP_LOGI(TAG, "HW set_flow_control OK"); + } #elif defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB) while (1) { @@ -205,26 +214,17 @@ void app_main(void) const esp_modem_dte_config_t dte_usb_config = ESP_MODEM_DTE_DEFAULT_USB_CONFIG(usb_config); ESP_LOGI(TAG, "Waiting for USB device connection..."); esp_modem_dce_t *dce = esp_modem_new_dev_usb(ESP_MODEM_DCE_BG96, &dte_usb_config, &dce_config, esp_netif); + assert(dce); esp_modem_set_error_cb(dce, usb_terminal_error_handler); vTaskDelay(pdMS_TO_TICKS(1000)); // Although the DTE should be ready after USB enumeration, sometimes it fails to respond without this delay #else #error Invalid serial connection to modem. #endif - assert(dce); + xEventGroupClearBits(event_group, CONNECT_BIT | GOT_DATA_BIT | USB_DISCONNECTED_BIT); /* Run the modem demo app */ - - if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) { - esp_err_t err = esp_modem_set_flow_control(dce, 2, 2); //2/2 means HW Flow Control. - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to set the set_flow_control mode"); - return; - } - ESP_LOGI(TAG, "set_flow_control OK"); - } - #if CONFIG_EXAMPLE_NEED_SIM_PIN == 1 // check if PIN needed bool pin_ok = false; diff --git a/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/SIM7070_gnss.cpp b/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/SIM7070_gnss.cpp index cafe1c2bb..b60f01b96 100644 --- a/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/SIM7070_gnss.cpp +++ b/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/SIM7070_gnss.cpp @@ -7,36 +7,37 @@ // Created on: 23.08.2022 // Author: franz - -#include -#include -#include #include -#include #include #include #include "sdkconfig.h" -#include "esp_event.h" #include "cxx_include/esp_modem_dte.hpp" #include "cxx_include/esp_modem_dce.hpp" #include "esp_modem_config.h" #include "cxx_include/esp_modem_api.hpp" -#include "cxx_include/command_library.hpp" +#include "cxx_include/esp_modem_command_library_utils.hpp" #include "esp_log.h" #include "SIM7070_gnss.hpp" - -const static char *const TAG = "SIM7070_gnss"; +constexpr auto const TAG = "SIM7070_gnss"; -class LocalFactory: public esp_modem::dce_factory::Factory { +namespace gnss_factory { +using namespace esp_modem; +using namespace dce_factory; + +class LocalFactory: public Factory { + using DCE_gnss_ret = std::unique_ptr; // this custom Factory manufactures only unique_ptr's public: - static std::unique_ptr create(const esp_modem::dce_config *config, std::shared_ptr dte, esp_netif_t *netif) + static DCE_gnss_ret create(const dce_config *config, std::shared_ptr dte, esp_netif_t *netif) { - return esp_modem::dce_factory::Factory::build_generic_DCE>(config, dte, netif); + return Factory::build_generic_DCE + (config, std::move(dte), netif); } - }; + +} // namespace gnss_factory + /** * @brief Helper create method which employs the DCE factory for creating DCE objects templated by a custom module * @return unique pointer of the resultant DCE @@ -45,19 +46,19 @@ std::unique_ptr create_SIM7070_GNSS_dce(const esp_modem::dce_config *c std::shared_ptr dte, esp_netif_t *netif) { - return LocalFactory::create(config, std::move(dte), netif); + return gnss_factory::LocalFactory::create(config, std::move(dte), netif); } -esp_modem::command_result get_gnss_information_sim70xx_lib(esp_modem::CommandableIf *t, gps_t &gps) +esp_modem::command_result get_gnss_information_sim70xx_lib(esp_modem::CommandableIf *t, esp_modem_gps_t &gps) { ESP_LOGV(TAG, "%s", __func__ ); - std::string_view out; - auto ret = esp_modem::dce_commands::generic_get_string(t, "AT+CGNSINF\r", out); + std::string str_out; + auto ret = esp_modem::dce_commands::generic_get_string(t, "AT+CGNSINF\r", str_out); if (ret != esp_modem::command_result::OK) { return ret; } - + std::string_view out(str_out); constexpr std::string_view pattern = "+CGNSINF: "; @@ -329,12 +330,12 @@ esp_modem::command_result get_gnss_information_sim70xx_lib(esp_modem::Commandabl return esp_modem::command_result::OK; } -esp_modem::command_result SIM7070_gnss::get_gnss_information_sim70xx(gps_t &gps) +esp_modem::command_result SIM7070_gnss::get_gnss_information_sim70xx(esp_modem_gps_t &gps) { return get_gnss_information_sim70xx_lib(dte.get(), gps); } -esp_modem::command_result DCE_gnss::get_gnss_information_sim70xx(gps_t &gps) +esp_modem::command_result DCE_gnss::get_gnss_information_sim70xx(esp_modem_gps_t &gps) { return device->get_gnss_information_sim70xx(gps); } diff --git a/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/SIM7070_gnss.hpp b/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/SIM7070_gnss.hpp index 10650867e..8ca99dc0d 100644 --- a/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/SIM7070_gnss.hpp +++ b/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/SIM7070_gnss.hpp @@ -16,15 +16,19 @@ #include "nmea_parser.h" /** - * @brief Definition of a custom modem which inherits from the GenericModule, uses all its methods - * and could override any of them. Here, for demonstration purposes only, we redefine just `get_module_name()` + * @brief Definition of a custom SIM7070 class with GNSS capabilities. + * This inherits from the official esp-modem's SIM7070 device which contains all common library methods. + * On top of that, the SIM7070_gnss adds reading GNSS information, which is implemented in a private component. */ class SIM7070_gnss: public esp_modem::SIM7070 { using SIM7070::SIM7070; public: - esp_modem::command_result get_gnss_information_sim70xx(gps_t &gps); + esp_modem::command_result get_gnss_information_sim70xx(esp_modem_gps_t &gps); }; +/** + * @brief DCE for the SIM7070_gnss. Here we've got to forward the general commands, aa well as the GNSS one. + */ class DCE_gnss : public esp_modem::DCE_T { public: @@ -43,14 +47,14 @@ public: #undef ESP_MODEM_DECLARE_DCE_COMMAND - esp_modem::command_result get_gnss_information_sim70xx(gps_t &gps); + esp_modem::command_result get_gnss_information_sim70xx(esp_modem_gps_t &gps); }; /** - * @brief Helper create method which employs the DCE factory for creating DCE objects templated by a custom module - * @return unique pointer of the resultant DCE + * @brief Helper create method which employs the customized DCE factory for building DCE_gnss objects + * @return unique pointer of the specific DCE */ std::unique_ptr create_SIM7070_GNSS_dce(const esp_modem::dce_config *config, std::shared_ptr dte, diff --git a/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/nmea_parser.h b/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/nmea_parser.h index 4f6fcebf9..a0c59a714 100644 --- a/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/nmea_parser.h +++ b/components/esp_modem/examples/simple_cmux_client/components/SIM7070_gnss/nmea_parser.h @@ -97,7 +97,7 @@ typedef enum { * @brief GPS object * */ -struct gps_s { +struct esp_modem_gps { float latitude; /*!< Latitude (degrees) */ float longitude; /*!< Longitude (degrees) */ float altitude; /*!< Altitude (meters) */ @@ -117,11 +117,7 @@ struct gps_s { float vpa; /*!< Vertical Position Accuracy */ }; -typedef struct gps_s gps_t; -typedef struct gps_s esp_modem_gps_s_t; - - - +typedef struct esp_modem_gps esp_modem_gps_t; /** * @brief NMEA Parser Event ID diff --git a/components/esp_modem/examples/simple_cmux_client/main/simple_cmux_client_main.cpp b/components/esp_modem/examples/simple_cmux_client/main/simple_cmux_client_main.cpp index dadbcc6cc..df9229547 100644 --- a/components/esp_modem/examples/simple_cmux_client/main/simple_cmux_client_main.cpp +++ b/components/esp_modem/examples/simple_cmux_client/main/simple_cmux_client_main.cpp @@ -195,7 +195,7 @@ extern "C" void app_main(void) #if CONFIG_EXAMPLE_MODEM_DEVICE_SIM7070_GNSS == 1 - gps_t gps; + esp_modem_gps_t gps; for (int i = 0; i < 200; ++i) { if (dce->get_gnss_information_sim70xx(gps) == esp_modem::command_result::OK) { diff --git a/components/esp_modem/include/cxx_include/command_library.hpp b/components/esp_modem/include/cxx_include/command_library.hpp deleted file mode 100644 index c2c00ee69..000000000 --- a/components/esp_modem/include/cxx_include/command_library.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once -namespace esp_modem::dce_commands { -command_result generic_command(CommandableIf *t, const std::string &command, - const std::list &pass_phrase, - const std::list &fail_phrase, - uint32_t timeout_ms); - - -command_result generic_command(CommandableIf *t, const std::string &command, - const std::string &pass_phrase, - const std::string &fail_phrase, uint32_t timeout_ms); - -command_result generic_get_string(CommandableIf *t, const std::string &command, std::string_view &output, uint32_t timeout_ms = 500); - -command_result generic_get_string(CommandableIf *t, const std::string &command, std::string &output, uint32_t timeout_ms = 500); - -command_result generic_command_common(CommandableIf *t, const std::string &command, uint32_t timeout = 500); - - - -} // esp_modem::dce_commands diff --git a/components/esp_modem/include/cxx_include/esp_modem_command_library_utils.hpp b/components/esp_modem/include/cxx_include/esp_modem_command_library_utils.hpp new file mode 100644 index 000000000..b47c150d8 --- /dev/null +++ b/components/esp_modem/include/cxx_include/esp_modem_command_library_utils.hpp @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +namespace esp_modem::dce_commands { + +/** + * @brief Generic command that passes on supplied pass_phrase, and fails on fail_phrase + * @param t Any "Command-able" class that implements "command()" method + * @param command Command to issue + * @param pass_phrase Pattern to find in replies to complete the command successfully + * @param fail_phrase If this pattern found the command fails immediately + * @param timeout_ms Command timeout in ms + * @return Generic command return type (OK, FAIL, TIMEOUT) + */ +command_result generic_command(CommandableIf *t, const std::string &command, + const std::string &pass_phrase, + const std::string &fail_phrase, uint32_t timeout_ms); + +/** + * @brief Utility command to send command and return reply (after DCE says OK) + * @param t Anything that is "command-able" + * @param command Command to issue + * @param output String to return + * @param timeout_ms + * @param timeout_ms Command timeout in ms + * @return Generic command return type (OK, FAIL, TIMEOUT) + */ +command_result generic_get_string(CommandableIf *t, const std::string &command, std::string &output, uint32_t timeout_ms = 500); + +/** + * @brief Generic command that passes on "OK" and fails on "ERROR" + * @param t Anything that is "command-able" + * @param command Command to issue + * @param timeout + * @param timeout_ms Command timeout in ms + * @return Generic command return type (OK, FAIL, TIMEOUT) + */ +command_result generic_command_common(CommandableIf *t, const std::string &command, uint32_t timeout_ms = 500); + +} // esp_modem::dce_commands diff --git a/components/esp_modem/src/esp_modem_command_library.cpp b/components/esp_modem/src/esp_modem_command_library.cpp index 5b320a054..2a638e982 100644 --- a/components/esp_modem/src/esp_modem_command_library.cpp +++ b/components/esp_modem/src/esp_modem_command_library.cpp @@ -10,17 +10,16 @@ #include "cxx_include/esp_modem_dte.hpp" #include "cxx_include/esp_modem_dce_module.hpp" #include "cxx_include/esp_modem_command_library.hpp" -#include "cxx_include/command_library.hpp" - +#include "cxx_include/esp_modem_command_library_utils.hpp" namespace esp_modem::dce_commands { static const char *TAG = "command_lib"; -command_result generic_command(CommandableIf *t, const std::string &command, - const std::list &pass_phrase, - const std::list &fail_phrase, - uint32_t timeout_ms) +static command_result generic_command(CommandableIf *t, const std::string &command, + const std::list &pass_phrase, + const std::list &fail_phrase, + uint32_t timeout_ms) { ESP_LOGD(TAG, "%s command %s\n", __func__, command.c_str()); return t->command(command, [&](uint8_t *data, size_t len) { @@ -52,7 +51,7 @@ command_result generic_command(CommandableIf *t, const std::string &command, return generic_command(t, command, pass, fail, timeout_ms); } -command_result generic_get_string(CommandableIf *t, const std::string &command, std::string_view &output, uint32_t timeout_ms) +static 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__ ); return t->command(command, [&](uint8_t *data, size_t len) { @@ -91,10 +90,10 @@ command_result generic_get_string(CommandableIf *t, const std::string &command, } -command_result generic_command_common(CommandableIf *t, const std::string &command, uint32_t timeout) +command_result generic_command_common(CommandableIf *t, const std::string &command, uint32_t timeout_ms) { ESP_LOGV(TAG, "%s", __func__ ); - return generic_command(t, command, "OK", "ERROR", timeout); + return generic_command(t, command, "OK", "ERROR", timeout_ms); } command_result sync(CommandableIf *t)