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,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
(See the README.md file in the upper level 'examples' directory for more information about examples.)
# AP to PPPoS example
## 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
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"
"NetworkDCE.cpp"
INCLUDE_DIRS ".")
if(CONFIG_EXAMPLE_USE_MINIMAL_DCE)
set(NETWORK_DCE "network_dce.cpp")
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"
help
WiFi password (WPA or WPA2) for the example to use.
config ESP_WIFI_CHANNEL
int "WiFi Channel"
range 1 13
@ -23,4 +24,24 @@ menu "Example Configuration"
default 4
help
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

View File

@ -15,13 +15,16 @@
#include "lwip/lwip_napt.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "network_dce.h"
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_WIFI_CHANNEL CONFIG_ESP_WIFI_CHANNEL
#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 const int CONNECT_BIT = BIT0;
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)
{
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)
{
@ -122,13 +125,9 @@ void wifi_init_softap(void)
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)
{
//Initialize NVS
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
@ -136,29 +135,33 @@ void app_main(void)
}
ESP_ERROR_CHECK(ret);
// Initialize esp_netif and default event loop
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
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_t *ppp_netif = esp_netif_new(&ppp_netif_config);
assert(ppp_netif);
// Initialize the PPP network and register for IP event
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));
/* Init and start the modem network */
// Start the PPP network and wait for connection
modem_start_network();
/* Wait for the first connection */
EventBits_t bits;
do {
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();
assert(ap_netif);
esp_netif_dns_info_t dns;
@ -168,11 +171,13 @@ void app_main(void)
wifi_init_softap();
ip_napt_enable(_g_esp_netif_soft_ap_ip.ip.addr, 1);
/* 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
modem_stop_network();
modem_start_network();
// Provide a recovery if disconnection of some kind registered
while (true) {
bits = xEventGroupWaitBits(event_group, DISCONNECT_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
if (bits & DISCONNECT_BIT) {
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.)
@ -13,6 +13,7 @@
#include "cxx_include/esp_modem_dce_factory.hpp"
#include <memory>
#include <utility>
#include "network_dce.h"
using namespace esp_modem;
using namespace esp_modem::dce_factory;
@ -26,6 +27,7 @@ typedef DCE_T<NetModule> NetDCE;
class PPPNetwork {
public:
esp_err_t init(esp_netif_t *netif, const std::string& apn, const std::string &pin_number);
void deinit();
NetDCE * get_dce();
private:
NetDCE *dce;
@ -120,7 +122,6 @@ esp_err_t PPPNetwork::init(esp_netif_t *netif, const std::string& apn, const std
{
// configure
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.tx_buffer_size = 2048;
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;
}
void PPPNetwork::deinit()
{
free(dce);
dce = nullptr;
}
NetDCE *PPPNetwork::get_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)
{
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()
@ -159,3 +169,8 @@ extern "C" void modem_stop_network()
{
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_PAP_SUPPORT=y
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
# Do not enable IPV6 in dte<->dce link local
CONFIG_LWIP_PPP_ENABLE_IPV6=n
# Disable legacy API
CONFIG_MODEM_LEGACY_API=n
CONFIG_UART_ISR_IN_IRAM=y
# Enable NAPT
CONFIG_LWIP_IP_FORWARD=y
CONFIG_LWIP_IPV4_NAPT=y