diff --git a/esp_modem/examples/ap_to_pppos/main/CMakeLists.txt b/esp_modem/examples/ap_to_pppos/main/CMakeLists.txt index a18b3c44a..7a59f37cf 100644 --- a/esp_modem/examples/ap_to_pppos/main/CMakeLists.txt +++ b/esp_modem/examples/ap_to_pppos/main/CMakeLists.txt @@ -1,3 +1,5 @@ idf_component_register(SRCS "ap2pppos_example_main.c" - "modem_board.c" - INCLUDE_DIRS ".") \ No newline at end of file + "NetworkDCE.cpp" + INCLUDE_DIRS ".") + +#target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17) \ No newline at end of file diff --git a/esp_modem/examples/ap_to_pppos/main/NetworkDCE.cpp b/esp_modem/examples/ap_to_pppos/main/NetworkDCE.cpp new file mode 100644 index 000000000..d6a4130f1 --- /dev/null +++ b/esp_modem/examples/ap_to_pppos/main/NetworkDCE.cpp @@ -0,0 +1,116 @@ +// +// Created by david on 3/25/21. +// +#include "cxx_include/esp_modem_dte.hpp" +#include "esp_modem_config.h" +#include "cxx_include/esp_modem_api.hpp" +#include "cxx_include/esp_modem_dce_factory.hpp" +#include +#include + +class NetModule; +typedef DCE_T NetDCE; + +class NetModule: public ModuleIf { +public: + explicit NetModule(std::shared_ptr dte): + dte(std::move(dte)) {} + + bool setup_data_mode() override + { + set_command_mode(); // send in case we were in PPP mode, ignore potential failure + bool is_pin_ok; + if (read_pin(is_pin_ok) != command_result::OK) + return false; + if (!is_pin_ok) { + if (set_pin(pin) != command_result::OK) + return ESP_FAIL; + vTaskDelay(pdMS_TO_TICKS(1000)); + if (read_pin(is_pin_ok) != command_result::OK || !is_pin_ok) + return ESP_FAIL; + } + + PdpContext pdp(apn); + if (set_pdp_context(pdp) != command_result::OK) + return false; + return true; + } + + bool set_mode(modem_mode mode) override + { + if (mode == modem_mode::DATA_MODE) { + if (set_data_mode() != command_result::OK) + return resume_data_mode() == command_result::OK; + return true; + } + if (mode == modem_mode::COMMAND_MODE) { + return set_command_mode() == command_result::OK; + } + return false; + } + + static esp_err_t init(esp_netif_t *netif, std::string apn_name, std::string pin_number) + { + apn = std::move(apn_name); + pin = std::move(pin_number); + esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); + dte_config.event_task_stack_size = 4096; + dte_config.rx_buffer_size = 16384; + dte_config.tx_buffer_size = 2048; + + // create + auto uart_dte = create_uart_dte(&dte_config); + esp_modem::DCE::Factory f(esp_modem::DCE::Modem::MinModule); + MinimalModule* module; + if (!f.build_module_T(module, uart_dte, netif)) { + return ESP_OK; + } + esp_modem::DCE::Factory f2(esp_modem::DCE::Modem::SIM7600); +// std::shared_ptr dev; + auto dev = f2.build_shared_module(uart_dte, netif); + + // esp_modem::DCE::Builder factory(uart_dte, netif); +// dce = factory.create(apn_name); +// auto pdp = std::make_unique(apn); +// auto dev = std::make_shared(uart_dte, std::move(pdp)); +// auto dev = std::make_shared(uart_dte, nullptr); +// dce = new DCE_T(uart_dte, module, netif); + return ESP_OK; + } + + static void deinit() { delete dce; } + static void start() { dce->set_data(); } + static void stop() { dce->exit_data(); } + +private: + static NetDCE *dce; + std::shared_ptr dte; + static std::string apn; + static std::string pin; + + template command_result set_pdp_context(T&&... args) { return esp_modem::dce_commands::set_pdp_context(dte.get(),std::forward(args)...); } + template command_result set_pin(T&&... args) { return esp_modem::dce_commands::set_pin(dte.get(),std::forward(args)...); } + template command_result read_pin(T&&... args) { return esp_modem::dce_commands::read_pin(dte.get(),std::forward(args)...); } + command_result set_data_mode() { return esp_modem::dce_commands::set_data_mode(dte.get()); } + command_result resume_data_mode() { return esp_modem::dce_commands::resume_data_mode(dte.get()); } + command_result set_command_mode() { return esp_modem::dce_commands::set_command_mode(dte.get()); } +}; + +NetDCE *NetModule::dce = nullptr; +std::string NetModule::apn; +std::string NetModule::pin; + +extern "C" esp_err_t modem_init_network(esp_netif_t *netif) +{ + return NetModule::init(netif, "internet", "1234"); +} + +extern "C" void modem_start_network() +{ + NetModule::start(); +} + +extern "C" void modem_stop_network() +{ + NetModule::stop(); +} diff --git a/esp_modem/examples/ap_to_pppos/main/ap2pppos_example_main.c b/esp_modem/examples/ap_to_pppos/main/ap2pppos_example_main.c index 7830c8f60..46d1322f7 100644 --- a/esp_modem/examples/ap_to_pppos/main/ap2pppos_example_main.c +++ b/esp_modem/examples/ap_to_pppos/main/ap2pppos_example_main.c @@ -12,7 +12,6 @@ #include "esp_event.h" #include "esp_log.h" #include "nvs_flash.h" -#include "esp_modem.h" #include "lwip/lwip_napt.h" #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" @@ -35,6 +34,7 @@ static void on_modem_event(void *arg, esp_event_base_t event_base, if (event_id == IP_EVENT_PPP_GOT_IP) { esp_netif_dns_info_t dns_info; + ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; esp_netif_t *netif = event->esp_netif; @@ -59,9 +59,6 @@ static void on_modem_event(void *arg, esp_event_base_t event_base, ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data; ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip)); } - } else if (event_base == ESP_MODEM_EVENT) { - ESP_LOGD(TAG, "Modem event! %d", event_id); - } } @@ -125,7 +122,9 @@ void wifi_init_softap(void) EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL); } -esp_modem_dce_t *sim7600_board_create(esp_modem_dce_config_t *config); +esp_err_t modem_init_network(esp_netif_t *netif); +void modem_start_network(); +void modem_stop_network(); void app_main(void) { @@ -142,29 +141,32 @@ void app_main(void) event_group = xEventGroupCreate(); // init the DTE - esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); - dte_config.event_task_stack_size = 4096; - dte_config.rx_buffer_size = 16384; - dte_config.tx_buffer_size = 2048; - esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet23"); - dce_config.populate_command_list = true; esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP(); + esp_netif_t *ppp_netif = esp_netif_new(&ppp_netif_config); + assert(ppp_netif); + + ESP_ERROR_CHECK(modem_init_network(ppp_netif)); +// vTaskDelay(pdMS_TO_TICKS(1000)); +// esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); +// dte_config.event_task_stack_size = 4096; +// dte_config.rx_buffer_size = 16384; +// dte_config.tx_buffer_size = 2048; +// esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet23"); +// dce_config.populate_command_list = true; // Initialize esp-modem units, DTE, DCE, ppp-netif - esp_modem_dte_t *dte = esp_modem_dte_new(&dte_config); - esp_modem_dce_t *dce = sim7600_board_create(&dce_config); - esp_netif_t *ppp_netif = esp_netif_new(&ppp_netif_config); - - assert(ppp_netif); - - ESP_ERROR_CHECK(esp_modem_set_event_handler(dte, on_modem_event, ESP_EVENT_ANY_ID, dte)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_modem_event, dte)); - - ESP_ERROR_CHECK(esp_modem_default_attach(dte, dce, ppp_netif)); - - ESP_ERROR_CHECK(esp_modem_default_start(dte)); // use retry - ESP_ERROR_CHECK(esp_modem_start_ppp(dte)); +// esp_modem_dte_t *dte = esp_modem_dte_new(&dte_config); +// esp_modem_dce_t *dce = sim7600_board_create(&dce_config); +// +// ESP_ERROR_CHECK(esp_modem_set_event_handler(dte, on_modem_event, ESP_EVENT_ANY_ID, dte)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_modem_event, NULL)); +// +// ESP_ERROR_CHECK(esp_modem_default_attach(dte, dce, ppp_netif)); +// +// ESP_ERROR_CHECK(esp_modem_default_start(dte)); // use retry +// ESP_ERROR_CHECK(esp_modem_start_ppp(dte)); + modem_start_network(); /* Wait for the first connection */ EventBits_t bits; do { @@ -186,8 +188,8 @@ void app_main(void) /* Provide recovery if disconnection of some kind registered */ while (DISCONNECT_BIT&xEventGroupWaitBits(event_group, DISCONNECT_BIT, pdTRUE, pdFALSE, portMAX_DELAY)) { // restart the modem PPP mode - ESP_ERROR_CHECK(esp_modem_stop_ppp(dte)); - ESP_ERROR_CHECK(esp_modem_start_ppp(dte)); + modem_stop_network(); + modem_start_network(); } } diff --git a/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp b/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp new file mode 100644 index 000000000..3e79aa13c --- /dev/null +++ b/esp_modem/include/cxx_include/esp_modem_dce_factory.hpp @@ -0,0 +1,261 @@ +// +// Created by david on 3/28/21. +// + +#ifndef AP_TO_PPPOS_ESP_MODEM_DCE_FACTORY_HPP +#define AP_TO_PPPOS_ESP_MODEM_DCE_FACTORY_HPP + +namespace esp_modem::DCE { + + + class FactoryHelper { + public: + static std::unique_ptr create_pdp_context(std::string &apn); + + template + static bool make(T* &t, Args&&... args) + { + t = new T(std::forward(args)...); + return true; + } + + template + static bool make(std::shared_ptr &t, Args&&... args) + { + t = std::make_shared(std::forward(args)...); + return true; + } + + template + static bool make(std::unique_ptr &t, Args&&... args) + { + t = std::unique_ptr(std::forward(args)...); + return true; + } + +// template +// static T* make(Args&&... args) +// { +// return new T(std::forward(args)...); +// } +// template +// static std::shared_ptr make(Args&&... args) +// { +// return std::make_shared(std::forward(args)...); +// } +// template +// static std::unique_ptr make(Args&&... args) +// { +// return std::unique_ptr(new T(std::forward(args)...)); +// } + + + }; + + template + class Builder { + public: + explicit Builder(std::shared_ptr dte): dte(std::move(dte)) + { + esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_PPP(); + netif = esp_netif_new(&netif_config); + throw_if_false(netif != nullptr, "Cannot create default PPP netif"); + } + + Builder(std::shared_ptr dte, esp_netif_t* esp_netif): dte(std::move(dte)), module(nullptr), netif(esp_netif) + { + throw_if_false(netif != nullptr, "Null netif"); + } + + Builder(std::shared_ptr dte, esp_netif_t* esp_netif, std::shared_ptr dev): dte(std::move(dte)), module(std::move(dev)), netif(esp_netif) + { + throw_if_false(netif != nullptr, "Null netif"); + } + + ~Builder() + { + throw_if_false(netif == nullptr, "Netif created but never used"); + throw_if_false(dte == nullptr, "dte was captured but never used"); + } + + DCE_T* create(std::string &apn) + { + return create_dce(dte, netif, apn); + } + + template + bool create_module(U &t, std::string &apn) + { + auto pdp = FactoryHelper::create_pdp_context(apn); +// t = new T(std::move(dte), std::move(pdp)); + return FactoryHelper::make(t, std::move(dte), std::move(pdp)); + return true; + } + +// bool create_module(std::shared_ptr &t, std::string &apn) +// { +// auto pdp = FactoryHelper::create_pdp_context(apn); +// t = std::make_shared(std::move(dte), std::move(pdp)); +// return true; +// } + + template + U create_device(std::string &apn) + { + auto pdp = FactoryHelper::create_pdp_context(apn); + return FactoryHelper::make(std::move(dte), std::move(pdp)); + } + + T* create_dev(std::string &apn) + { + auto pdp = FactoryHelper::create_pdp_context(apn); + return new T(std::move(dte), std::move(pdp)); + } + + std::shared_ptr create_shared_dev(std::string &apn) + { + auto pdp = FactoryHelper::create_pdp_context(apn); + return std::make_shared(std::move(dte), std::move(pdp)); + } + + static DCE_T* create_dce_from_module(const std::shared_ptr& dte, const std::shared_ptr& dev, esp_netif_t *netif) + { + return new DCE_T(dte, dev, netif); + } + + static std::unique_ptr> create_unique_dce_from_module(const std::shared_ptr& dte, const std::shared_ptr& dev, esp_netif_t *netif) + { + return std::unique_ptr>(new DCE_T(dte, dev, netif)); + } + + static std::shared_ptr create_module(const std::shared_ptr& dte, std::string &apn) + { + auto pdp = FactoryHelper::create_pdp_context(apn); + return std::make_shared(dte, std::move(pdp)); + } + + static std::unique_ptr> create_unique_dce(const std::shared_ptr& dte, esp_netif_t *netif, std::string &apn) + { + auto module = create_module(dte, apn); + return create_unique_dce_from_module(dte, std::move(module), netif); + } + + static DCE_T* create_dce(const std::shared_ptr& dte, esp_netif_t *netif, std::string &apn) + { + auto module = create_module(dte, apn); + return create_dce_from_module(dte, std::move(module), netif); + } + + private: + std::shared_ptr dte; + std::shared_ptr module; + esp_netif_t *netif; + }; + + enum class Modem { + SIM800, + SIM7600, + BG96, + MinModule + }; + class Factory { + public: + explicit Factory(Modem modem): m(modem) {} + + template + T* create(Builder b, std::string apn) + { + return b.create_dev(apn); + } + + template + std::shared_ptr create(Builder b, std::string apn) + { + return b.create_shared_dev(apn); + } + + template +// std::shared_ptr build_module_T(Args&&... args) +// bool build_module_T(std::shared_ptr &t, Args&&... args) + bool build_module_T(U &t, Args&&... args) + { + Builder b(std::forward(args)...); + std::string apn = "internet"; + return b.create_module(t, apn); +// return b.create_shared_dev(apn); + } +// template +// T* build_module_T(Args&&... args) +// { +// Builder b(std::forward(args)...); +// std::string apn = "internet"; +// return b.create_dev(apn); +// } + + template + T build_module_T(Args&&... args) + { +// Builder b(std::forward(args)...); +// std::string apn = "internet"; +// return b.template create_device(apn); + + + T module; + if (build_module_T(module, std::forward(args)...)) + return module; + return nullptr; + } + + template + T build_module_xxT(Args&&... args) + { + T generic_module = nullptr; + switch (m) { + case Modem::MinModule: + break; + case Modem::SIM7600: { + SIM7600 *module; + if (build_module_T(module, std::forward(args)...)) + generic_module = module; + break; + } + case Modem::SIM800: { + SIM800 *module; + if (build_module_T(module, std::forward(args)...)) + generic_module = module; + break; + } + case Modem::BG96: { + BG96 *module; + if (build_module_T(module, std::forward(args)...)) + generic_module = module; + break; + } + } + return generic_module; + } + + template + std::shared_ptr build_shared_module_specific(Args&&... args) + { + return build_module_T, T>(std::forward(args)...); + } + + template + std::shared_ptr build_shared_module(Args&&... args) + { +// Builder b(std::forward(args)...); +// std::string apn = "internet"; +// return b.template create_device>(apn); + + return build_shared_module_specific(std::forward(args)...); + } + + + private: + Modem m; + }; + +} // esp_modem + +#endif //AP_TO_PPPOS_ESP_MODEM_DCE_FACTORY_HPP diff --git a/esp_modem/include/cxx_include/esp_modem_dce_module.hpp b/esp_modem/include/cxx_include/esp_modem_dce_module.hpp index 7b1ee8ad8..351193a7d 100644 --- a/esp_modem/include/cxx_include/esp_modem_dce_module.hpp +++ b/esp_modem/include/cxx_include/esp_modem_dce_module.hpp @@ -8,9 +8,9 @@ enum class command_result; class DTE; -class GenericModule: public ModuleIf { +class MinimalModule: public ModuleIf { public: - explicit GenericModule(std::shared_ptr dte, std::unique_ptr pdp): + explicit MinimalModule(std::shared_ptr dte, std::unique_ptr pdp): dte(std::move(dte)), pdp(std::move(pdp)) {} bool setup_data_mode() override @@ -36,20 +36,31 @@ public: return true; } - -#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \ - virtual return_type name(__VA_ARGS__); - - DECLARE_ALL_COMMAND_APIS(virtual return_type name(...); ) - -#undef ESP_MODEM_DECLARE_DCE_COMMAND - + template command_result set_echo(T&&... args) { return esp_modem::dce_commands::set_echo(dte.get(),std::forward(args)...); } + template command_result set_pdp_context(T&&... args) { return esp_modem::dce_commands::set_pdp_context(dte.get(),std::forward(args)...); } + template command_result set_data_mode(T&&... args) { return esp_modem::dce_commands::set_data_mode(dte.get(),std::forward(args)...); } + template command_result resume_data_mode(T&&... args) { return esp_modem::dce_commands::resume_data_mode(dte.get(),std::forward(args)...); } + template command_result set_command_mode(T&&... args) { return esp_modem::dce_commands::set_command_mode(dte.get(),std::forward(args)...); } + template command_result set_cmux(T&&... args) { return esp_modem::dce_commands::set_cmux(dte.get(),std::forward(args)...); } protected: std::shared_ptr dte; std::unique_ptr pdp; }; +class GenericModule: public MinimalModule { + using MinimalModule::MinimalModule; +public: + +#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \ + virtual return_type name(__VA_ARGS__); + + DECLARE_ALL_COMMAND_APIS(virtual return_type name(...);) + +#undef ESP_MODEM_DECLARE_DCE_COMMAND +}; + + // Definitions of other modules class SIM7600: public GenericModule { using GenericModule::GenericModule; @@ -64,6 +75,7 @@ public: }; class BG96: public GenericModule { + using GenericModule::GenericModule; public: command_result get_module_name(std::string& name) override; }; diff --git a/esp_modem/src/esp_modem_netif.cpp b/esp_modem/src/esp_modem_netif.cpp index 544f64272..59cc69f99 100644 --- a/esp_modem/src/esp_modem_netif.cpp +++ b/esp_modem/src/esp_modem_netif.cpp @@ -33,7 +33,7 @@ esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len) { Netif *ppp = (Netif*)h; if (ppp->signal.is_any(PPP_STARTED)) { - std::cout << "sending data " << len << std::endl; +// std::cout << "sending data " << len << std::endl; if (ppp->ppp_dte->write((uint8_t*)buffer, len) > 0) { return ESP_OK; } @@ -66,7 +66,7 @@ esp_err_t Netif::esp_modem_post_attach(esp_netif_t * esp_netif, void * args) void Netif::receive(uint8_t *data, size_t len) { if (signal.is_any(PPP_STARTED)) { - std::cout << "received data " << len << std::endl; +// std::cout << "received data " << len << std::endl; esp_netif_receive(driver.base.netif, data, len, nullptr); } } diff --git a/esp_modem/src/esp_modem_uart.cpp b/esp_modem/src/esp_modem_uart.cpp index 9fbf5d77b..8d81a07b9 100644 --- a/esp_modem/src/esp_modem_uart.cpp +++ b/esp_modem/src/esp_modem_uart.cpp @@ -191,10 +191,10 @@ void uart_terminal::task() } switch (event.type) { case UART_DATA: - ESP_LOGI(TAG, "UART_DATA"); +// ESP_LOGI(TAG, "UART_DATA"); // ESP_LOG_BUFFER_HEXDUMP("esp-modem-pattern: debug_data", esp_dte->buffer, length, ESP_LOG_DEBUG); uart_get_buffered_data_len(uart.port, &len); - ESP_LOGI(TAG, "UART_DATA len=%d, on_data=%d", len, (bool)on_data); +// ESP_LOGI(TAG, "UART_DATA len=%d, on_data=%d", len, (bool)on_data); if (len && on_data_priv) { if (on_data_priv(len)) { on_data_priv = nullptr;