Final cleanup of the docs and examples

This commit is contained in:
David Cermak
2021-05-18 19:10:32 +02:00
parent 6e9ddbef32
commit ac475f2560
30 changed files with 359 additions and 332 deletions

View File

@ -1,18 +0,0 @@
menu "ESP-MODEM"
config MODEM_LEGACY_API
bool "Enable Legacy API"
default y
help
Set to true if the original pppos_client API from the example's internal
component should be used.....
config MODEM_PPP_APN
string "Local netif hostname"
default 'internet'
depends on MODEM_LEGACY_API
help
APN (Access Point Name), a logical name of a network
the modem connects to in the PPP mode
endmenu

View File

@ -10,6 +10,8 @@ Get started with one of the examples:
* `examples/modem_console` -- C++ example implementing simple terminal console with DCE commands * `examples/modem_console` -- C++ example implementing simple terminal console with DCE commands
* `examples/ap_to_pppos` -- this example focuses on the network connectivity of the esp-modem and provides a WiFi AP * `examples/ap_to_pppos` -- this example focuses on the network connectivity of the esp-modem and provides a WiFi AP
that forwards packets (and uses NAT) to and from the PPPoS connection. that forwards packets (and uses NAT) to and from the PPPoS connection.
* `examples/simple_cmux_client` -- this example sets up the CMUX mode to talk to the modem using AT commands
with simultaneously maintaining active network connection.
## Documentation ## Documentation

View File

@ -1,3 +0,0 @@
COMPONENT_ADD_INCLUDEDIRS := include
COMPONENT_PRIV_INCLUDEDIRS := private_include
COMPONENT_SRCDIRS := src

View File

@ -31,11 +31,14 @@ the specific module, using :cpp:func:`esp_modem::dce_factory::Factory::build`.
Please refer to the implementation of the existing modules. Please refer to the implementation of the existing modules.
Please note that the ``modem_console`` example defines a trivial custom modem DCE which overrides one command,
for demonstration purposes only.
Create new communication interface Create new communication interface
---------------------------------- ----------------------------------
In order to connect to a device using an unsuppoeted interface (e.g. SPI or I2C), it is necessary to implement In order to connect to a device using an unsupported interface (e.g. SPI or I2C), it is necessary to implement
a custom DTE object and supply it into :ref:`the DCE factory<dce_factory>`. The DCE is typically created in two steps: a custom DTE object and supply it into :ref:`the DCE factory<dce_factory>`. The DCE is typically created in two steps:
- Define and create the corresponding terminal, which can communicate on the custom interface. This terminal should support basic IO methods defined in :cpp:class:`esp_modem::Terminal` and derive from it. - Define and create the corresponding terminal, which can communicate on the custom interface. This terminal should support basic IO methods defined in :cpp:class:`esp_modem::Terminal` and derive from it.

View File

@ -1,9 +0,0 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := ap-to-pppos
include $(IDF_PATH)/make/project.mk

View File

@ -1,11 +1,17 @@
# PPPoS simple client example # AP to PPPoS example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## Overview ## Overview
This example focuses on the networking part, enables forwarding packets between network interfaces. It creates a WiFi soft AP, which uses NAT to forward packets to and from the PPP network This example focuses on the networking part, enables forwarding packets between network interfaces. It creates a WiFi soft AP, which uses NAT to forward packets to and from the PPP network
interface. interface.
## How to use this example ### Specific network DCE
See the README.md file in the upper level `pppos` directory for more information about the PPPoS examples. Note, that this example could use of a minimal Network DCE, defined in the `network_dce.cpp` file.
Please set `EXAMPLE_USE_MINIMAL_DCE` to `y` in order to demonstrate this functionality.
By default, this example simply connects to the PPP server using a supported device with C-API modem interface.
This example however, doesn't rely on sending specific AT commands, just the bare minimum to setup the cellular network.
Thus, if the `EXAMPLE_USE_MINIMAL_DCE` option is enabled, we directly inherit from the `ModuleIf` and implement only the basic commands.
Also, to demonstrate the dce_factory functionality, a new `NetDCE_Factory` is implemented for creating the network module and the DCE.

View File

@ -1,5 +1,9 @@
idf_component_register(SRCS "ap2pppos_example_main.c" if(CONFIG_EXAMPLE_USE_MINIMAL_DCE)
"NetworkDCE.cpp" set(NETWORK_DCE "network_dce.cpp")
INCLUDE_DIRS ".") else()
set(NETWORK_DCE "network_dce.c")
endif()
#target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17) idf_component_register(SRCS "ap_to_pppos.c"
${NETWORK_DCE}
INCLUDE_DIRS ".")

View File

@ -11,6 +11,7 @@ menu "Example Configuration"
default "mypassword" default "mypassword"
help help
WiFi password (WPA or WPA2) for the example to use. WiFi password (WPA or WPA2) for the example to use.
config ESP_WIFI_CHANNEL config ESP_WIFI_CHANNEL
int "WiFi Channel" int "WiFi Channel"
range 1 13 range 1 13
@ -23,4 +24,24 @@ menu "Example Configuration"
default 4 default 4
help help
Max number of the STA connects to AP. Max number of the STA connects to AP.
config EXAMPLE_MODEM_PPP_APN
string "Set MODEM APN"
default "internet"
help
Set APN (Access Point Name), a logical name to choose data network
config EXAMPLE_SIM_PIN
string "Set SIM PIN"
default "1234"
help
Pin to unlock the SIM
config EXAMPLE_USE_MINIMAL_DCE
bool "Use minimal network DCE"
default n
help
Define a specific network only DCE class and
create it using DCE factory
endmenu endmenu

View File

@ -15,13 +15,16 @@
#include "lwip/lwip_napt.h" #include "lwip/lwip_napt.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h" #include "freertos/event_groups.h"
#include "network_dce.h"
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID #define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD #define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_WIFI_CHANNEL CONFIG_ESP_WIFI_CHANNEL #define EXAMPLE_ESP_WIFI_CHANNEL CONFIG_ESP_WIFI_CHANNEL
#define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN #define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN
static const char *TAG = "ap-2-pppos";
static const char *TAG = "ap_to_pppos";
static EventGroupHandle_t event_group = NULL; static EventGroupHandle_t event_group = NULL;
static const int CONNECT_BIT = BIT0; static const int CONNECT_BIT = BIT0;
static const int DISCONNECT_BIT = BIT1; static const int DISCONNECT_BIT = BIT1;
@ -62,7 +65,6 @@ static void on_ip_event(void *arg, esp_event_base_t event_base,
} }
} }
static esp_err_t set_dhcps_dns(esp_netif_t *netif, uint32_t addr) static esp_err_t set_dhcps_dns(esp_netif_t *netif, uint32_t addr)
{ {
esp_netif_dns_info_t dns; esp_netif_dns_info_t dns;
@ -88,6 +90,7 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base,
} }
} }
void wifi_init_softap(void) void wifi_init_softap(void)
{ {
@ -122,13 +125,9 @@ void wifi_init_softap(void)
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL); EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
} }
esp_err_t modem_init_network(esp_netif_t *netif);
void modem_start_network();
void modem_stop_network();
void app_main(void) void app_main(void)
{ {
//Initialize NVS // Initialize NVS
esp_err_t ret = nvs_flash_init(); esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase()); ESP_ERROR_CHECK(nvs_flash_erase());
@ -136,29 +135,33 @@ void app_main(void)
} }
ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(ret);
// Initialize esp_netif and default event loop
ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_event_loop_create_default());
event_group = xEventGroupCreate(); event_group = xEventGroupCreate();
// init the DTE // Initialize lwip network interface in PPP mode
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP(); esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
esp_netif_t *ppp_netif = esp_netif_new(&ppp_netif_config); esp_netif_t *ppp_netif = esp_netif_new(&ppp_netif_config);
assert(ppp_netif); assert(ppp_netif);
// Initialize the PPP network and register for IP event
ESP_ERROR_CHECK(modem_init_network(ppp_netif)); ESP_ERROR_CHECK(modem_init_network(ppp_netif));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event, NULL)); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event, NULL));
/* Init and start the modem network */ // Start the PPP network and wait for connection
modem_start_network(); modem_start_network();
/* Wait for the first connection */
EventBits_t bits; EventBits_t bits;
do { do {
bits = xEventGroupWaitBits(event_group, (CONNECT_BIT | DISCONNECT_BIT), pdTRUE, pdFALSE, portMAX_DELAY); bits = xEventGroupWaitBits(event_group, (CONNECT_BIT | DISCONNECT_BIT), pdTRUE, pdFALSE, portMAX_DELAY);
if (bits&DISCONNECT_BIT) { if (bits & DISCONNECT_BIT) {
ESP_LOGW(TAG, "Modem got disconnected from the PPP server: retrying...");
modem_stop_network();
modem_start_network();
} }
} while ((bits&CONNECT_BIT) == 0); } while ((bits & CONNECT_BIT) == 0);
/* Init the AP with NAT enabled */ // Initialize the AP and setup the NAT
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap(); esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
assert(ap_netif); assert(ap_netif);
esp_netif_dns_info_t dns; esp_netif_dns_info_t dns;
@ -168,11 +171,13 @@ void app_main(void)
wifi_init_softap(); wifi_init_softap();
ip_napt_enable(_g_esp_netif_soft_ap_ip.ip.addr, 1); ip_napt_enable(_g_esp_netif_soft_ap_ip.ip.addr, 1);
/* Provide recovery if disconnection of some kind registered */ // Provide a recovery if disconnection of some kind registered
while (DISCONNECT_BIT&xEventGroupWaitBits(event_group, DISCONNECT_BIT, pdTRUE, pdFALSE, portMAX_DELAY)) { while (true) {
// restart the modem PPP mode bits = xEventGroupWaitBits(event_group, DISCONNECT_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
modem_stop_network(); if (bits & DISCONNECT_BIT) {
modem_start_network(); ESP_LOGW(TAG, "Modem got disconnected from the PPP server: restarting the network...");
modem_stop_network();
modem_start_network();
}
} }
} }

View File

@ -1,8 +0,0 @@
#
# Main component makefile.
#
# This Makefile can be left empty. By default, it will take the sources in the
# src/ directory, compile them and link them into lib(subdirectory_name).a
# in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#

View File

@ -1,7 +0,0 @@
version: "0.0.2"
targets:
- esp32
description: pppos_client to AP
dependencies:
espressif/esp_modem:
version: "~0.0.2"

View File

@ -1,162 +0,0 @@
/* softAP to PPPoS Example (modem_board)
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_modem_recov_helper.h"
#include "esp_modem_dce.h"
#include "esp_modem_dce_common_commands.h"
#define ESP_MODEM_EXAMPLE_CHECK(a, str, goto_tag, ...) \
do \
{ \
if (!(a)) \
{ \
ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
goto goto_tag; \
} \
} while (0)
static const char *TAG = "sim7600_board";
typedef struct {
esp_modem_dce_t parent;
esp_modem_recov_gpio_t *power_pin;
esp_modem_recov_gpio_t *reset_pin;
esp_err_t (*reset)(esp_modem_dce_t *dce);
esp_err_t (*power_down)(esp_modem_dce_t *dce);
esp_modem_recov_resend_t *re_sync;
esp_modem_recov_resend_t *re_store_profile;
} sim7600_board_t;
esp_err_t sim7600_board_handle_powerup(esp_modem_dce_t *dce, const char *line)
{
if (strstr(line, "PB DONE")) {
ESP_LOGI(TAG, "Board ready after hard reset/power-cycle");
}
return ESP_OK;
}
esp_err_t sim7600_board_deinit(esp_modem_dce_t *dce)
{
sim7600_board_t *board = __containerof(dce, sim7600_board_t, parent);
board->power_pin->destroy(board->power_pin);
board->power_pin->destroy(board->reset_pin);
esp_err_t err = esp_modem_command_list_deinit(&board->parent);
if (err == ESP_OK) {
free(dce);
}
return err;
}
esp_err_t sim7600_board_reset(esp_modem_dce_t *dce)
{
sim7600_board_t *board = __containerof(dce, sim7600_board_t, parent);
ESP_LOGI(TAG, "sim7600_board_reset!");
dce->handle_line = sim7600_board_handle_powerup;
board->power_pin->pulse(board->reset_pin);
return ESP_OK;
}
esp_err_t sim7600_board_power_up(esp_modem_dce_t *dce)
{
sim7600_board_t *board = __containerof(dce, sim7600_board_t, parent);
ESP_LOGI(TAG, "sim7600_board_power_up!");
dce->handle_line = sim7600_board_handle_powerup;
board->power_pin->pulse(board->power_pin);
return ESP_OK;
}
esp_err_t sim7600_board_power_down(esp_modem_dce_t *dce)
{
sim7600_board_t *board = __containerof(dce, sim7600_board_t, parent);
ESP_LOGI(TAG, "sim7600_board_power_down!");
/* power down sequence (typical values for SIM7600 Toff=min2.5s, Toff-status=26s) */
dce->handle_line = sim7600_board_handle_powerup;
board->power_pin->pulse_special(board->power_pin, 3000, 26000);
return ESP_OK;
}
static esp_err_t my_recov(esp_modem_recov_resend_t *retry_cmd, esp_err_t err, int timeouts, int errors)
{
esp_modem_dce_t *dce = retry_cmd->dce;
ESP_LOGI(TAG, "Current timeouts: %d and errors: %d", timeouts, errors);
if (err == ESP_ERR_TIMEOUT) {
if (timeouts < 2) {
// first timeout, try to exit data mode and sync again
dce->set_command_mode(dce, NULL, NULL);
esp_modem_dce_sync(dce, NULL, NULL);
} else if (timeouts < 3) {
// try to reset with GPIO if resend didn't help
sim7600_board_t *board = __containerof(dce, sim7600_board_t, parent);
board->reset(dce);
} else {
// otherwise power-cycle the board
sim7600_board_t *board = __containerof(dce, sim7600_board_t, parent);
board->power_down(dce);
esp_modem_dce_sync(dce, NULL, NULL);
}
} else {
// check if a PIN needs to be supplied in case of a failure
bool ready = false;
esp_modem_dce_read_pin(dce, NULL, &ready);
if (!ready) {
esp_modem_dce_set_pin(dce, "1234", NULL);
}
vTaskDelay(1000 / portTICK_RATE_MS);
esp_modem_dce_read_pin(dce, NULL, &ready);
if (!ready) {
return ESP_FAIL;
}
}
return ESP_OK;
}
static DEFINE_RETRY_CMD(re_sync_fn, re_sync, sim7600_board_t)
static DEFINE_RETRY_CMD(re_store_profile_fn, re_store_profile, sim7600_board_t)
esp_err_t sim7600_board_start_up(esp_modem_dce_t *dce)
{
// sim7600_board_t *board = __containerof(dce, sim7600_board_t, parent);
ESP_MODEM_EXAMPLE_CHECK(re_sync_fn(dce, NULL, NULL) == ESP_OK, "sending sync failed", err);
ESP_MODEM_EXAMPLE_CHECK(dce->set_echo(dce, (void*)false, NULL) == ESP_OK, "set_echo failed", err);
ESP_MODEM_EXAMPLE_CHECK(dce->set_flow_ctrl(dce, (void*)ESP_MODEM_FLOW_CONTROL_NONE, NULL) == ESP_OK, "set_flow_ctrl failed", err);
ESP_MODEM_EXAMPLE_CHECK(dce->store_profile(dce, NULL, NULL) == ESP_OK, "store_profile failed", err);
return ESP_OK;
err:
return ESP_FAIL;
}
esp_modem_dce_t *sim7600_board_create(esp_modem_dce_config_t *config)
{
sim7600_board_t *board = calloc(1, sizeof(sim7600_board_t));
ESP_MODEM_EXAMPLE_CHECK(board, "failed to allocate board-sim7600 object", err);
ESP_MODEM_EXAMPLE_CHECK(esp_modem_dce_init(&board->parent, config) == ESP_OK, "Failed to init sim7600", err);
/* power on sequence (typical values for SIM7600 Ton=500ms, Ton-status=16s) */
board->power_pin = esp_modem_recov_gpio_new( /*gpio_num*/ 12, /*inactive_level*/ 1, /*active_width*/
500, /*inactive_width*/ 16000);
/* reset sequence (typical values for SIM7600 Treset=200ms, wait 10s after reset */
board->reset_pin = esp_modem_recov_gpio_new( /*gpio_num*/ 13, /*inactive_level*/ 1, /*active_width*/
200, /*inactive_width*/ 10000);
board->parent.deinit = sim7600_board_deinit;
board->reset = sim7600_board_reset;
board->power_down = sim7600_board_power_down;
board->re_sync = esp_modem_recov_resend_new(&board->parent, board->parent.sync, my_recov, 5, 1);
board->parent.start_up = sim7600_board_start_up;
board->re_store_profile = esp_modem_recov_resend_new(&board->parent, board->parent.store_profile, my_recov, 2, 3);
board->parent.store_profile = re_store_profile_fn;
return &board->parent;
err:
return NULL;
}

View File

@ -0,0 +1,56 @@
/* softAP to PPPoS Example (network_dce)
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "esp_netif.h"
#include "esp_modem_api.h"
static esp_modem_dce_t *dce = NULL;
esp_err_t modem_init_network(esp_netif_t *netif)
{
// setup the DCE
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
dce = esp_modem_new(&dte_config, &dce_config, netif);
if (!dce) {
return ESP_FAIL;
}
// configure the PIN
bool pin_ok = false;
if (esp_modem_read_pin(dce, &pin_ok) == ESP_OK && pin_ok == false) {
if (esp_modem_set_pin(dce, CONFIG_EXAMPLE_SIM_PIN) == ESP_OK) {
vTaskDelay(pdMS_TO_TICKS(1000));
} else {
abort();
}
}
return ESP_OK;
}
void modem_deinit_network(void)
{
if (dce) {
esp_modem_destroy(dce);
dce = NULL;
}
}
void modem_start_network()
{
esp_modem_set_mode(dce, ESP_MODEM_MODE_DATA);
}
void modem_stop_network()
{
esp_modem_set_mode(dce, ESP_MODEM_MODE_COMMAND);
}

View File

@ -1,4 +1,4 @@
/* softAP to PPPoS Example (modem_board) /* softAP to PPPoS Example (network_dce)
This example code is in the Public Domain (or CC0 licensed, at your option.) This example code is in the Public Domain (or CC0 licensed, at your option.)
@ -13,6 +13,7 @@
#include "cxx_include/esp_modem_dce_factory.hpp" #include "cxx_include/esp_modem_dce_factory.hpp"
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "network_dce.h"
using namespace esp_modem; using namespace esp_modem;
using namespace esp_modem::dce_factory; using namespace esp_modem::dce_factory;
@ -26,6 +27,7 @@ typedef DCE_T<NetModule> NetDCE;
class PPPNetwork { class PPPNetwork {
public: public:
esp_err_t init(esp_netif_t *netif, const std::string& apn, const std::string &pin_number); esp_err_t init(esp_netif_t *netif, const std::string& apn, const std::string &pin_number);
void deinit();
NetDCE * get_dce(); NetDCE * get_dce();
private: private:
NetDCE *dce; NetDCE *dce;
@ -120,7 +122,6 @@ esp_err_t PPPNetwork::init(esp_netif_t *netif, const std::string& apn, const std
{ {
// configure // configure
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
dte_config.uart_config.event_task_stack_size = 4096;
dte_config.uart_config.rx_buffer_size = 16384; dte_config.uart_config.rx_buffer_size = 16384;
dte_config.uart_config.tx_buffer_size = 2048; dte_config.uart_config.tx_buffer_size = 2048;
esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(apn.c_str()); esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(apn.c_str());
@ -140,14 +141,23 @@ esp_err_t PPPNetwork::init(esp_netif_t *netif, const std::string& apn, const std
return ESP_OK; return ESP_OK;
} }
void PPPNetwork::deinit()
{
free(dce);
dce = nullptr;
}
NetDCE *PPPNetwork::get_dce() NetDCE *PPPNetwork::get_dce()
{ {
return dce; return dce;
} }
/**
* @brief Implement the C-API for the AP-2-PPP functionality
*/
extern "C" esp_err_t modem_init_network(esp_netif_t *netif) extern "C" esp_err_t modem_init_network(esp_netif_t *netif)
{ {
return ppp_network.init(netif, "internet", "1234"); return ppp_network.init(netif, CONFIG_EXAMPLE_MODEM_PPP_APN, CONFIG_EXAMPLE_SIM_PIN);
} }
extern "C" void modem_start_network() extern "C" void modem_start_network()
@ -159,3 +169,8 @@ extern "C" void modem_stop_network()
{ {
ppp_network.get_dce()->set_mode(esp_modem::modem_mode::COMMAND_MODE); ppp_network.get_dce()->set_mode(esp_modem::modem_mode::COMMAND_MODE);
} }
extern "C" void modem_deinit_network()
{
ppp_network.deinit();
}

View File

@ -0,0 +1,47 @@
/* softAP to PPPoS Example (network_dce)
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#ifndef _NETWORK_DCE_H_
#define _NETWORK_DCE_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize a singleton covering the PPP network provided by the connected modem device
*
* @param netif Already created network interface in PPP mode
*
* @return ESP_OK on success
*/
esp_err_t modem_init_network(esp_netif_t *netif);
/**
* @brief Destroys the single network DCE
*/
void modem_deinit_network();
/**
* @brief Starts the PPP network
*/
void modem_start_network();
/**
* @brief Stops the PPP network
*/
void modem_stop_network();
#ifdef __cplusplus
}
#endif
#endif //_NETWORK_DCE_H_

View File

@ -1,12 +1,8 @@
# Override some defaults to enable PPP
CONFIG_LWIP_PPP_SUPPORT=y CONFIG_LWIP_PPP_SUPPORT=y
CONFIG_LWIP_PPP_PAP_SUPPORT=y CONFIG_LWIP_PPP_PAP_SUPPORT=y
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
# Do not enable IPV6 in dte<->dce link local
CONFIG_LWIP_PPP_ENABLE_IPV6=n CONFIG_LWIP_PPP_ENABLE_IPV6=n
# Disable legacy API CONFIG_UART_ISR_IN_IRAM=y
CONFIG_MODEM_LEGACY_API=n
# Enable NAPT # Enable NAPT
CONFIG_LWIP_IP_FORWARD=y CONFIG_LWIP_IP_FORWARD=y
CONFIG_LWIP_IPV4_NAPT=y CONFIG_LWIP_IPV4_NAPT=y

View File

@ -3,8 +3,15 @@
(See the README.md file in the upper level 'examples' directory for more information about examples.) (See the README.md file in the upper level 'examples' directory for more information about examples.)
## Overview ## Overview
This example is mainly targets experimenting with a modem device, sending custom commands and switching to PPP mode using esp-console, command line API. This example is mainly targets experimenting with a modem device, sending custom commands and switching to PPP mode using esp-console, command line API.
Please check the list of supported commands using `help` command.
## How to use this example This example implements two very simple network commands to demonstrate and test basic network functionality.
* `httpget`: Connect and get http content
* `ping`: Send ICMP pings
See the README.md file in the upper level `pppos` directory for more information about the PPPoS examples. To demonstrate creating custom modem devices, this example creates a DCE object using a locally defined create method,
that sets up the DCE based on a custom module implemented in the `my_module_dce.hpp` file. The module class only overrides
`get_module_name()` method supplying a user defined name, but keeps all other commands the same as defined in the `GenericModule`
class.

View File

@ -20,15 +20,7 @@
#include "cxx_include/esp_modem_api.hpp" #include "cxx_include/esp_modem_api.hpp"
#include "esp_log.h" #include "esp_log.h"
#include "console_helper.hpp" #include "console_helper.hpp"
#include "my_module_dce.hpp"
extern "C" void modem_console_register_http(void);
extern "C" void modem_console_register_ping(void);
static const char *TAG = "modem_console";
static esp_console_repl_t *s_repl = nullptr;
using namespace esp_modem;
#define CHECK_ERR(cmd, success_action) do { \ #define CHECK_ERR(cmd, success_action) do { \
auto err = cmd; \ auto err = cmd; \
@ -40,63 +32,67 @@ using namespace esp_modem;
return 1; \ return 1; \
} } while (0) } } while (0)
/**
* Please update the default APN name here (this could be updated runtime)
*/
#define DEFAULT_APN "my_apn"
extern "C" void modem_console_register_http(void);
extern "C" void modem_console_register_ping(void);
static const char *TAG = "modem_console";
static esp_console_repl_t *s_repl = nullptr;
using namespace esp_modem;
extern "C" void app_main(void) extern "C" void app_main(void)
{ {
ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_event_loop_create_default());
// init the DTE // init the netif, DTE and DCE respectively
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
esp_modem_dte_config_t dte_config2 = {
.dte_buffer_size = 512,
.vfs_config = {.port_num = UART_NUM_1,
.dev_name = "/dev/uart/1",
.rx_buffer_size = 1024,
.tx_buffer_size = 1024,
.baud_rate = 115200,
.tx_io_num = 25,
.rx_io_num = 26,
.task_stack_size = 4096,
.task_prio = 5}
};
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP(); esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
esp_netif_t *esp_netif = esp_netif_new(&ppp_netif_config); esp_netif_t *esp_netif = esp_netif_new(&ppp_netif_config);
assert(esp_netif); assert(esp_netif);
auto uart_dte = create_vfs_dte(&dte_config2); auto uart_dte = create_uart_dte(&dte_config);
// auto uart_dte = create_uart_dte(&dte_config); esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(DEFAULT_APN);
auto dce = create_shiny_dce(&dce_config, uart_dte, esp_netif);
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet");
auto dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif);
assert(dce != nullptr); assert(dce != nullptr);
// init console REPL environment
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
// init console REPL environment
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl)); ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl));
modem_console_register_http(); modem_console_register_http();
modem_console_register_ping(); modem_console_register_ping();
const struct SetModeArgs { const struct SetModeArgs {
SetModeArgs(): mode(STR1, nullptr, nullptr, "<mode>", "PPP or CMD") {} SetModeArgs(): mode(STR1, nullptr, nullptr, "<mode>", "PPP, CMD or CMUX") {}
CommandArgs mode; CommandArgs mode;
} set_mode_args; } set_mode_args;
const ConsoleCommand SetModeParser("set_mode", "sets modem mode", &set_mode_args, sizeof(set_mode_args), [&](ConsoleCommand *c){ const ConsoleCommand SetModeParser("set_mode", "sets modem mode", &set_mode_args, sizeof(set_mode_args), [&](ConsoleCommand *c){
if (c->get_count_of(&SetModeArgs::mode)) { if (c->get_count_of(&SetModeArgs::mode)) {
auto mode = c->get_string_of(&SetModeArgs::mode); auto mode = c->get_string_of(&SetModeArgs::mode);
modem_mode dev_mode;
if (mode == "CMD") { if (mode == "CMD") {
ESP_LOGI(TAG, "Switching to command mode..."); dev_mode = esp_modem::modem_mode::COMMAND_MODE;
dce->exit_data();
} else if (mode == "PPP") { } else if (mode == "PPP") {
ESP_LOGI(TAG, "Switching to data mode..."); dev_mode = esp_modem::modem_mode::DATA_MODE;
dce->set_data(); } else if (mode == "CMUX") {
dev_mode = esp_modem::modem_mode::CMUX_MODE;
} else { } else {
ESP_LOGE(TAG, "Unsupported mode: %s", mode.c_str()); ESP_LOGE(TAG, "Unsupported mode: %s", mode.c_str());
return 1; return 1;
} }
ESP_LOGI(TAG, "Switching to %s name...", mode.c_str());
if (!dce->set_mode(dev_mode)) {
ESP_LOGE(TAG, "Failed to set the desired mode");
return 1;
}
ESP_LOGI(TAG, "OK");
} }
return 0; return 0;
}); });
@ -151,7 +147,7 @@ extern "C" void app_main(void)
cmd(STR1, nullptr, nullptr, "<command>", "AT command to send to the modem"), cmd(STR1, nullptr, nullptr, "<command>", "AT command to send to the modem"),
timeout(INT0, "t", "timeout", "<timeout>", "command timeout"), timeout(INT0, "t", "timeout", "<timeout>", "command timeout"),
pattern(STR0, "p", "pattern", "<pattern>", "command response to wait for"), pattern(STR0, "p", "pattern", "<pattern>", "command response to wait for"),
no_cr(LIT0, "n", "no-cr", "not add trailing CR to the command") {} no_cr(LIT0, "n", "no-cr", "do not add trailing CR to the command") {}
CommandArgs cmd; CommandArgs cmd;
CommandArgs timeout; CommandArgs timeout;
CommandArgs pattern; CommandArgs pattern;
@ -193,6 +189,20 @@ extern "C" void app_main(void)
ESP_LOGI(TAG, "Resetting the module..."); ESP_LOGI(TAG, "Resetting the module...");
CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK")); CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK"));
}); });
const struct SetApn {
SetApn(): apn(STR1, nullptr, nullptr, "<apn>", "APN (Access Point Name)") {}
CommandArgs apn;
} set_apn;
const ConsoleCommand SetApnParser("set_apn", "sets APN", &set_apn, sizeof(set_apn), [&](ConsoleCommand *c){
if (c->get_count_of(&SetApn::apn)) {
auto apn = c->get_string_of(&SetApn::apn);
ESP_LOGI(TAG, "Setting the APN=%s...", apn.c_str());
auto new_pdp = std::unique_ptr<PdpContext>(new PdpContext(apn));
dce->get_module()->configure_pdp_context(std::move(new_pdp));
ESP_LOGI(TAG, "OK");
}
return 0;
});
SignalGroup exit_signal; SignalGroup exit_signal;
const ConsoleCommand ExitConsole("exit", "exit the console application", no_args, [&](ConsoleCommand *c){ const ConsoleCommand ExitConsole("exit", "exit the console application", no_args, [&](ConsoleCommand *c){

View File

@ -0,0 +1,43 @@
/* Modem console example: Custom DCE
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#ifndef __MY_MODULE_DCE_HPP__
#define __MY_MODULE_DCE_HPP__
#include "cxx_include/esp_modem_dce_factory.hpp"
#include "cxx_include/esp_modem_dce_module.hpp"
/**
* @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()`
*/
class MyShinyModem: public esp_modem::GenericModule {
using GenericModule::GenericModule;
public:
esp_modem::command_result get_module_name(std::string& name) override
{
name = "Custom Shiny Module";
return esp_modem::command_result::OK;
}
};
/**
* @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
*/
std::unique_ptr<esp_modem::DCE> create_shiny_dce(const esp_modem::dce_config *config,
std::shared_ptr<esp_modem::DTE> dte,
esp_netif_t *netif)
{
return esp_modem::dce_factory::Factory::build_unique<MyShinyModem>(config, std::move(dte), netif);
}
#endif //__MY_MODULE_DCE_HPP__

View File

@ -1,9 +0,0 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := pppos_client
include $(IDF_PATH)/make/project.mk

View File

@ -26,14 +26,6 @@ menu "Example Configuration"
help help
Set APN (Access Point Name), a logical name to choose data network Set APN (Access Point Name), a logical name to choose data network
config EXAMPLE_MODEM_LEGACY_API
bool "Use Modem legacy API"
default y
select MODEM_LEGACY_API
help
Set this to true to use backward compatible API to the original modem
component in example/protocol folder in IDFv4.2 and below
config EXAMPLE_MODEM_PPP_AUTH_USERNAME config EXAMPLE_MODEM_PPP_AUTH_USERNAME
string "Set username for authentication" string "Set username for authentication"
default "espressif" default "espressif"
@ -68,6 +60,19 @@ menu "Example Configuration"
Enter the peer phone number that you want to send message to. Enter the peer phone number that you want to send message to.
endif endif
config EXAMPLE_NEED_SIM_PIN
bool "SIM PIN needed"
default n
help
Enable to set SIM PIN before starting the example
config EXAMPLE_SIM_PIN
string "Set SIM PIN"
default "1234"
depends on EXAMPLE_NEED_SIM_PIN
help
Pin to unlock the SIM
menu "UART Configuration" menu "UART Configuration"
config EXAMPLE_MODEM_UART_TX_PIN config EXAMPLE_MODEM_UART_TX_PIN
int "TXD Pin Number" int "TXD Pin Number"

View File

@ -1,4 +0,0 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@ -20,10 +20,8 @@
static const char *TAG = "pppos_example"; static const char *TAG = "pppos_example";
static EventGroupHandle_t event_group = NULL; static EventGroupHandle_t event_group = NULL;
static const int CONNECT_BIT = BIT0; static const int CONNECT_BIT = BIT0;
//static const int STOP_BIT = BIT1;
static const int GOT_DATA_BIT = BIT2; static const int GOT_DATA_BIT = BIT2;
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
{ {
esp_mqtt_client_handle_t client = event->client; esp_mqtt_client_handle_t client = event->client;
@ -131,8 +129,8 @@ void app_main(void)
dte_config.uart_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE; dte_config.uart_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
dte_config.uart_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE; dte_config.uart_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
dte_config.uart_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE; dte_config.uart_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
dte_config.uart_config.event_task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE; dte_config.task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE;
dte_config.uart_config.event_task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY; dte_config.task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY;
dte_config.dte_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2; dte_config.dte_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2;
/* Configure the DCE */ /* Configure the DCE */
@ -147,6 +145,7 @@ void app_main(void)
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);
#if CONFIG_EXAMPLE_NEED_SIM_PIN == 1
// check if PIN needed // check if PIN needed
bool pin_ok = false; bool pin_ok = false;
if (esp_modem_read_pin(dce, &pin_ok) == ESP_OK && pin_ok == false) { if (esp_modem_read_pin(dce, &pin_ok) == ESP_OK && pin_ok == false) {
@ -156,6 +155,8 @@ void app_main(void)
abort(); abort();
} }
} }
#endif
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) {
@ -164,7 +165,7 @@ 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 CONFIG_EXAMPLE_SEND_MSG
if (esp_modem_sms_txt_mode(dce, true) != ESP_OK || esp_modem_sms_character_set(dce) != ESP_OK) { 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"); ESP_LOGE(TAG, "Setting text mode or GSM character set failed");
return; return;
@ -175,7 +176,6 @@ void app_main(void)
ESP_LOGE(TAG, "esp_modem_send_sms() failed with %d", err); ESP_LOGE(TAG, "esp_modem_send_sms() failed with %d", err);
return; return;
} }
#endif #endif
err = esp_modem_set_mode(dce, ESP_MODEM_MODE_DATA); err = esp_modem_set_mode(dce, ESP_MODEM_MODE_DATA);

View File

@ -3,5 +3,4 @@ CONFIG_LWIP_PPP_SUPPORT=y
CONFIG_LWIP_PPP_NOTIFY_PHASE_SUPPORT=y CONFIG_LWIP_PPP_NOTIFY_PHASE_SUPPORT=y
CONFIG_LWIP_PPP_PAP_SUPPORT=y CONFIG_LWIP_PPP_PAP_SUPPORT=y
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
# Do not enable IPV6 in dte<->dce link local
CONFIG_LWIP_PPP_ENABLE_IPV6=n CONFIG_LWIP_PPP_ENABLE_IPV6=n

View File

@ -1,4 +1,4 @@
version: "0.1.4" version: "0.1.5"
targets: targets:
- esp32 - esp32
description: esp modem description: esp modem

View File

@ -49,7 +49,13 @@ using dte_config = ::esp_modem_dte_config;
*/ */
std::shared_ptr<DTE> create_uart_dte(const dte_config *config); std::shared_ptr<DTE> create_uart_dte(const dte_config *config);
/**
* @brief Create VFS DTE
* @param config DTE configuration
* @return shared ptr to DTE on success
* nullptr on failure (either due to insufficient memory or wrong dte configuration)
* if exceptions are disabled the API abort()'s on error
*/
std::shared_ptr<DTE> create_vfs_dte(const dte_config *config); std::shared_ptr<DTE> create_vfs_dte(const dte_config *config);

View File

@ -53,8 +53,8 @@ template<class SpecificModule>
class DCE_T { class DCE_T {
static_assert(std::is_base_of<ModuleIf, SpecificModule>::value, "DCE must be instantiated with Module class only"); static_assert(std::is_base_of<ModuleIf, SpecificModule>::value, "DCE must be instantiated with Module class only");
public: public:
explicit DCE_T(const std::shared_ptr<DTE>& dte, std::shared_ptr<SpecificModule> device, esp_netif_t * netif): explicit DCE_T(const std::shared_ptr<DTE>& dte, std::shared_ptr<SpecificModule> dev, esp_netif_t * netif):
dte(dte), module(std::move(device)), netif(dte, netif) dte(dte), device(std::move(dev)), netif(dte, netif)
{ } { }
~DCE_T() = default; ~DCE_T() = default;
@ -68,21 +68,18 @@ public:
void set_cmux() { set_mode(modem_mode::CMUX_MODE); } void set_cmux() { set_mode(modem_mode::CMUX_MODE); }
ModuleIf* get_module() { return module.get(); } SpecificModule* get_module() { return device.get(); }
command_result command(const std::string& command, got_line_cb got_line, uint32_t time_ms) command_result command(const std::string& command, got_line_cb got_line, uint32_t time_ms)
{ {
return dte->command(command, std::move(got_line), time_ms); return dte->command(command, std::move(got_line), time_ms);
} }
bool set_mode(modem_mode m) { return mode.set(dte.get(), module.get(), netif, m); } bool set_mode(modem_mode m) { return mode.set(dte.get(), device.get(), netif, m); }
protected: protected:
std::shared_ptr<DTE> dte; std::shared_ptr<DTE> dte;
std::shared_ptr<SpecificModule> module; std::shared_ptr<SpecificModule> device;
Netif netif; Netif netif;
DCE_Mode mode; DCE_Mode mode;
}; };
@ -99,7 +96,7 @@ public:
template <typename ...Agrs> \ template <typename ...Agrs> \
return_type name(Agrs&&... args) \ return_type name(Agrs&&... args) \
{ \ { \
return module->name(std::forward<Agrs>(args)...); \ return device->name(std::forward<Agrs>(args)...); \
} }
DECLARE_ALL_COMMAND_APIS(forwards name(...) { device->name(...); } ) DECLARE_ALL_COMMAND_APIS(forwards name(...) { device->name(...); } )

View File

@ -64,19 +64,19 @@ template<typename Module>
class Builder { class Builder {
static_assert(std::is_base_of<ModuleIf, Module>::value, "Builder must be used only for Module classes"); static_assert(std::is_base_of<ModuleIf, Module>::value, "Builder must be used only for Module classes");
public: public:
Builder(std::shared_ptr<DTE> x, esp_netif_t* esp_netif): dte(std::move(x)), module(nullptr), netif(esp_netif) Builder(std::shared_ptr<DTE> x, esp_netif_t* esp_netif): dte(std::move(x)), device(nullptr), netif(esp_netif)
{ {
throw_if_false(netif != nullptr, "Null netif"); throw_if_false(netif != nullptr, "Null netif");
} }
Builder(std::shared_ptr<DTE> dte, esp_netif_t* esp_netif, std::shared_ptr<Module> dev): dte(std::move(dte)), module(std::move(dev)), netif(esp_netif) Builder(std::shared_ptr<DTE> dte, esp_netif_t* esp_netif, std::shared_ptr<Module> dev): dte(std::move(dte)), device(std::move(dev)), netif(esp_netif)
{ {
throw_if_false(netif != nullptr, "Null netif"); throw_if_false(netif != nullptr, "Null netif");
} }
~Builder() ~Builder()
{ {
throw_if_false(module == nullptr, "module was captured or created but never used"); throw_if_false(device == nullptr, "module was captured or created but never used");
} }
template<typename Ptr> template<typename Ptr>
@ -90,17 +90,17 @@ public:
{ {
if (dte == nullptr) if (dte == nullptr)
return nullptr; return nullptr;
if (module == nullptr) { if (device == nullptr) {
module = create_module<decltype(module)>(config); device = create_module<decltype(device)>(config);
if (module == nullptr) if (device == nullptr)
return nullptr; return nullptr;
} }
return FactoryHelper::make<DceT, Ptr>(std::move(dte), std::move(module), netif); return FactoryHelper::make<DceT, Ptr>(std::move(dte), std::move(device), netif);
} }
private: private:
std::shared_ptr<DTE> dte; std::shared_ptr<DTE> dte;
std::shared_ptr<Module> module; std::shared_ptr<Module> device;
esp_netif_t *netif; esp_netif_t *netif;
}; };

View File

@ -43,10 +43,20 @@ struct PdpContext;
*/ */
class GenericModule: public ModuleIf { class GenericModule: public ModuleIf {
public: public:
/**
* @brief We can construct a generic device with an existent DTE and it's configuration
* The configuration could be either the dce-config struct or just a pdp context
*/
explicit GenericModule(std::shared_ptr<DTE> dte, std::unique_ptr<PdpContext> pdp): explicit GenericModule(std::shared_ptr<DTE> dte, std::unique_ptr<PdpContext> pdp):
dte(std::move(dte)), pdp(std::move(pdp)) {} dte(std::move(dte)), pdp(std::move(pdp)) {}
explicit GenericModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config* config); explicit GenericModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config* config);
/**
* @brief This is a mandatory method for ModuleIf class, which sets up the device
* to be able to connect to the network. This typically consists of setting basic
* communication parameters and setting the PDP (defining logical access point
* to cellular network)
*/
bool setup_data_mode() override bool setup_data_mode() override
{ {
if (set_echo(false) != command_result::OK) if (set_echo(false) != command_result::OK)
@ -56,6 +66,10 @@ public:
return true; return true;
} }
/**
* @brief This is a mandatory method of ModuleIf class, which defines
* basic commands for switching between DATA, COMMAND and CMUX modes
*/
bool set_mode(modem_mode mode) override bool set_mode(modem_mode mode) override
{ {
if (mode == modem_mode::DATA_MODE) { if (mode == modem_mode::DATA_MODE) {
@ -70,7 +84,17 @@ public:
return true; return true;
} }
/**
* @brief Additional method providing runtime configuration of PDP context
*/
void configure_pdp_context(std::unique_ptr<PdpContext> new_pdp)
{
pdp = std::move(new_pdp);
}
/**
* @brief Common DCE commands generated from the API AT list
*/
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \ #define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
virtual return_type name(__VA_ARGS__); virtual return_type name(__VA_ARGS__);
@ -80,8 +104,8 @@ public:
protected: protected:
std::shared_ptr<DTE> dte; std::shared_ptr<DTE> dte; /*!< Generic device needs the DTE as a channel talk to the module using AT commands */
std::unique_ptr<PdpContext> pdp; std::unique_ptr<PdpContext> pdp; /*!< It also needs a PDP data, const information used for setting up cellular network */
}; };
// Definitions of other supported modules with some specific commands overwritten // Definitions of other supported modules with some specific commands overwritten

View File

@ -15,6 +15,7 @@
#ifndef _ESP_MODEM_API_H_ #ifndef _ESP_MODEM_API_H_
#define _ESP_MODEM_API_H_ #define _ESP_MODEM_API_H_
#include "esp_err.h"
#include "generate/esp_modem_command_declare.inc" #include "generate/esp_modem_command_declare.inc"
#include "esp_modem_c_api_types.h" #include "esp_modem_c_api_types.h"