mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-23 07:17:29 +02:00
esp_modem: Refactor the modem to a standalone managed component
This commit is contained in:
8
esp_modem/examples/ap_to_pppos/CMakeLists.txt
Normal file
8
esp_modem/examples/ap_to_pppos/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
# The following five lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(ap-to-pppos)
|
9
esp_modem/examples/ap_to_pppos/Makefile
Normal file
9
esp_modem/examples/ap_to_pppos/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# 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
|
||||
|
11
esp_modem/examples/ap_to_pppos/README.md
Normal file
11
esp_modem/examples/ap_to_pppos/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# PPPoS simple client example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## 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
|
||||
|
||||
See the README.md file in the upper level `pppos` directory for more information about the PPPoS examples.
|
3
esp_modem/examples/ap_to_pppos/main/CMakeLists.txt
Normal file
3
esp_modem/examples/ap_to_pppos/main/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS "ap2pppos_example_main.c"
|
||||
"modem_board.c"
|
||||
INCLUDE_DIRS ".")
|
26
esp_modem/examples/ap_to_pppos/main/Kconfig.projbuild
Normal file
26
esp_modem/examples/ap_to_pppos/main/Kconfig.projbuild
Normal file
@ -0,0 +1,26 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config ESP_WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) for the example to connect to.
|
||||
|
||||
config ESP_WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
config ESP_WIFI_CHANNEL
|
||||
int "WiFi Channel"
|
||||
range 1 13
|
||||
default 1
|
||||
help
|
||||
WiFi channel (network channel) for the example to use.
|
||||
|
||||
config ESP_MAX_STA_CONN
|
||||
int "Maximal STA connections"
|
||||
default 4
|
||||
help
|
||||
Max number of the STA connects to AP.
|
||||
endmenu
|
193
esp_modem/examples/ap_to_pppos/main/ap2pppos_example_main.c
Normal file
193
esp_modem/examples/ap_to_pppos/main/ap2pppos_example_main.c
Normal file
@ -0,0 +1,193 @@
|
||||
/* softAP to PPPoS Example
|
||||
|
||||
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_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#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"
|
||||
|
||||
#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 EventGroupHandle_t event_group = NULL;
|
||||
static const int CONNECT_BIT = BIT0;
|
||||
static const int DISCONNECT_BIT = BIT1;
|
||||
|
||||
static void on_modem_event(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == IP_EVENT) {
|
||||
ESP_LOGD(TAG, "IP event! %d", event_id);
|
||||
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;
|
||||
|
||||
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
||||
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
||||
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
||||
esp_netif_get_dns_info(netif, 0, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
esp_netif_get_dns_info(netif, 1, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||
|
||||
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||
xEventGroupSetBits(event_group, DISCONNECT_BIT);
|
||||
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||
ESP_LOGI(TAG, "GOT IPv6 event!");
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t set_dhcps_dns(esp_netif_t *netif, uint32_t addr)
|
||||
{
|
||||
esp_netif_dns_info_t dns;
|
||||
dns.ip.u_addr.ip4.addr = addr;
|
||||
dns.ip.type = IPADDR_TYPE_V4;
|
||||
dhcps_offer_t dhcps_dns_value = OFFER_DNS;
|
||||
ESP_ERROR_CHECK(esp_netif_dhcps_option(netif, ESP_NETIF_OP_SET, ESP_NETIF_DOMAIN_NAME_SERVER, &dhcps_dns_value, sizeof(dhcps_dns_value)));
|
||||
ESP_ERROR_CHECK(esp_netif_set_dns_info(netif, ESP_NETIF_DNS_MAIN, &dns));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
|
||||
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
|
||||
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_init_softap(void)
|
||||
{
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&wifi_event_handler,
|
||||
NULL,
|
||||
NULL));
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.ap = {
|
||||
.ssid = EXAMPLE_ESP_WIFI_SSID,
|
||||
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
|
||||
.channel = EXAMPLE_ESP_WIFI_CHANNEL,
|
||||
.password = EXAMPLE_ESP_WIFI_PASS,
|
||||
.max_connection = EXAMPLE_MAX_STA_CONN,
|
||||
.authmode = WIFI_AUTH_WPA_WPA2_PSK
|
||||
},
|
||||
};
|
||||
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
|
||||
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
|
||||
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);
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
//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());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
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();
|
||||
|
||||
|
||||
// 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));
|
||||
/* 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) {
|
||||
}
|
||||
} while ((bits&CONNECT_BIT) == 0);
|
||||
|
||||
/* Init the AP with NAT enabled */
|
||||
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
|
||||
assert(ap_netif);
|
||||
esp_netif_dns_info_t dns;
|
||||
ESP_ERROR_CHECK(esp_netif_get_dns_info(ppp_netif, ESP_NETIF_DNS_MAIN, &dns));
|
||||
set_dhcps_dns(ap_netif, dns.ip.u_addr.ip4.addr);
|
||||
|
||||
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
|
||||
ESP_ERROR_CHECK(esp_modem_stop_ppp(dte));
|
||||
ESP_ERROR_CHECK(esp_modem_start_ppp(dte));
|
||||
}
|
||||
|
||||
}
|
8
esp_modem/examples/ap_to_pppos/main/component.mk
Normal file
8
esp_modem/examples/ap_to_pppos/main/component.mk
Normal file
@ -0,0 +1,8 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
7
esp_modem/examples/ap_to_pppos/main/idf_component.yml
Normal file
7
esp_modem/examples/ap_to_pppos/main/idf_component.yml
Normal file
@ -0,0 +1,7 @@
|
||||
version: "0.0.2"
|
||||
targets:
|
||||
- esp32
|
||||
description: pppos_client to AP
|
||||
dependencies:
|
||||
espressif/esp_modem:
|
||||
version: "~0.0.2"
|
162
esp_modem/examples/ap_to_pppos/main/modem_board.c
Normal file
162
esp_modem/examples/ap_to_pppos/main/modem_board.c
Normal file
@ -0,0 +1,162 @@
|
||||
/* 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;
|
||||
}
|
12
esp_modem/examples/ap_to_pppos/sdkconfig.defaults
Normal file
12
esp_modem/examples/ap_to_pppos/sdkconfig.defaults
Normal file
@ -0,0 +1,12 @@
|
||||
# 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
|
||||
# Enable NAPT
|
||||
CONFIG_LWIP_IP_FORWARD=y
|
||||
CONFIG_LWIP_IPV4_NAPT=y
|
||||
|
8
esp_modem/examples/modem_console/CMakeLists.txt
Normal file
8
esp_modem/examples/modem_console/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(modem-console)
|
11
esp_modem/examples/modem_console/Makefile
Normal file
11
esp_modem/examples/modem_console/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := modem-console
|
||||
|
||||
EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
10
esp_modem/examples/modem_console/README.md
Normal file
10
esp_modem/examples/modem_console/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# PPPoS simple client example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## 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.
|
||||
|
||||
## How to use this example
|
||||
|
||||
See the README.md file in the upper level `pppos` directory for more information about the PPPoS examples.
|
4
esp_modem/examples/modem_console/main/CMakeLists.txt
Normal file
4
esp_modem/examples/modem_console/main/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "modem_console_main.c"
|
||||
"httpget_handle.c"
|
||||
"ping_handle.c"
|
||||
INCLUDE_DIRS ".")
|
4
esp_modem/examples/modem_console/main/component.mk
Normal file
4
esp_modem/examples/modem_console/main/component.mk
Normal file
@ -0,0 +1,4 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
108
esp_modem/examples/modem_console/main/httpget_handle.c
Normal file
108
esp_modem/examples/modem_console/main/httpget_handle.c
Normal file
@ -0,0 +1,108 @@
|
||||
/* Modem console example
|
||||
|
||||
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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_http_client.h"
|
||||
|
||||
static const char *TAG = "modem_console_httpget";
|
||||
|
||||
static esp_err_t http_event_handler(esp_http_client_event_t *evt)
|
||||
{
|
||||
switch(evt->event_id) {
|
||||
case HTTP_EVENT_ERROR:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
|
||||
break;
|
||||
case HTTP_EVENT_ON_CONNECTED:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
|
||||
break;
|
||||
case HTTP_EVENT_HEADER_SENT:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
|
||||
break;
|
||||
case HTTP_EVENT_ON_HEADER:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
|
||||
break;
|
||||
case HTTP_EVENT_ON_DATA:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
|
||||
if ((bool)evt->user_data &&
|
||||
!esp_http_client_is_chunked_response(evt->client)) {
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, evt->data, evt->data_len, ESP_LOG_INFO);
|
||||
}
|
||||
|
||||
break;
|
||||
case HTTP_EVENT_ON_FINISH:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
|
||||
break;
|
||||
case HTTP_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_str *host;
|
||||
struct arg_lit *hex;
|
||||
struct arg_end *end;
|
||||
} http_args;
|
||||
|
||||
static int do_http_client(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&http_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, http_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
esp_http_client_config_t config = {
|
||||
.event_handler = http_event_handler,
|
||||
};
|
||||
|
||||
if (http_args.host->count > 0) {
|
||||
config.url = http_args.host->sval[0];
|
||||
} else {
|
||||
config.url = "http://httpbin.org/get";
|
||||
}
|
||||
|
||||
if (http_args.hex->count > 0) {
|
||||
// show hex data from http-get
|
||||
config.user_data = (void*)true;
|
||||
}
|
||||
|
||||
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||
|
||||
esp_err_t err = esp_http_client_perform(client);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
|
||||
esp_http_client_get_status_code(client),
|
||||
esp_http_client_get_content_length(client));
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void modem_console_register_http(void)
|
||||
{
|
||||
http_args.host = arg_str0(NULL, NULL, "<host>", "address or host-name to send GET request (defaults to http://httpbin.org/get)");
|
||||
http_args.hex = arg_litn("p", "print-hex", 0, 1, "print hex output"),
|
||||
http_args.end = arg_end(1);
|
||||
const esp_console_cmd_t http_cmd = {
|
||||
.command = "httpget",
|
||||
.help = "http get command to test data mode",
|
||||
.hint = NULL,
|
||||
.func = &do_http_client,
|
||||
.argtable = &http_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&http_cmd));
|
||||
}
|
307
esp_modem/examples/modem_console/main/modem_console_main.c
Normal file
307
esp_modem/examples/modem_console/main/modem_console_main.c
Normal file
@ -0,0 +1,307 @@
|
||||
/* Modem console example
|
||||
|
||||
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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <esp_modem_dce_common_commands.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_event.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_modem.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
// utilities to check network connectivity
|
||||
void modem_console_register_http(void);
|
||||
void modem_console_register_ping(void);
|
||||
|
||||
static esp_modem_dce_t *s_dce = NULL;
|
||||
static const char *TAG = "modem_console";
|
||||
|
||||
static struct {
|
||||
struct arg_str *command;
|
||||
struct arg_int *param_int;
|
||||
struct arg_str *param_str;
|
||||
struct arg_str *param_pdp;
|
||||
struct arg_str *param_bool;
|
||||
struct arg_str *param;
|
||||
struct arg_str *result;
|
||||
struct arg_end *end;
|
||||
} at_args;
|
||||
|
||||
static struct {
|
||||
struct arg_str *param;
|
||||
struct arg_end *end;
|
||||
} modem_args;
|
||||
|
||||
|
||||
|
||||
static struct {
|
||||
struct arg_str *command;
|
||||
struct arg_int *timeout;
|
||||
struct arg_str *pattern;
|
||||
struct arg_lit *no_cr;
|
||||
struct arg_end *end;
|
||||
} generic_at_args;
|
||||
|
||||
static char s_common_in_str[100]; // used as common string input param holder
|
||||
static char s_common_out_str[100]; // used as output string/command result holder
|
||||
|
||||
static esp_err_t handle_line_pattern(esp_modem_dce_t *dce, const char *line)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
ESP_LOGI(TAG, "handle_line_pattern: DCE response: %s\n", line);
|
||||
if (strstr(line, dce->handle_line_ctx)) {
|
||||
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int do_dce(int argc, char **argv)
|
||||
{
|
||||
// specific DCE generic command params
|
||||
static bool bool_result;
|
||||
static char pdp_type[10];
|
||||
static char pdp_apn[10];
|
||||
static esp_modem_dce_pdp_ctx_t pdp = { .type = pdp_type, .apn = pdp_apn };
|
||||
static esp_modem_dce_csq_ctx_t csq;
|
||||
static esp_modem_dce_cbc_ctx_t cbc;
|
||||
|
||||
int nerrors = arg_parse(argc, argv, (void **) &at_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, at_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
void * command_param = NULL;
|
||||
void * command_result = NULL;
|
||||
|
||||
// parse input params
|
||||
if (at_args.param_int->count > 0) {
|
||||
command_param = (void*)(at_args.param_int->ival[0]);
|
||||
} else if (at_args.param_bool->count > 0) {
|
||||
const char * bool_in_str = at_args.param_bool->sval[0];
|
||||
s_common_out_str[0] = '\0';
|
||||
command_result = s_common_out_str;
|
||||
if (strstr(bool_in_str,"true") || strstr(bool_in_str,"1")) {
|
||||
command_param = (void*)true;
|
||||
} else {
|
||||
command_param = (void*)false;
|
||||
}
|
||||
} else if (at_args.param_pdp->count > 0) {
|
||||
// parse out three comma separated sub-arguments
|
||||
sscanf(at_args.param_pdp->sval[0], "%d,%s", &pdp.cid, pdp_type);
|
||||
char *str_apn = strchr(pdp_type, ',');
|
||||
if (str_apn) {
|
||||
strncpy(pdp_apn, str_apn + 1, sizeof(pdp_apn));
|
||||
str_apn[0] = '\0';
|
||||
}
|
||||
command_param = &pdp;
|
||||
} else if (at_args.param_str->count > 0) {
|
||||
strncpy(s_common_in_str, at_args.param_str->sval[0], sizeof(s_common_in_str));
|
||||
command_param = s_common_in_str;
|
||||
} else if (at_args.param->count > 0) { // default param is treated as string
|
||||
strncpy(s_common_in_str, at_args.param->sval[0], sizeof(s_common_in_str));
|
||||
command_param = s_common_in_str;
|
||||
}
|
||||
|
||||
// parse output params
|
||||
if (at_args.result->count > 0) {
|
||||
const char *res = at_args.result->sval[0];
|
||||
if (strstr(res, "csq")) {
|
||||
command_result = &csq;
|
||||
}else if (strstr(res, "cbc")) {
|
||||
command_result = &cbc;
|
||||
} else if (strstr(res, "str")) {
|
||||
command_param = (void*)sizeof(s_common_out_str);
|
||||
command_result = s_common_out_str;
|
||||
} else if (strstr(res, "bool")) {
|
||||
command_result = &bool_result;
|
||||
} else {
|
||||
command_param = (void*)sizeof(s_common_out_str);
|
||||
command_result = s_common_out_str;
|
||||
}
|
||||
}
|
||||
|
||||
// by default (if no param/result provided) expect string output
|
||||
if (command_param == NULL && command_result == NULL) {
|
||||
s_common_out_str[0] = '\0';
|
||||
command_param = (void*)sizeof(s_common_out_str);
|
||||
command_result = s_common_out_str;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_modem_command_list_run(s_dce, at_args.command->sval[0], command_param, command_result);
|
||||
if (err == ESP_OK) {
|
||||
printf("Command %s succeeded\n", at_args.command->sval[0]);
|
||||
if (command_result == s_common_out_str && s_common_out_str[0] != '\0') {
|
||||
ESP_LOGI(TAG, "Command string output: %s", s_common_out_str);
|
||||
} else if (command_result == &csq) {
|
||||
ESP_LOGI(TAG, "Command CSQ output: rssi:%d, ber:%d", csq.rssi, csq.ber);
|
||||
} else if (command_result == &cbc) {
|
||||
ESP_LOGI(TAG, "Command battery output:%d mV", cbc.battery_status);
|
||||
} else if (command_result == &bool_result) {
|
||||
ESP_LOGI(TAG, "Command bool output: %s", bool_result ? "true" : "false");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGE(TAG, "Command %s failed with %d", at_args.command->sval[0], err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int do_at_command(int argc, char **argv)
|
||||
{
|
||||
int timeout = 1000;
|
||||
int nerrors = arg_parse(argc, argv, (void **)&generic_at_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, generic_at_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
esp_modem_dce_handle_line_t handle_line = esp_modem_dce_handle_response_default;
|
||||
|
||||
strncpy(s_common_in_str, generic_at_args.command->sval[0], sizeof(s_common_in_str) - 2);
|
||||
if (generic_at_args.no_cr->count == 0) {
|
||||
size_t cmd_len = strlen(generic_at_args.command->sval[0]);
|
||||
s_common_in_str[cmd_len] = '\r';
|
||||
s_common_in_str[cmd_len + 1] = '\0';
|
||||
}
|
||||
|
||||
if (generic_at_args.timeout->count > 0) {
|
||||
timeout = generic_at_args.timeout->ival[0];
|
||||
}
|
||||
|
||||
if (generic_at_args.pattern->count > 0) {
|
||||
strncpy(s_common_out_str, generic_at_args.pattern->sval[0], sizeof(s_common_out_str));
|
||||
handle_line = handle_line_pattern;
|
||||
}
|
||||
|
||||
if (esp_modem_dce_generic_command(s_dce, s_common_in_str, timeout, handle_line, s_common_out_str) == ESP_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int do_modem_lifecycle(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&modem_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, modem_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (modem_args.param->count > 0) {
|
||||
esp_err_t err = ESP_FAIL;
|
||||
if (strstr(modem_args.param->sval[0], "PPP")) {
|
||||
err = esp_modem_start_ppp(s_dce->dte);
|
||||
} else if (strstr(modem_args.param->sval[0], "CMD")) {
|
||||
err = esp_modem_stop_ppp(s_dce->dte);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG, "set_working_mode %s succeeded", at_args.param->sval[0]);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "set_working_mode %s failed with %d", at_args.param->sval[0], err);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void register_dce(void)
|
||||
{
|
||||
at_args.command = arg_str1(NULL, NULL, "<command>", "Symbolic name of DCE command");
|
||||
at_args.param_int = arg_int0("i", "int", "<num>", "Input parameter of integer type");
|
||||
at_args.param_str = arg_str0("s", "str", "<str>", "Input parameter of string type");
|
||||
at_args.param_pdp = arg_str0("p", "pdp", "<pdp>", "Comma separated string with PDP context");
|
||||
at_args.param_bool = arg_str0("b", "bool", "<true/false>", "Input parameter of bool type");
|
||||
at_args.param = arg_str0(NULL, NULL, "<param>", "Default input argument treated as string");
|
||||
at_args.result = arg_str0("o", "out", "<type>", "Type of output parameter");
|
||||
at_args.end = arg_end(1);
|
||||
const esp_console_cmd_t at_cmd = {
|
||||
.command = "dce",
|
||||
.help = "send symbolic command to the modem",
|
||||
.hint = NULL,
|
||||
.func = &do_dce,
|
||||
.argtable = &at_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&at_cmd));
|
||||
}
|
||||
static void register_at_command(void)
|
||||
{
|
||||
generic_at_args.command = arg_str1(NULL, NULL, "<command>", "AT command to send to the modem");
|
||||
generic_at_args.timeout = arg_int0("t", "timeout", "<timeout>", "command timeout");
|
||||
generic_at_args.pattern = arg_str0("p", "pattern", "<pattern>", "command response to wait for");
|
||||
generic_at_args.no_cr = arg_litn("n", "no-cr", 0, 1, "not add trailing CR to the command");
|
||||
generic_at_args.end = arg_end(1);
|
||||
|
||||
const esp_console_cmd_t at_command = {
|
||||
.command = "at",
|
||||
.help = "send generic AT command to the modem",
|
||||
.hint = NULL,
|
||||
.func = &do_at_command,
|
||||
.argtable = &generic_at_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&at_command));
|
||||
}
|
||||
|
||||
static void register_modem_lifecycle(void)
|
||||
{
|
||||
modem_args.param = arg_str1(NULL, NULL, "<mode>", "PPP or CMD");
|
||||
modem_args.end = arg_end(1);
|
||||
const esp_console_cmd_t modem_cmd = {
|
||||
.command = "modem",
|
||||
.help = "set modem mode",
|
||||
.hint = NULL,
|
||||
.func = &do_modem_lifecycle,
|
||||
.argtable = &modem_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&modem_cmd));
|
||||
}
|
||||
|
||||
static esp_console_repl_t *s_repl = NULL;
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// init the DTE
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
dte_config.event_task_stack_size = 4096;
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet");
|
||||
dce_config.populate_command_list = true;
|
||||
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
|
||||
|
||||
esp_modem_dte_t *dte = esp_modem_dte_new(&dte_config);
|
||||
s_dce = esp_modem_dce_new(&dce_config);
|
||||
assert(s_dce != NULL);
|
||||
|
||||
esp_netif_t *esp_netif = esp_netif_new(&ppp_netif_config);
|
||||
assert(esp_netif);
|
||||
|
||||
ESP_ERROR_CHECK(esp_modem_default_attach(dte, s_dce, esp_netif));
|
||||
|
||||
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();
|
||||
// init console REPL environment
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl));
|
||||
|
||||
register_dce();
|
||||
register_at_command();
|
||||
register_modem_lifecycle();
|
||||
modem_console_register_http();
|
||||
modem_console_register_ping();
|
||||
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(s_repl));
|
||||
}
|
141
esp_modem/examples/modem_console/main/ping_handle.c
Normal file
141
esp_modem/examples/modem_console/main/ping_handle.c
Normal file
@ -0,0 +1,141 @@
|
||||
/* Ping handle example
|
||||
|
||||
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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_log.h"
|
||||
#include "ping/ping_sock.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
static const char *TAG = "modem_console_ping";
|
||||
|
||||
static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint8_t ttl;
|
||||
uint16_t seqno;
|
||||
uint32_t elapsed_time, recv_len;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
|
||||
ESP_LOGI(TAG, "%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n",
|
||||
recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time);
|
||||
}
|
||||
|
||||
static void cmd_ping_on_ping_timeout(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint16_t seqno;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
ESP_LOGE(TAG, "From %s icmp_seq=%d timeout\n", inet_ntoa(target_addr.u_addr.ip4), seqno);
|
||||
}
|
||||
|
||||
static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
ip_addr_t target_addr;
|
||||
uint32_t transmitted;
|
||||
uint32_t received;
|
||||
uint32_t total_time_ms;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
|
||||
uint32_t loss = (uint32_t)((1 - ((float)received) / transmitted) * 100);
|
||||
if (IP_IS_V4(&target_addr)) {
|
||||
ESP_LOGI(TAG, "\n--- %s ping statistics ---\n", inet_ntoa(*ip_2_ip4(&target_addr)));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "\n--- %s ping statistics ---\n", inet6_ntoa(*ip_2_ip6(&target_addr)));
|
||||
}
|
||||
ESP_LOGI(TAG, "%d packets transmitted, %d received, %d%% packet loss, time %dms\n",
|
||||
transmitted, received, loss, total_time_ms);
|
||||
// delete the ping sessions, so that we clean up all resources and can create a new ping session
|
||||
// we don't have to call delete function in the callback, instead we can call delete function from other tasks
|
||||
esp_ping_delete_session(hdl);
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_dbl *timeout;
|
||||
struct arg_int *count;
|
||||
struct arg_str *host;
|
||||
struct arg_end *end;
|
||||
} ping_args;
|
||||
|
||||
static int do_ping_cmd(int argc, char **argv)
|
||||
{
|
||||
esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG();
|
||||
|
||||
int nerrors = arg_parse(argc, argv, (void **)&ping_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, ping_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ping_args.timeout->count > 0) {
|
||||
config.timeout_ms = (uint32_t)(ping_args.timeout->dval[0] * 1000);
|
||||
}
|
||||
|
||||
if (ping_args.count->count > 0) {
|
||||
config.count = (uint32_t)(ping_args.count->ival[0]);
|
||||
}
|
||||
|
||||
// parse IP address
|
||||
ip_addr_t target_addr;
|
||||
struct addrinfo hint;
|
||||
struct addrinfo *res = NULL;
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
memset(&target_addr, 0, sizeof(target_addr));
|
||||
/* convert domain name to IP address */
|
||||
if (getaddrinfo(ping_args.host->sval[0], NULL, &hint, &res) != 0) {
|
||||
printf("ping: unknown host %s\n", ping_args.host->sval[0]);
|
||||
return 1;
|
||||
}
|
||||
if (res->ai_family == AF_INET) {
|
||||
struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr;
|
||||
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
|
||||
} else {
|
||||
struct in6_addr addr6 = ((struct sockaddr_in6 *) (res->ai_addr))->sin6_addr;
|
||||
inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6);
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
config.target_addr = target_addr;
|
||||
|
||||
/* set callback functions */
|
||||
esp_ping_callbacks_t cbs = {
|
||||
.on_ping_success = cmd_ping_on_ping_success,
|
||||
.on_ping_timeout = cmd_ping_on_ping_timeout,
|
||||
.on_ping_end = cmd_ping_on_ping_end,
|
||||
.cb_args = NULL
|
||||
};
|
||||
esp_ping_handle_t ping;
|
||||
esp_ping_new_session(&config, &cbs, &ping);
|
||||
esp_ping_start(ping);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void modem_console_register_ping(void)
|
||||
{
|
||||
ping_args.timeout = arg_dbl0("W", "timeout", "<t>", "Time to wait for a response, in seconds");
|
||||
ping_args.count = arg_int0("c", "count", "<n>", "Stop after sending count packets");
|
||||
ping_args.host = arg_str1(NULL, NULL, "<host>", "Host address");
|
||||
ping_args.end = arg_end(1);
|
||||
const esp_console_cmd_t ping_cmd = {
|
||||
.command = "ping",
|
||||
.help = "send ICMP ECHO_REQUEST to network hosts",
|
||||
.hint = NULL,
|
||||
.func = &do_ping_cmd,
|
||||
.argtable = &ping_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&ping_cmd));
|
||||
}
|
8
esp_modem/examples/modem_console/sdkconfig.defaults
Normal file
8
esp_modem/examples/modem_console/sdkconfig.defaults
Normal file
@ -0,0 +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
|
10
esp_modem/examples/pppos_client/CMakeLists.txt
Normal file
10
esp_modem/examples/pppos_client/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(pppos_client)
|
||||
|
||||
|
9
esp_modem/examples/pppos_client/Makefile
Normal file
9
esp_modem/examples/pppos_client/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# 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
|
||||
|
10
esp_modem/examples/pppos_client/README.md
Normal file
10
esp_modem/examples/pppos_client/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# PPPoS simple client example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## Overview
|
||||
This example shows how to act as a MQTT client after the PPPoS channel created by using [ESP-MQTT](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/protocols/mqtt.html) APIs.
|
||||
|
||||
## How to use this example
|
||||
|
||||
See the README.md file in the upper level `pppos` directory for more information about the PPPoS examples.
|
2
esp_modem/examples/pppos_client/main/CMakeLists.txt
Normal file
2
esp_modem/examples/pppos_client/main/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "pppos_client_main.c"
|
||||
INCLUDE_DIRS ".")
|
143
esp_modem/examples/pppos_client/main/Kconfig.projbuild
Normal file
143
esp_modem/examples/pppos_client/main/Kconfig.projbuild
Normal file
@ -0,0 +1,143 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
choice EXAMPLE_MODEM_DEVICE
|
||||
prompt "Choose supported modem device (DCE)"
|
||||
default EXAMPLE_MODEM_DEVICE_BG96
|
||||
help
|
||||
Select modem device connected to the ESP DTE.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM800
|
||||
bool "SIM800"
|
||||
help
|
||||
SIMCom SIM800L is a GSM/GPRS module.
|
||||
It supports Quad-band 850/900/1800/1900MHz.
|
||||
config EXAMPLE_MODEM_DEVICE_BG96
|
||||
bool "BG96"
|
||||
help
|
||||
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7600
|
||||
bool "SIM7600"
|
||||
help
|
||||
SIM7600 is Multi-Band LTE-TDD/LTE-FDD/HSPA+ and GSM/GPRS/EDGE module
|
||||
endchoice
|
||||
|
||||
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_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
|
||||
string "Set username for authentication"
|
||||
default "espressif"
|
||||
depends on !EXAMPLE_MODEM_PPP_AUTH_NONE
|
||||
help
|
||||
Set username for PPP Authentication.
|
||||
|
||||
config EXAMPLE_MODEM_PPP_AUTH_PASSWORD
|
||||
string "Set password for authentication"
|
||||
default "esp32"
|
||||
depends on !EXAMPLE_MODEM_PPP_AUTH_NONE
|
||||
help
|
||||
Set password for PPP Authentication.
|
||||
|
||||
config EXAMPLE_MODEM_PPP_AUTH_NONE
|
||||
bool "Skip PPP authentication"
|
||||
default n
|
||||
help
|
||||
Set to true for the PPP client to skip authentication
|
||||
|
||||
config EXAMPLE_SEND_MSG
|
||||
bool "Short message (SMS)"
|
||||
default n
|
||||
help
|
||||
Select this, the modem will send a short message before power off.
|
||||
|
||||
if EXAMPLE_SEND_MSG
|
||||
config EXAMPLE_SEND_MSG_PEER_PHONE_NUMBER
|
||||
string "Peer Phone Number (with area code)"
|
||||
default "+8610086"
|
||||
help
|
||||
Enter the peer phone number that you want to send message to.
|
||||
endif
|
||||
|
||||
menu "UART Configuration"
|
||||
config EXAMPLE_MODEM_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 25
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 26
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RTS_PIN
|
||||
int "RTS Pin Number"
|
||||
default 27
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RTS.
|
||||
|
||||
config EXAMPLE_MODEM_UART_CTS_PIN
|
||||
int "CTS Pin Number"
|
||||
default 23
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART CTS.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE
|
||||
int "UART Event Task Stack Size"
|
||||
range 2000 6000
|
||||
default 2048
|
||||
help
|
||||
Stack size of UART event task.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY
|
||||
int "UART Event Task Priority"
|
||||
range 3 22
|
||||
default 5
|
||||
help
|
||||
Priority of UART event task.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE
|
||||
int "UART Event Queue Size"
|
||||
range 10 40
|
||||
default 30
|
||||
help
|
||||
Length of UART event queue.
|
||||
|
||||
config EXAMPLE_MODEM_UART_PATTERN_QUEUE_SIZE
|
||||
int "UART Pattern Queue Size"
|
||||
range 10 40
|
||||
default 20
|
||||
help
|
||||
Length of UART pattern queue.
|
||||
|
||||
config EXAMPLE_MODEM_UART_TX_BUFFER_SIZE
|
||||
int "UART TX Buffer Size"
|
||||
range 256 2048
|
||||
default 512
|
||||
help
|
||||
Buffer size of UART TX buffer.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_BUFFER_SIZE
|
||||
int "UART RX Buffer Size"
|
||||
range 256 2048
|
||||
default 1024
|
||||
help
|
||||
Buffer size of UART RX buffer.
|
||||
endmenu
|
||||
|
||||
endmenu
|
4
esp_modem/examples/pppos_client/main/component.mk
Normal file
4
esp_modem/examples/pppos_client/main/component.mk
Normal file
@ -0,0 +1,4 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
422
esp_modem/examples/pppos_client/main/pppos_client_main.c
Normal file
422
esp_modem/examples/pppos_client/main/pppos_client_main.c
Normal file
@ -0,0 +1,422 @@
|
||||
/* PPPoS Client Example
|
||||
|
||||
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 "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_netif_ppp.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "esp_modem.h"
|
||||
#include "esp_modem_netif.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#if defined(CONFIG_EXAMPLE_MODEM_LEGACY_API)
|
||||
#include "sim800.h"
|
||||
#include "bg96.h"
|
||||
#include "sim7600.h"
|
||||
#endif
|
||||
|
||||
#define BROKER_URL "mqtt://mqtt.eclipse.org"
|
||||
|
||||
static const char *TAG = "pppos_example";
|
||||
static EventGroupHandle_t event_group = NULL;
|
||||
static const int CONNECT_BIT = BIT0;
|
||||
static const int STOP_BIT = BIT1;
|
||||
static const int GOT_DATA_BIT = BIT2;
|
||||
|
||||
#if CONFIG_EXAMPLE_SEND_MSG
|
||||
/**
|
||||
* @brief This example will also show how to send short message using the infrastructure provided by esp modem library.
|
||||
* @note Not all modem support SMG.
|
||||
*
|
||||
*/
|
||||
static esp_err_t example_default_handle(esp_modem_dce_t *dce, const char *line)
|
||||
{
|
||||
esp_err_t err = ESP_FAIL;
|
||||
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
|
||||
err = esp_modem_process_command_done(dce, MODEM_STATE_SUCCESS);
|
||||
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
|
||||
err = esp_modem_process_command_done(dce, MODEM_STATE_FAIL);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t example_handle_cmgs(esp_modem_dce_t *dce, const char *line)
|
||||
{
|
||||
esp_err_t err = ESP_FAIL;
|
||||
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
|
||||
err = esp_modem_process_command_done(dce, MODEM_STATE_SUCCESS);
|
||||
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
|
||||
err = esp_modem_process_command_done(dce, MODEM_STATE_FAIL);
|
||||
} else if (!strncmp(line, "+CMGS", strlen("+CMGS"))) {
|
||||
err = ESP_OK;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#define MODEM_SMS_MAX_LENGTH (128)
|
||||
#define MODEM_COMMAND_TIMEOUT_SMS_MS (120000)
|
||||
#define MODEM_PROMPT_TIMEOUT_MS (10)
|
||||
|
||||
static esp_err_t example_send_message_text(modem_dce_t *user_dce, const char *phone_num, const char *text)
|
||||
{
|
||||
esp_modem_dce_t *dce = &user_dce->parent;
|
||||
modem_dte_t *dte = dce->dte;
|
||||
dce->handle_line = example_default_handle;
|
||||
/* Set text mode */
|
||||
if (dte->send_cmd(dte, "AT+CMGF=1\r", MODEM_COMMAND_TIMEOUT_DEFAULT) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "send command failed");
|
||||
goto err;
|
||||
}
|
||||
if (dce->state != MODEM_STATE_SUCCESS) {
|
||||
ESP_LOGE(TAG, "set message format failed");
|
||||
goto err;
|
||||
}
|
||||
ESP_LOGD(TAG, "set message format ok");
|
||||
/* Specify character set */
|
||||
dce->handle_line = example_default_handle;
|
||||
if (dte->send_cmd(dte, "AT+CSCS=\"GSM\"\r", MODEM_COMMAND_TIMEOUT_DEFAULT) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "send command failed");
|
||||
goto err;
|
||||
}
|
||||
if (dce->state != MODEM_STATE_SUCCESS) {
|
||||
ESP_LOGE(TAG, "set character set failed");
|
||||
goto err;
|
||||
}
|
||||
ESP_LOGD(TAG, "set character set ok");
|
||||
/* send message */
|
||||
char command[MODEM_SMS_MAX_LENGTH] = {0};
|
||||
int length = snprintf(command, MODEM_SMS_MAX_LENGTH, "AT+CMGS=\"%s\"\r", phone_num);
|
||||
/* set phone number and wait for "> " */
|
||||
dte->send_wait(dte, command, length, "\r\n> ", MODEM_PROMPT_TIMEOUT_MS);
|
||||
/* end with CTRL+Z */
|
||||
snprintf(command, MODEM_SMS_MAX_LENGTH, "%s\x1A", text);
|
||||
dce->handle_line = example_handle_cmgs;
|
||||
if (dte->send_cmd(dte, command, MODEM_COMMAND_TIMEOUT_SMS_MS) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "send command failed");
|
||||
goto err;
|
||||
}
|
||||
if (dce->state != MODEM_STATE_SUCCESS) {
|
||||
ESP_LOGE(TAG, "send message failed");
|
||||
goto err;
|
||||
}
|
||||
ESP_LOGD(TAG, "send message ok");
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void modem_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
switch (event_id) {
|
||||
case ESP_MODEM_EVENT_PPP_START:
|
||||
ESP_LOGI(TAG, "Modem PPP Started");
|
||||
break;
|
||||
case ESP_MODEM_EVENT_PPP_STOP:
|
||||
ESP_LOGI(TAG, "Modem PPP Stopped");
|
||||
xEventGroupSetBits(event_group, STOP_BIT);
|
||||
break;
|
||||
case ESP_MODEM_EVENT_UNKNOWN:
|
||||
ESP_LOGW(TAG, "Unknow line received: %s", (char *)event_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
|
||||
{
|
||||
esp_mqtt_client_handle_t client = event->client;
|
||||
int msg_id;
|
||||
switch (event->event_id) {
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
|
||||
msg_id = esp_mqtt_client_subscribe(client, "/topic/esp-pppos", 0);
|
||||
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
|
||||
break;
|
||||
case MQTT_EVENT_SUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
msg_id = esp_mqtt_client_publish(client, "/topic/esp-pppos", "esp32-pppos", 0, 0, 0);
|
||||
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_UNSUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_PUBLISHED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
|
||||
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
||||
printf("DATA=%.*s\r\n", event->data_len, event->data);
|
||||
xEventGroupSetBits(event_group, GOT_DATA_BIT);
|
||||
break;
|
||||
case MQTT_EVENT_ERROR:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "MQTT other event id: %d", event->event_id);
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
ESP_LOGI(TAG, "PPP state changed event %d", event_id);
|
||||
if (event_id == NETIF_PPP_ERRORUSER) {
|
||||
/* User interrupted event from esp-netif */
|
||||
esp_netif_t *netif = event_data;
|
||||
ESP_LOGI(TAG, "User interrupted event from netif:%p", netif);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_ip_event(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
ESP_LOGD(TAG, "IP event! %d", event_id);
|
||||
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;
|
||||
|
||||
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
||||
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
||||
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
||||
esp_netif_get_dns_info(netif, 0, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
esp_netif_get_dns_info(netif, 1, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||
|
||||
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||
ESP_LOGI(TAG, "GOT IPv6 event!");
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void modem_test_app(esp_modem_dte_config_t *dte_config, esp_modem_dce_config_t *dce_config, esp_netif_config_t *ppp_config);
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
|
||||
/* Init and register system/core components */
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, NULL));
|
||||
|
||||
event_group = xEventGroupCreate();
|
||||
|
||||
/* Configure the DTE */
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
/* setup UART specific configuration based on kconfig options */
|
||||
dte_config.tx_io_num = CONFIG_EXAMPLE_MODEM_UART_TX_PIN;
|
||||
dte_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
|
||||
dte_config.rts_io_num = CONFIG_EXAMPLE_MODEM_UART_RTS_PIN;
|
||||
dte_config.cts_io_num = CONFIG_EXAMPLE_MODEM_UART_CTS_PIN;
|
||||
dte_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
|
||||
dte_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
|
||||
dte_config.pattern_queue_size = CONFIG_EXAMPLE_MODEM_UART_PATTERN_QUEUE_SIZE;
|
||||
dte_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
|
||||
dte_config.event_task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE;
|
||||
dte_config.event_task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY;
|
||||
dte_config.line_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2;
|
||||
|
||||
/* Configure the DCE */
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
|
||||
|
||||
/* Configure the PPP netif */
|
||||
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
||||
|
||||
/* Run the modem demo app */
|
||||
return modem_test_app(&dte_config, &dce_config,&netif_ppp_config);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_EXAMPLE_MODEM_LEGACY_API)
|
||||
static void modem_test_app(esp_modem_dte_config_t *dte_config, esp_modem_dce_config_t *dce_config, esp_netif_config_t *ppp_config)
|
||||
{
|
||||
/* create dte object */
|
||||
esp_modem_dte_t *dte = esp_modem_dte_new(dte_config);
|
||||
assert(dte != NULL);
|
||||
|
||||
/* create dce object */
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_SIM800
|
||||
dce_config->device = ESP_MODEM_DEVICE_SIM800;
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_BG96
|
||||
dce_config->device = ESP_MODEM_DEVICE_BG96;
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600
|
||||
dce_config->device = ESP_MODEM_DEVICE_SIM7600;
|
||||
#else
|
||||
#error "Unsupported DCE"
|
||||
#endif
|
||||
esp_modem_dce_t *dce = esp_modem_dce_new(dce_config);
|
||||
assert(dce != NULL);
|
||||
|
||||
/* create netif object */
|
||||
esp_netif_t *esp_netif = esp_netif_new(ppp_config);
|
||||
assert(esp_netif);
|
||||
#if !defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_NONE) && (defined(CONFIG_LWIP_PPP_PAP_SUPPORT) || defined(CONFIG_LWIP_PPP_CHAP_SUPPORT))
|
||||
#if CONFIG_LWIP_PPP_PAP_SUPPORT
|
||||
esp_netif_auth_type_t auth_type = NETIF_PPP_AUTHTYPE_PAP;
|
||||
#elif CONFIG_LWIP_PPP_CHAP_SUPPORT
|
||||
esp_netif_auth_type_t auth_type = NETIF_PPP_AUTHTYPE_CHAP;
|
||||
#else
|
||||
#error "Unsupported AUTH Negotiation"
|
||||
#endif
|
||||
esp_netif_ppp_set_auth(esp_netif, auth_type, CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME, CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD);
|
||||
#endif
|
||||
/* Register event handler */
|
||||
ESP_ERROR_CHECK(esp_modem_set_event_handler(dte, modem_event_handler, ESP_EVENT_ANY_ID, NULL));
|
||||
|
||||
/* attach the DCE, DTE, netif to initialize the modem */
|
||||
ESP_ERROR_CHECK(esp_modem_default_attach(dte, dce, esp_netif));
|
||||
|
||||
while (1) {
|
||||
ESP_ERROR_CHECK(esp_modem_default_start(dte));
|
||||
/* Start PPP mode */
|
||||
ESP_ERROR_CHECK(esp_modem_start_ppp(dte));
|
||||
/* Wait for IP address */
|
||||
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
|
||||
/* Config MQTT */
|
||||
esp_mqtt_client_config_t mqtt_config = {
|
||||
.uri = BROKER_URL,
|
||||
.event_handle = mqtt_event_handler,
|
||||
};
|
||||
esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config);
|
||||
esp_mqtt_client_start(mqtt_client);
|
||||
xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
esp_mqtt_client_destroy(mqtt_client);
|
||||
|
||||
/* Exit PPP mode */
|
||||
ESP_ERROR_CHECK(esp_modem_stop_ppp(dte));
|
||||
|
||||
xEventGroupWaitBits(event_group, STOP_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
ESP_LOGI(TAG, "Restart after 60 seconds");
|
||||
vTaskDelay(pdMS_TO_TICKS(60000));
|
||||
}
|
||||
|
||||
/* Default destroy all modem sub-units attached to it (DTE, DCE, netif) */
|
||||
ESP_ERROR_CHECK(esp_modem_default_destroy(dte));
|
||||
}
|
||||
#else // defined(CONFIG_EXAMPLE_MODEM_LEGACY_API)
|
||||
|
||||
static void modem_test_app(esp_modem_dte_config_t *dte_config, esp_modem_dce_config_t *dce_config, esp_netif_config_t *ppp_config)
|
||||
{
|
||||
/* create dte object */
|
||||
modem_dte_t *dte = esp_modem_dte_init(dte_config);
|
||||
/* Register event handler */
|
||||
ESP_ERROR_CHECK(esp_modem_set_event_handler(dte, modem_event_handler, ESP_EVENT_ANY_ID, NULL));
|
||||
|
||||
// Init netif object
|
||||
esp_netif_t *esp_netif = esp_netif_new(ppp_config);
|
||||
assert(esp_netif);
|
||||
|
||||
void *modem_netif_adapter = esp_modem_netif_setup(dte);
|
||||
esp_modem_netif_set_default_handlers(modem_netif_adapter, esp_netif);
|
||||
|
||||
while (1) {
|
||||
modem_dce_t *dce = NULL;
|
||||
/* create dce object */
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_SIM800
|
||||
dce = sim800_init(dte);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_BG96
|
||||
dce = bg96_init(dte);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600
|
||||
dce = sim7600_init(dte);
|
||||
#else
|
||||
#error "Unsupported DCE"
|
||||
#endif
|
||||
assert(dce != NULL);
|
||||
ESP_ERROR_CHECK(dce->set_flow_ctrl(dce, ESP_MODEM_FLOW_CONTROL_NONE));
|
||||
ESP_ERROR_CHECK(dce->store_profile(dce));
|
||||
/* Print Module ID, Operator, IMEI, IMSI */
|
||||
ESP_LOGI(TAG, "Module: %s", dce->name);
|
||||
ESP_LOGI(TAG, "Operator: %s", dce->oper);
|
||||
ESP_LOGI(TAG, "IMEI: %s", dce->imei);
|
||||
ESP_LOGI(TAG, "IMSI: %s", dce->imsi);
|
||||
|
||||
/* Get signal quality */
|
||||
uint32_t rssi = 0, ber = 0;
|
||||
ESP_ERROR_CHECK(dce->get_signal_quality(dce, &rssi, &ber));
|
||||
ESP_LOGI(TAG, "rssi: %d, ber: %d", rssi, ber);
|
||||
/* Get battery voltage */
|
||||
uint32_t voltage = 0, bcs = 0, bcl = 0;
|
||||
ESP_ERROR_CHECK(dce->get_battery_status(dce, &bcs, &bcl, &voltage));
|
||||
ESP_LOGI(TAG, "Battery voltage: %d mV", voltage);
|
||||
/* setup PPPoS network parameters */
|
||||
#if !defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_NONE) && (defined(CONFIG_LWIP_PPP_PAP_SUPPORT) || defined(CONFIG_LWIP_PPP_CHAP_SUPPORT))
|
||||
#if CONFIG_LWIP_PPP_PAP_SUPPORT
|
||||
esp_netif_auth_type_t auth_type = NETIF_PPP_AUTHTYPE_PAP;
|
||||
#elif CONFIG_LWIP_PPP_CHAP_SUPPORT
|
||||
esp_netif_auth_type_t auth_type = NETIF_PPP_AUTHTYPE_CHAP;
|
||||
#else
|
||||
#error "Unsupported AUTH Negotiation"
|
||||
#endif
|
||||
esp_netif_ppp_set_auth(esp_netif, auth_type, CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME, CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD);
|
||||
#endif
|
||||
/* attach the modem to the network interface */
|
||||
esp_netif_attach(esp_netif, modem_netif_adapter);
|
||||
/* Wait for IP address */
|
||||
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
|
||||
/* Config MQTT */
|
||||
esp_mqtt_client_config_t mqtt_config = {
|
||||
.uri = BROKER_URL,
|
||||
.event_handle = mqtt_event_handler,
|
||||
};
|
||||
esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config);
|
||||
esp_mqtt_client_start(mqtt_client);
|
||||
xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
esp_mqtt_client_destroy(mqtt_client);
|
||||
|
||||
/* Exit PPP mode */
|
||||
ESP_ERROR_CHECK(esp_modem_stop_ppp(dte));
|
||||
|
||||
xEventGroupWaitBits(event_group, STOP_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
#if CONFIG_EXAMPLE_SEND_MSG
|
||||
const char *message = "Welcome to ESP32!";
|
||||
ESP_ERROR_CHECK(example_send_message_text(dce, CONFIG_EXAMPLE_SEND_MSG_PEER_PHONE_NUMBER, message));
|
||||
ESP_LOGI(TAG, "Send send message [%s] ok", message);
|
||||
#endif
|
||||
/* Power down module */
|
||||
ESP_ERROR_CHECK(dce->power_down(dce));
|
||||
ESP_LOGI(TAG, "Power down");
|
||||
ESP_ERROR_CHECK(dce->deinit(dce));
|
||||
|
||||
ESP_LOGI(TAG, "Restart after 60 seconds");
|
||||
vTaskDelay(pdMS_TO_TICKS(60000));
|
||||
}
|
||||
|
||||
/* Unregister events, destroy the netif adapter and destroy its esp-netif instance */
|
||||
esp_modem_netif_clear_default_handlers(modem_netif_adapter);
|
||||
esp_modem_netif_teardown(modem_netif_adapter);
|
||||
esp_netif_destroy(esp_netif);
|
||||
|
||||
ESP_ERROR_CHECK(dte->deinit(dte));
|
||||
}
|
||||
|
||||
#endif // CONFIG_EXAMPLE_MODEM_LEGACY_API
|
7
esp_modem/examples/pppos_client/sdkconfig.defaults
Normal file
7
esp_modem/examples/pppos_client/sdkconfig.defaults
Normal file
@ -0,0 +1,7 @@
|
||||
# Override some defaults to enable PPP
|
||||
CONFIG_LWIP_PPP_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_NOTIFY_PHASE_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
|
Reference in New Issue
Block a user