Examples: Remove pppos_client example

This commit is contained in:
David Cermak 2021-12-03 08:47:30 +01:00
parent 15fec25dff
commit 5a41e6afa9
26 changed files with 0 additions and 3251 deletions

View File

@ -1,6 +0,0 @@
# 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)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(pppos_client)

View File

@ -1,133 +0,0 @@
# PPP over Serial (PPPoS) client example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
**Note:** This example uses an internal implementation of the [modem component](components/modem) that will not be maintained in `v5.0` and this example will be migrated to [esp-modem component](https://components.espressif.com/component/espressif/esp_modem).
## Overview
A general PPP application consists of two parts: PPP server which is provided by cellular modem module and PPP client which is provided by ESP32 in this example.
Standard operating systems like Windows and Unix integrate a full PPP stack and provide a way to setup PPP connection at the same time. But how can we get access to Internet by PPP protocol in a resource constrained system? Fortunately, the PPP protocol has already been implemented in lwIP, but it doesn't supply a common way to setup a PPP connection.
This example introduces a library focusing on sending and parsing AT commands, and also provides useful functions to set up PPP connection.
When PPP connection has been established, the IP packet flow from application side will be transmitted to Internet by cellular module. 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 example
### Hardware Required
To run this example, you need an ESP32 dev board (e.g. ESP32-WROVER Kit) or ESP32 core board (e.g. ESP32-DevKitC).
For test purpose, you also need a cellular modem module. Here we take the [SIM800L](https://www.simcom.com/product/SIM800.html) and [BG96](https://www.quectel.com/product/lpwa-bg96-cat-m1-nb1-egprs/) as an example.
You can also try other modules as long as they embedded PPP protocol.
**Note:** Since SIM800L only support **2G** which will **not** work in some countries. And also keep in mind that in some other countries it will stop working soon (many remaining 2G networks will be switched off in the next 2-3 years). So you should **check with your local providers for further details** if you try this example with any 2G modules.
#### Pin Assignment
**Note:** The following pin assignments are used by default which can be changed in menuconfig.
| ESP32 | Cellular Modem |
| ------ | -------------- |
| GPIO25 | RX |
| GPIO26 | TX |
| GND | GND |
| 5V | VCC |
### Configure the project
Open the project configuration menu (`idf.py menuconfig`). Then go into `Example Configuration` menu.
- Choose the modem module in `Choose supported modem device(DCE)` option, currently we only support BG96 and SIM800L.
- Set the access point name in `Set Access Point Name(APN)` option, which should depend on the operator of your SIM card.
- Set the username and password for PPP authentication in `Set username for authentication` and `Set password for authentication` options.
- Select `Send MSG before power off` if you want to send a short message in the end of this example, and also you need to set the phone number correctly in `Peer Phone Number(with area code)` option.
- In `UART Configuration` menu, you need to set the GPIO numbers of UART and task specific parameters such as stack size, priority.
**Note:** During PPP setup, we should specify the way of authentication negotiation. By default it's configured to `PAP`. You can change to others (e.g. `CHAP`) in `Component config-->LWIP-->Enable PPP support` menu.
### Build and Flash
Run `idf.py -p PORT flash monitor` to build and flash the project..
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
The example will get module and operator's information after start up, and then go into PPP mode to start mqtt client operations. This example will also send a short message to someone's phone if you have enabled this feature in menuconfig. The PPP connection will get restarted after 60 seconds.
### BG96 Output
```bash
I (1276) pppos_example: Module: BG96
I (1276) pppos_example: Operator: "CHINA MOBILE CMCC"
I (1276) pppos_example: IMEI: 866425030121349
I (1276) pppos_example: IMSI: 460007454185220
I (1476) pppos_example: rssi: 27, ber: 99
I (1676) pppos_example: Battery voltage: 3908 mV
I (1876) pppos_example: Modem PPP Started
I (2656) pppos_example: Modem Connect to PPP Server
I (2656) pppos_example: ~~~~~~~~~~~~~~
I (2656) pppos_example: IP : 10.65.71.127
I (2656) pppos_example: Netmask : 255.255.255.255
I (2666) pppos_example: Gateway : 10.64.64.64
I (2666) pppos_example: Name Server1: 211.136.112.50
I (2676) pppos_example: Name Server2: 211.136.150.66
I (2676) pppos_example: ~~~~~~~~~~~~~~
I (2686) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (2696) pppos_example: MQTT other event id: 7
I (3426) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000
I (3856) pppos_example: MQTT_EVENT_CONNECTED
I (3856) pppos_example: sent subscribe successful, msg_id=20132
I (4226) pppos_example: MQTT_EVENT_SUBSCRIBED, msg_id=20132
I (4226) pppos_example: sent publish successful, msg_id=0
I (4646) pppos_example: MQTT_EVENT_DATA
TOPIC=/topic/esp-pppos
DATA=esp32-pppos
I (4696) pppos_example: Modem PPP Stopped
I (9466) pppos_example: Send send message [Welcome to ESP32!] ok
I (9666) pppos_example: Power down
```
### SIM800L Output
```bash
I (1276) pppos_example: Module: SIMCOM_SIM800L
I (1276) pppos_example: Operator: "CHINA MOBILE"
I (1276) pppos_example: IMEI: 865992039850864
I (1276) pppos_example: IMSI: 460007454185220
I (1476) pppos_example: rssi: 25, ber: 0
I (1676) pppos_example: Battery voltage: 4674 mV
I (1876) pppos_example: Modem PPP Started
I (2806) pppos_example: Modem Connect to PPP Server
I (2806) pppos_example: ~~~~~~~~~~~~~~
I (2806) pppos_example: IP : 10.188.173.2
I (2806) pppos_example: Netmask : 255.255.255.255
I (2816) pppos_example: Gateway : 192.168.254.254
I (2816) pppos_example: Name Server1: 211.136.112.50
I (2826) pppos_example: Name Server2: 211.136.150.66
I (2826) pppos_example: ~~~~~~~~~~~~~~
I (2836) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (2846) pppos_example: MQTT other event id: 7
I (8156) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000
I (8826) pppos_example: MQTT_EVENT_CONNECTED
I (8826) pppos_example: sent subscribe successful, msg_id=26237
I (9526) pppos_example: MQTT_EVENT_SUBSCRIBED, msg_id=26237
I (9526) pppos_example: sent publish successful, msg_id=0
I (10326) pppos_example: MQTT_EVENT_DATA
TOPIC=/topic/esp-pppos
DATA=esp32-pppos
I (10376) pppos_example: Modem PPP Stopped
I (14526) pppos_example: Send send message [Welcome to ESP32!] ok
I (15076) pppos_example: Power down
```
## Troubleshooting
1. Why sending AT commands always failed and this example just keeping rebooting? e.g.
```bash
E (626) sim800: sim800_sync(293): send command failed
E (626) sim800: sim800_init(628): sync failed
```
* Make sure your modem module is in command mode stably before you run this example.
(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.)

View File

@ -1,11 +0,0 @@
set(srcs "src/esp_modem.c"
"src/esp_modem_dce_service"
"src/esp_modem_netif.c"
"src/esp_modem_compat.c"
"src/sim800.c"
"src/sim7600.c"
"src/bg96.c")
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS include
REQUIRES driver)

View File

@ -1,9 +0,0 @@
menu "ESP-MODEM"
config EXAMPLE_COMPONENT_MODEM_APN
string "Set Access Point Name (APN)"
default "CMNET"
help
Logical name which is used to select the GGSN or the external packet data network.
endmenu

View File

@ -1,33 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_modem_dce_service.h"
#include "esp_modem.h"
/**
* @brief Create and initialize BG96 object
*
* @param dte Modem DTE object
* @return modem_dce_t* Modem DCE object
*/
modem_dce_t *bg96_init(modem_dte_t *dte);
#ifdef __cplusplus
}
#endif

View File

@ -1,175 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_modem_dce.h"
#include "esp_modem_dte.h"
#include "esp_event.h"
#include "driver/uart.h"
#include "esp_modem_compat.h"
/**
* @brief Declare Event Base for ESP Modem
*
*/
ESP_EVENT_DECLARE_BASE(ESP_MODEM_EVENT);
/**
* @brief ESP Modem Event
*
*/
typedef enum {
ESP_MODEM_EVENT_PPP_START = 0, /*!< ESP Modem Start PPP Session */
ESP_MODEM_EVENT_PPP_STOP = 3, /*!< ESP Modem Stop PPP Session*/
ESP_MODEM_EVENT_UNKNOWN = 4 /*!< ESP Modem Unknown Response */
} esp_modem_event_t;
/**
* @brief ESP Modem DTE Configuration
*
*/
typedef struct {
uart_port_t port_num; /*!< UART port number */
uart_word_length_t data_bits; /*!< Data bits of UART */
uart_stop_bits_t stop_bits; /*!< Stop bits of UART */
uart_parity_t parity; /*!< Parity type */
modem_flow_ctrl_t flow_control; /*!< Flow control type */
uint32_t baud_rate; /*!< Communication baud rate */
int tx_io_num; /*!< TXD Pin Number */
int rx_io_num; /*!< RXD Pin Number */
int rts_io_num; /*!< RTS Pin Number */
int cts_io_num; /*!< CTS Pin Number */
int rx_buffer_size; /*!< UART RX Buffer Size */
int tx_buffer_size; /*!< UART TX Buffer Size */
int event_queue_size; /*!< UART Event Queue Size */
uint32_t event_task_stack_size; /*!< UART Event Task Stack size */
int event_task_priority; /*!< UART Event Task Priority */
union {
int dte_buffer_size; /*!< Internal buffer size */
int line_buffer_size; /*!< Compatible option for the internal buffer size */
};
} esp_modem_dte_config_t;
/**
* @brief Type used for reception callback
*
*/
typedef esp_err_t (*esp_modem_on_receive)(void *buffer, size_t len, void *context);
/**
* @brief ESP Modem DTE Default Configuration
*
*/
#define ESP_MODEM_DTE_DEFAULT_CONFIG() \
{ \
.port_num = UART_NUM_1, \
.data_bits = UART_DATA_8_BITS, \
.stop_bits = UART_STOP_BITS_1, \
.parity = UART_PARITY_DISABLE, \
.baud_rate = 115200, \
.flow_control = MODEM_FLOW_CONTROL_NONE,\
.tx_io_num = 25, \
.rx_io_num = 26, \
.rts_io_num = 27, \
.cts_io_num = 23, \
.rx_buffer_size = 1024, \
.tx_buffer_size = 512, \
.event_queue_size = 30, \
.event_task_stack_size = 2048, \
.event_task_priority = 5, \
.dte_buffer_size = 512 \
}
/**
* @brief Create and initialize Modem DTE object
*
* @param config configuration of ESP Modem DTE object
* @return modem_dte_t*
* - Modem DTE object
*/
modem_dte_t *esp_modem_dte_init(const esp_modem_dte_config_t *config);
/**
* @brief Register event handler for ESP Modem event loop
*
* @param dte modem_dte_t type object
* @param handler event handler to register
* @param handler_args arguments for registered handler
* @return esp_err_t
* - ESP_OK on success
* - ESP_ERR_NO_MEM on allocating memory for the handler failed
* - ESP_ERR_INVALID_ARG on invalid combination of event base and event id
*/
esp_err_t esp_modem_set_event_handler(modem_dte_t *dte, esp_event_handler_t handler, int32_t event_id, void *handler_args);
/**
* @brief Unregister event handler for ESP Modem event loop
*
* @param dte modem_dte_t type object
* @param handler event handler to unregister
* @return esp_err_t
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG on invalid combination of event base and event id
*/
esp_err_t esp_modem_remove_event_handler(modem_dte_t *dte, esp_event_handler_t handler);
/**
* @brief Setup PPP Session
*
* @param dte Modem DTE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_start_ppp(modem_dte_t *dte);
/**
* @brief Exit PPP Session
*
* @param dte Modem DTE Object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_stop_ppp(modem_dte_t *dte);
/**
* @brief Setup on reception callback
*
* @param dte ESP Modem DTE object
* @param receive_cb Function pointer to the reception callback
* @param receive_cb_ctx Contextual pointer to be passed to the reception callback
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_set_rx_cb(modem_dte_t *dte, esp_modem_on_receive receive_cb, void *receive_cb_ctx);
/**
* @brief Notify the modem, that ppp netif has closed
*
* @note This API should only be used internally by the modem-netif layer
*
* @param dte ESP Modem DTE object
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_notify_ppp_netif_closed(modem_dte_t *dte);
#ifdef __cplusplus
}
#endif

View File

@ -1,62 +0,0 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "lwip/ip.h"
/**
* @brief ESP Modem Event backward compatible version
*/
typedef enum {
MODEM_EVENT_PPP_START = 0x100,
MODEM_EVENT_PPP_CONNECT = 0x101,
MODEM_EVENT_PPP_DISCONNECT = 0x102,
MODEM_EVENT_PPP_STOP = 0x103,
MODEM_EVENT_UNKNOWN = 0x104,
} esp_modem_compat_event_t;
/**
* @brief PPPoS Client IP Information backward compatible version
*
*/
typedef struct {
ip4_addr_t ip; /*!< IP Address */
ip4_addr_t netmask; /*!< Net Mask */
ip4_addr_t gw; /*!< Gateway */
ip4_addr_t ns1; /*!< Name Server1 */
ip4_addr_t ns2; /*!< Name Server2 */
} ppp_client_ip_info_t;
/**
* @brief Backward compatible version of esp_modem_set_event_handler()
*/
esp_err_t esp_modem_add_event_handler(modem_dte_t *dte, esp_event_handler_t handler, void *handler_args) __attribute__ ((deprecated));
/**
* @brief Backward compatible version of creating esp-netif(PPP) and attaching to esp_modem_start_ppp()
*/
esp_err_t esp_modem_setup_ppp(modem_dte_t *dte) __attribute__ ((deprecated));
/**
* @brief Backward compatible version of deleting esp-netif and esp_modem_stop_ppp()
*/
esp_err_t esp_modem_exit_ppp(modem_dte_t *dte) __attribute__ ((deprecated));
#ifdef __cplusplus
}
#endif

View File

@ -1,112 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_types.h"
#include "esp_err.h"
#include "esp_modem_dte.h"
typedef struct modem_dce modem_dce_t;
typedef struct modem_dte modem_dte_t;
typedef struct esp_modem_dce esp_modem_dce_t;
/**
* @brief Result Code from DCE
*
*/
#define MODEM_RESULT_CODE_SUCCESS "OK" /*!< Acknowledges execution of a command */
#define MODEM_RESULT_CODE_CONNECT "CONNECT" /*!< A connection has been established */
#define MODEM_RESULT_CODE_RING "RING" /*!< Detect an incoming call signal from network */
#define MODEM_RESULT_CODE_NO_CARRIER "NO CARRIER" /*!< Connection termincated or establish a connection failed */
#define MODEM_RESULT_CODE_ERROR "ERROR" /*!< Command not recognized, command line maximum length exceeded, parameter value invalid */
#define MODEM_RESULT_CODE_NO_DIALTONE "NO DIALTONE" /*!< No dial tone detected */
#define MODEM_RESULT_CODE_BUSY "BUSY" /*!< Engaged signal detected */
#define MODEM_RESULT_CODE_NO_ANSWER "NO ANSWER" /*!< Wait for quiet answer */
/**
* @brief Specific Length Constraint
*
*/
#define MODEM_MAX_NAME_LENGTH (32) /*!< Max Module Name Length */
#define MODEM_MAX_OPERATOR_LENGTH (32) /*!< Max Operator Name Length */
#define MODEM_IMEI_LENGTH (15) /*!< IMEI Number Length */
#define MODEM_IMSI_LENGTH (15) /*!< IMSI Number Length */
/**
* @brief Specific Timeout Constraint, Unit: millisecond
*
*/
#define MODEM_COMMAND_TIMEOUT_DEFAULT (500) /*!< Default timeout value for most commands */
#define MODEM_COMMAND_TIMEOUT_OPERATOR (75000) /*!< Timeout value for getting operator status */
#define MODEM_COMMAND_TIMEOUT_MODE_CHANGE (5000) /*!< Timeout value for changing working mode */
#define MODEM_COMMAND_TIMEOUT_HANG_UP (90000) /*!< Timeout value for hang up */
#define MODEM_COMMAND_TIMEOUT_POWEROFF (1000) /*!< Timeout value for power down */
/**
* @brief Working state of DCE
*
*/
typedef enum {
MODEM_STATE_PROCESSING, /*!< In processing */
MODEM_STATE_SUCCESS, /*!< Process successfully */
MODEM_STATE_FAIL /*!< Process failed */
} modem_state_t;
/**
* @brief DCE(Data Communication Equipment)
*
*/
struct modem_dce {
char imei[MODEM_IMEI_LENGTH + 1]; /*!< IMEI number */
char imsi[MODEM_IMSI_LENGTH + 1]; /*!< IMSI number */
char name[MODEM_MAX_NAME_LENGTH]; /*!< Module name */
char oper[MODEM_MAX_OPERATOR_LENGTH]; /*!< Operator name */
uint8_t act; /*!< Access technology */
const char *prompt; /*!< Modem prompt string */
modem_state_t state; /*!< Modem working state */
modem_mode_t mode; /*!< Working mode */
modem_dte_t *dte; /*!< DTE which connect to DCE */
esp_err_t (*handle_line)(modem_dce_t *dce, const char *line); /*!< Handle line strategy */
esp_err_t (*sync)(modem_dce_t *dce); /*!< Synchronization */
esp_err_t (*echo_mode)(modem_dce_t *dce, bool on); /*!< Echo command on or off */
esp_err_t (*store_profile)(modem_dce_t *dce); /*!< Store user settings */
esp_err_t (*set_flow_ctrl)(modem_dce_t *dce, modem_flow_ctrl_t flow_ctrl); /*!< Flow control on or off */
esp_err_t (*get_signal_quality)(modem_dce_t *dce, uint32_t *rssi, uint32_t *ber); /*!< Get signal quality */
esp_err_t (*get_battery_status)(modem_dce_t *dce, uint32_t *bcs,
uint32_t *bcl, uint32_t *voltage); /*!< Get battery status */
esp_err_t (*get_operator_name)(modem_dce_t *dce); /*!< Get operator name */
esp_err_t (*define_pdp_context)(modem_dce_t *dce, uint32_t cid,
const char *type, const char *apn); /*!< Set PDP Contex */
esp_err_t (*set_working_mode)(modem_dce_t *dce, modem_mode_t mode); /*!< Set working mode */
esp_err_t (*hang_up)(modem_dce_t *dce); /*!< Hang up */
esp_err_t (*power_down)(modem_dce_t *dce); /*!< Normal power down */
esp_err_t (*deinit)(modem_dce_t *dce); /*!< Deinitialize */
};
/**
* @brief ESP Modem with private resource
*
*/
struct esp_modem_dce {
void *priv_resource; /*!< Private resource */
modem_dce_t parent; /*!< DCE parent class */
};
#ifdef __cplusplus
}
#endif

View File

@ -1,218 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_modem_dce.h"
/**
* @brief Indicate that processing current command has done
*
* @param dce Modem DCE object
* @param state Modem state after processing
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static inline esp_err_t esp_modem_process_command_done(modem_dce_t *dce, modem_state_t state)
{
dce->state = state;
return dce->dte->process_cmd_done(dce->dte);
}
/**
* @brief Strip the tailed "\r\n"
*
* @param str string to strip
* @param len length of string
*/
static inline void strip_cr_lf_tail(char *str, uint32_t len)
{
if (str[len - 2] == '\r') {
str[len - 2] = '\0';
} else if (str[len - 1] == '\r') {
str[len - 1] = '\0';
}
}
/**
* @brief Default handler for response
* Some responses for command are simple, commonly will return OK when succeed of ERROR when failed
*
* @param dce Modem DCE object
* @param line line string
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_handle_response_default(modem_dce_t *dce, const char *line);
/**
* @brief Handle response from +++ (Set Working Mode)
*
* @param dce Modem DCE object
* @param line line string
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_handle_exit_data_mode(modem_dce_t *dce, const char *line);
/**
* @brief Handle response from ATD*99# (Set Working Mode)
*
* @param dce Modem DCE object
* @param line line string
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_handle_atd_ppp(modem_dce_t *dce, const char *line);
/**
* @brief Syncronization
*
* @param dce Modem DCE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_sync(modem_dce_t *dce);
/**
* @brief Enable or not echo mode of DCE (V.25TER specification)
*
* @param dce Modem DCE object
* @param on true to enable echo mode, false to disable echo mode
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_echo(modem_dce_t *dce, bool on);
/**
* @brief Store current parameter setting in the user profile
*
* @param dce Modem DCE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_store_profile(modem_dce_t *dce);
/**
* @brief Set flow control mode of DCE in data mode (V.25TER specification)
*
* @param dce Modem DCE object
* @param flow_ctrl flow control mode
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_set_flow_ctrl(modem_dce_t *dce, modem_flow_ctrl_t flow_ctrl);
/**
* @brief Define PDP context (GPRS)
*
* @param dce Modem DCE object
* @param cid PDP context identifier
* @param type Protocol type
* @param apn Access point name
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_define_pdp_context(modem_dce_t *dce, uint32_t cid, const char *type, const char *apn);
/**
* @brief Get signal quality (3GPP TS 27.007 specification)
*
* @param dce Modem DCE object
* @param rssi received signal strength indication
* @param ber bit error ratio
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_get_signal_quality(modem_dce_t *dce, uint32_t *rssi, uint32_t *ber);
/**
* @brief Get battery status (3GPP TS 27.007 specification)
*
* @param dce Modem DCE object
* @param bcs Battery charge status
* @param bcl Battery connection level
* @param voltage Battery voltage
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_get_battery_status(modem_dce_t *dce, uint32_t *bcs, uint32_t *bcl, uint32_t *voltage);
/**
* @brief Get DCE module name (3GPP TS 27.007 specification)
*
* @param dce Modem DCE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_get_module_name(modem_dce_t *dce);
/**
* @brief Get DCE module IMEI number (3GPP TS 27.007 specification)
*
* @param dce Modem DCE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_get_imei_number(modem_dce_t *dce);
/**
* @brief Get DCE module IMSI number (3GPP TS 27.007 specification)
*
* @param dce Modem DCE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_get_imsi_number(modem_dce_t *dce);
/**
* @brief Get Operator's name (3GPP TS 27.007 specification)
*
* @param dce Modem DCE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_get_operator_name(modem_dce_t *dce);
/**
* @brief Hang up (V.25TER specification)
*
* @param dce Modem DCE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_hang_up(modem_dce_t *dce);
#ifdef __cplusplus
}
#endif

View File

@ -1,66 +0,0 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_types.h"
#include "esp_err.h"
#include "esp_event.h"
typedef struct modem_dte modem_dte_t;
typedef struct modem_dce modem_dce_t;
/**
* @brief Working mode of Modem
*
*/
typedef enum {
MODEM_COMMAND_MODE = 0, /*!< Command Mode */
MODEM_PPP_MODE, /*!< PPP Mode */
MODEM_TRANSITION_MODE /*!< Transition Mode between data and command mode indicating that
the modem is not yet ready for sending commands nor data */
} modem_mode_t;
/**
* @brief Modem flow control type
*
*/
typedef enum {
MODEM_FLOW_CONTROL_NONE = 0,
MODEM_FLOW_CONTROL_SW,
MODEM_FLOW_CONTROL_HW
} modem_flow_ctrl_t;
/**
* @brief DTE(Data Terminal Equipment)
*
*/
struct modem_dte {
modem_flow_ctrl_t flow_ctrl; /*!< Flow control of DTE */
modem_dce_t *dce; /*!< DCE which connected to the DTE */
esp_err_t (*send_cmd)(modem_dte_t *dte, const char *command, uint32_t timeout); /*!< Send command to DCE */
int (*send_data)(modem_dte_t *dte, const char *data, uint32_t length); /*!< Send data to DCE */
esp_err_t (*send_wait)(modem_dte_t *dte, const char *data, uint32_t length,
const char *prompt, uint32_t timeout); /*!< Wait for specific prompt */
esp_err_t (*change_mode)(modem_dte_t *dte, modem_mode_t new_mode); /*!< Changing working mode */
esp_err_t (*process_cmd_done)(modem_dte_t *dte); /*!< Callback when DCE process command done */
esp_err_t (*deinit)(modem_dte_t *dte); /*!< Deinitialize */
};
#ifdef __cplusplus
}
#endif

View File

@ -1,53 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Creates handle to esp_modem used as an esp-netif driver
*
* @param dte ESP Modem DTE object
*
* @return opaque pointer to esp-modem IO driver used to attach to esp-netif
*/
void *esp_modem_netif_setup(modem_dte_t *dte);
/**
* @brief Destroys the esp-netif driver handle
*
* @param h pointer to the esp-netif adapter for esp-modem
*/
void esp_modem_netif_teardown(void *h);
/**
* @brief Clears default handlers for esp-modem lifecycle
*
* @param h pointer to the esp-netif adapter for esp-modem
*/
esp_err_t esp_modem_netif_clear_default_handlers(void *h);
/**
* @brief Setups default handlers for esp-modem lifecycle
*
* @param h pointer to the esp-netif adapter for esp-modem
* @param esp_netif pointer corresponding esp-netif instance
*/
esp_err_t esp_modem_netif_set_default_handlers(void *h, esp_netif_t * esp_netif);
#ifdef __cplusplus
}
#endif

View File

@ -1,33 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_modem_dce_service.h"
#include "esp_modem.h"
/**
* @brief Create and initialize SIM7600 object
*
* @param dte Modem DTE object
* @return modem_dce_t* Modem DCE object
*/
modem_dce_t *sim7600_init(modem_dte_t *dte);
#ifdef __cplusplus
}
#endif

View File

@ -1,33 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_modem_dce_service.h"
#include "esp_modem.h"
/**
* @brief Create and initialize SIM800 object
*
* @param dte Modem DTE object
* @return modem_dce_t* Modem DCE object
*/
modem_dce_t *sim800_init(modem_dte_t *dte);
#ifdef __cplusplus
}
#endif

View File

@ -1,184 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_modem_dce_service.h"
#include "bg96.h"
#define MODEM_RESULT_CODE_POWERDOWN "POWERED DOWN"
static const char *DCE_TAG = "bg96";
/**
* @brief Macro defined for error checking
*
*/
#define DCE_CHECK(a, str, goto_tag, ...) \
do \
{ \
if (!(a)) \
{ \
ESP_LOGE(DCE_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
goto goto_tag; \
} \
} while (0)
/**
* @brief Handle response from AT+QPOWD=1
*/
static esp_err_t bg96_handle_power_down(modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = ESP_OK;
} else if (strstr(line, MODEM_RESULT_CODE_POWERDOWN)) {
err = esp_modem_process_command_done(dce, MODEM_STATE_SUCCESS);
}
return err;
}
/**
* @brief Set Working Mode
*
* @param dce Modem DCE object
* @param mode woking mode
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t bg96_set_working_mode(modem_dce_t *dce, modem_mode_t mode)
{
modem_dte_t *dte = dce->dte;
switch (mode) {
case MODEM_COMMAND_MODE:
vTaskDelay(pdMS_TO_TICKS(1000)); // spec: 1s delay for the modem to recognize the escape sequence
dce->handle_line = esp_modem_dce_handle_exit_data_mode;
if (dte->send_cmd(dte, "+++", MODEM_COMMAND_TIMEOUT_MODE_CHANGE) != ESP_OK) {
// "+++" Could fail if we are already in the command mode.
// in that case we ignore the timeout and re-sync the modem
ESP_LOGI(DCE_TAG, "Sending \"+++\" command failed");
dce->handle_line = esp_modem_dce_handle_response_default;
DCE_CHECK(dte->send_cmd(dte, "AT\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "sync failed", err);
} else {
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "enter command mode failed", err);
}
ESP_LOGD(DCE_TAG, "enter command mode ok");
dce->mode = MODEM_COMMAND_MODE;
break;
case MODEM_PPP_MODE:
dce->handle_line = esp_modem_dce_handle_atd_ppp;
DCE_CHECK(dte->send_cmd(dte, "ATD*99***1#\r", MODEM_COMMAND_TIMEOUT_MODE_CHANGE) == ESP_OK, "send command failed", err);
if (dce->state != MODEM_STATE_SUCCESS) {
// Initiate PPP mode could fail, if we've already "dialed" the data call before.
// in that case we retry with "ATO" to just resume the data mode
ESP_LOGD(DCE_TAG, "enter ppp mode failed, retry with ATO");
dce->handle_line = esp_modem_dce_handle_atd_ppp;
DCE_CHECK(dte->send_cmd(dte, "ATO\r", MODEM_COMMAND_TIMEOUT_MODE_CHANGE) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "enter ppp mode failed", err);
}
ESP_LOGD(DCE_TAG, "enter ppp mode ok");
dce->mode = MODEM_PPP_MODE;
break;
default:
ESP_LOGW(DCE_TAG, "unsupported working mode: %d", mode);
goto err;
break;
}
return ESP_OK;
err:
return ESP_FAIL;
}
/**
* @brief Power down
*
* @param bg96_dce bg96 object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t bg96_power_down(modem_dce_t *dce)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = bg96_handle_power_down;
DCE_CHECK(dte->send_cmd(dte, "AT+QPOWD=1\r", MODEM_COMMAND_TIMEOUT_POWEROFF) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "power down failed", err);
ESP_LOGD(DCE_TAG, "power down ok");
return ESP_OK;
err:
return ESP_FAIL;
}
/**
* @brief Deinitialize BG96 object
*
* @param dce Modem DCE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on fail
*/
static esp_err_t bg96_deinit(modem_dce_t *dce)
{
esp_modem_dce_t *esp_modem_dce = __containerof(dce, esp_modem_dce_t, parent);
if (dce->dte) {
dce->dte->dce = NULL;
}
free(esp_modem_dce);
return ESP_OK;
}
modem_dce_t *bg96_init(modem_dte_t *dte)
{
DCE_CHECK(dte, "DCE should bind with a DTE", err);
/* malloc memory for esp_modem_dce object */
esp_modem_dce_t *esp_modem_dce = calloc(1, sizeof(esp_modem_dce_t));
DCE_CHECK(esp_modem_dce, "calloc bg96_dce failed", err);
/* Bind DTE with DCE */
esp_modem_dce->parent.dte = dte;
dte->dce = &(esp_modem_dce->parent);
/* Bind methods */
esp_modem_dce->parent.handle_line = NULL;
esp_modem_dce->parent.sync = esp_modem_dce_sync;
esp_modem_dce->parent.echo_mode = esp_modem_dce_echo;
esp_modem_dce->parent.store_profile = esp_modem_dce_store_profile;
esp_modem_dce->parent.set_flow_ctrl = esp_modem_dce_set_flow_ctrl;
esp_modem_dce->parent.define_pdp_context = esp_modem_dce_define_pdp_context;
esp_modem_dce->parent.hang_up = esp_modem_dce_hang_up;
esp_modem_dce->parent.get_signal_quality = esp_modem_dce_get_signal_quality;
esp_modem_dce->parent.get_battery_status = esp_modem_dce_get_battery_status;
esp_modem_dce->parent.get_operator_name = esp_modem_dce_get_operator_name;
esp_modem_dce->parent.set_working_mode = bg96_set_working_mode;
esp_modem_dce->parent.power_down = bg96_power_down;
esp_modem_dce->parent.deinit = bg96_deinit;
/* Sync between DTE and DCE */
DCE_CHECK(esp_modem_dce_sync(&(esp_modem_dce->parent)) == ESP_OK, "sync failed", err_io);
/* Close echo */
DCE_CHECK(esp_modem_dce_echo(&(esp_modem_dce->parent), false) == ESP_OK, "close echo mode failed", err_io);
/* Get Module name */
DCE_CHECK(esp_modem_dce_get_module_name(&(esp_modem_dce->parent)) == ESP_OK, "get module name failed", err_io);
/* Get IMEI number */
DCE_CHECK(esp_modem_dce_get_imei_number(&(esp_modem_dce->parent)) == ESP_OK, "get imei failed", err_io);
/* Get IMSI number */
DCE_CHECK(esp_modem_dce_get_imsi_number(&(esp_modem_dce->parent)) == ESP_OK, "get imsi failed", err_io);
/* Get operator name */
DCE_CHECK(esp_modem_dce_get_operator_name(&(esp_modem_dce->parent)) == ESP_OK, "get operator name failed", err_io);
return &(esp_modem_dce->parent);
err_io:
free(esp_modem_dce);
dte->dce = NULL;
err:
return NULL;
}

View File

@ -1,544 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_modem.h"
#include "esp_log.h"
#include "sdkconfig.h"
#define ESP_MODEM_EVENT_QUEUE_SIZE (16)
/**
* @brief This sets the threshold for receiving data events when UART RX buffer reaches
* this level. Decreasing the number causes more events and lowers changes of UART overflows,
* but more allocations in lwIP. You can increase this number if you're using slower baudrates
* or having the UART ISR in IRAM.
*/
#define ESP_MODEM_UART_RX_FULL_THRESHOLD (64)
/**
* @brief Macro defined for error checking
*
*/
static const char *MODEM_TAG = "esp-modem";
#define MODEM_CHECK(a, str, goto_tag, ...) \
do \
{ \
if (!(a)) \
{ \
ESP_LOGE(MODEM_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
goto goto_tag; \
} \
} while (0)
ESP_EVENT_DEFINE_BASE(ESP_MODEM_EVENT);
/**
* @brief ESP32 Modem DTE
*
*/
typedef struct {
uart_port_t uart_port; /*!< UART port */
uint8_t *buffer; /*!< Internal buffer to store response lines/data from DCE */
QueueHandle_t event_queue; /*!< UART event queue handle */
esp_event_loop_handle_t event_loop_hdl; /*!< Event loop handle */
TaskHandle_t uart_event_task_hdl; /*!< UART event task handle */
SemaphoreHandle_t process_sem; /*!< Semaphore used for indicating processing status */
SemaphoreHandle_t exit_sem; /*!< Semaphore used for indicating PPP mode has stopped */
modem_dte_t parent; /*!< DTE interface that should extend */
esp_modem_on_receive receive_cb; /*!< ptr to data reception */
void *receive_cb_ctx; /*!< ptr to rx fn context data */
int buffer_size; /*!< internal buffer size */
int consumed; /*!< index to the consumed buffer pointer */
} esp_modem_dte_t;
/**
* @brief Returns true if the supplied string contains only CR or LF
*
* @param str string to check
* @param len length of string
*/
static inline bool is_only_cr_lf(const char *str, uint32_t len)
{
for (int i=0; i<len; ++i) {
if (str[i] != '\r' && str[i] != '\n') {
return false;
}
}
return true;
}
static inline void report_unknown_line(esp_modem_dte_t *esp_dte, char *line)
{
/* Send ESP_MODEM_EVENT_UNKNOWN signal to event loop */
esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_MODEM_EVENT_UNKNOWN,
(void *)line, strlen(line) + 1, pdMS_TO_TICKS(100));
}
esp_err_t esp_modem_set_rx_cb(modem_dte_t *dte, esp_modem_on_receive receive_cb, void *receive_cb_ctx)
{
esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent);
esp_dte->receive_cb_ctx = receive_cb_ctx;
esp_dte->receive_cb = receive_cb;
return ESP_OK;
}
/**
* @brief Handle one line in DTE
*
* @param esp_dte ESP modem DTE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t esp_dte_handle_line(esp_modem_dte_t *esp_dte, char * line, size_t len, char separator)
{
esp_err_t err = ESP_FAIL;
modem_dce_t *dce = esp_dte->parent.dce;
MODEM_CHECK(dce, "DTE has not yet bind with DCE", err);
if (separator != '\n' && dce->handle_line) {
/* If waiting for a specific separator, just pass the entire string */
MODEM_CHECK(dce->handle_line(dce, line) == ESP_OK, "handle line failed", post_event_unknown);
return ESP_OK;
}
/* Tokenize the data to call handlers separately for each *line* */
char *str_ptr = NULL;
char *p = strtok_r(line, "\n", &str_ptr);
while (p) {
if (len > 2 && !is_only_cr_lf(p, strlen(p))) {
ESP_LOGD(MODEM_TAG, "Handling line: >>%s\n<<", p);
if (dce->handle_line == NULL) {
/* Received an asynchronous line, but no handler waiting this this */
ESP_LOGD(MODEM_TAG, "No handler for line: %s", p);
report_unknown_line(esp_dte, line);
return ESP_OK; /* Not an error, just propagate the line to user handler */
}
if (dce->handle_line(dce, p) != ESP_OK) {
ESP_LOGE(MODEM_TAG, "handle line failed");
report_unknown_line(esp_dte, line);
}
}
p = strtok_r(NULL, "\n", &str_ptr);
}
return ESP_OK;
post_event_unknown:
report_unknown_line(esp_dte, line);
err:
return err;
}
/**
* @brief Handle when new data received by UART
*
* @param esp_dte ESP32 Modem DTE object
*/
static void esp_handle_uart_data(esp_modem_dte_t *esp_dte)
{
size_t length = 0;
uart_get_buffered_data_len(esp_dte->uart_port, &length);
ESP_LOGV(MODEM_TAG, "uart_get_buffered_data_len()=%d", length);
if (esp_dte->parent.dce->mode != MODEM_PPP_MODE && length) {
// Read the data and process it using `handle_line` logic
length = MIN(esp_dte->buffer_size - 1, length);
length = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer + esp_dte->consumed, length - esp_dte->consumed, portMAX_DELAY);
const char separator = esp_dte->parent.dce->prompt == NULL ? '\n' : (esp_dte->parent.dce->prompt)[strlen(esp_dte->parent.dce->prompt)-1];
if (memchr(esp_dte->buffer + esp_dte->consumed, separator, length)) {
esp_dte->buffer[length] = '\0';
ESP_LOG_BUFFER_HEXDUMP("esp-modem: pattern-detection", esp_dte->buffer, length, ESP_LOG_VERBOSE);
if (esp_dte->parent.dce->handle_line) {
/* Send new line to handle if handler registered */
if (esp_dte_handle_line(esp_dte, (char*)esp_dte->buffer, length, separator) == ESP_OK) {
esp_dte->consumed = 0;
return;
}
}
esp_dte->consumed += length;
}
return;
}
length = MIN(esp_dte->buffer_size, length);
length = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer, length, portMAX_DELAY);
/* pass the input data to configured callback */
if (length) {
esp_dte->receive_cb(esp_dte->buffer, length, esp_dte->receive_cb_ctx);
}
}
/**
* @brief UART Event Task Entry
*
* @param param task parameter
*/
static void uart_event_task_entry(void *param)
{
esp_modem_dte_t *esp_dte = (esp_modem_dte_t *)param;
uart_event_t event;
while (1) {
/* Drive the event loop */
esp_event_loop_run(esp_dte->event_loop_hdl, pdMS_TO_TICKS(0));
/* Process UART events */
if (xQueueReceive(esp_dte->event_queue, &event, pdMS_TO_TICKS(100))) {
if (esp_dte->parent.dce == NULL) {
ESP_LOGD(MODEM_TAG, "Ignore UART event for DTE with no DCE attached");
// No action on any uart event with null DCE.
// This might happen before DCE gets initialized and attached to running DTE,
// or after destroying the DCE when DTE is up and gets a data event.
uart_flush(esp_dte->uart_port);
continue;
}
switch (event.type) {
case UART_DATA:
esp_handle_uart_data(esp_dte);
break;
case UART_FIFO_OVF:
ESP_LOGW(MODEM_TAG, "HW FIFO Overflow");
uart_flush_input(esp_dte->uart_port);
xQueueReset(esp_dte->event_queue);
break;
case UART_BUFFER_FULL:
ESP_LOGW(MODEM_TAG, "Ring Buffer Full");
uart_flush_input(esp_dte->uart_port);
xQueueReset(esp_dte->event_queue);
break;
case UART_BREAK:
ESP_LOGW(MODEM_TAG, "Rx Break");
break;
case UART_PARITY_ERR:
ESP_LOGE(MODEM_TAG, "Parity Error");
break;
case UART_FRAME_ERR:
ESP_LOGE(MODEM_TAG, "Frame Error");
break;
default:
ESP_LOGW(MODEM_TAG, "unknown uart event type: %d", event.type);
break;
}
}
}
}
/**
* @brief Send command to DCE
*
* @param dte Modem DTE object
* @param command command string
* @param timeout timeout value, unit: ms
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t esp_modem_dte_send_cmd(modem_dte_t *dte, const char *command, uint32_t timeout)
{
esp_err_t ret = ESP_FAIL;
modem_dce_t *dce = dte->dce;
ESP_LOGD(MODEM_TAG, "Sending command:%s", command);
MODEM_CHECK(dce, "DTE has not yet bind with DCE", errdce);
MODEM_CHECK(command, "command is NULL", err);
esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent);
esp_dte->consumed = 0;
/* Calculate timeout clock tick */
/* Reset runtime information */
dce->state = MODEM_STATE_PROCESSING;
/* Send command via UART */
uart_write_bytes(esp_dte->uart_port, command, strlen(command));
/* Check timeout */
MODEM_CHECK(xSemaphoreTake(esp_dte->process_sem, pdMS_TO_TICKS(timeout)) == pdTRUE, "process command timeout", err);
ret = ESP_OK;
err:
dce->handle_line = NULL;
errdce:
return ret;
}
/**
* @brief Send data to DCE
*
* @param dte Modem DTE object
* @param data data buffer
* @param length length of data to send
* @return int actual length of data that has been send out
*/
static int esp_modem_dte_send_data(modem_dte_t *dte, const char *data, uint32_t length)
{
MODEM_CHECK(data, "data is NULL", err);
esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent);
if (esp_dte->parent.dce->mode == MODEM_TRANSITION_MODE) {
ESP_LOGD(MODEM_TAG, "Not sending data in transition mode");
return -1;
}
return uart_write_bytes(esp_dte->uart_port, data, length);
err:
return -1;
}
/**
* @brief Handle response from send data and wait from prompt.
*/
static esp_err_t esp_modem_dte_send_wait_default_handler(modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (!strncmp(line, dce->prompt, strlen(dce->prompt))) {
dce->state = MODEM_STATE_SUCCESS;
err = dce->dte->process_cmd_done(dce->dte);
} else {
dce->state = MODEM_STATE_FAIL;
err = dce->dte->process_cmd_done(dce->dte);
}
return err;
}
/**
* @brief Send data and wait for prompt from DCE
*
* @param dte Modem DTE object
* @param data data buffer
* @param length length of data to send
* @param prompt pointer of specific prompt
* @param timeout timeout value (unit: ms)
* @return esp_err_t
* ESP_OK on success
* ESP_FAIL on error
*/
static esp_err_t esp_modem_dte_send_wait(modem_dte_t *dte, const char *data, uint32_t length,
const char *prompt, uint32_t timeout)
{
MODEM_CHECK(data, "data is NULL", err_param);
MODEM_CHECK(prompt, "prompt is NULL", err_param);
modem_dce_t *dce = dte->dce;
MODEM_CHECK(dce, "DTE has not yet bind with DCE", err_param);
dce->prompt = prompt; // the last character of this prompt will be used as a separator to call the line handker
dce->handle_line = esp_modem_dte_send_wait_default_handler;
MODEM_CHECK(dte->send_cmd(dte, data, timeout) == ESP_OK, "wait for prompt timeout", err);
MODEM_CHECK(dce->state == MODEM_STATE_SUCCESS, "wait for prompt failed", err);
dce->prompt = NULL;
return ESP_OK;
err:
dce->prompt = NULL;
err_param:
return ESP_FAIL;
}
/**
* @brief Change Modem's working mode
*
* @param dte Modem DTE object
* @param new_mode new working mode
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t esp_modem_dte_change_mode(modem_dte_t *dte, modem_mode_t new_mode)
{
modem_dce_t *dce = dte->dce;
MODEM_CHECK(dce, "DTE has not yet bind with DCE", err);
modem_mode_t current_mode = dce->mode;
MODEM_CHECK(current_mode != new_mode, "already in mode: %d", err, new_mode);
dce->mode = MODEM_TRANSITION_MODE; // mode switching will be finished in set_working_mode() on success
// (or restored on failure)
MODEM_CHECK(dce->set_working_mode(dce, new_mode) == ESP_OK, "set new working mode:%d failed", err_restore_mode, new_mode);
return ESP_OK;
err_restore_mode:
dce->mode = current_mode;
err:
return ESP_FAIL;
}
static esp_err_t esp_modem_dte_process_cmd_done(modem_dte_t *dte)
{
esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent);
return xSemaphoreGive(esp_dte->process_sem) == pdTRUE ? ESP_OK : ESP_FAIL;
}
/**
* @brief Deinitialize a Modem DTE object
*
* @param dte Modem DTE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t esp_modem_dte_deinit(modem_dte_t *dte)
{
esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent);
/* Delete UART event task */
vTaskDelete(esp_dte->uart_event_task_hdl);
/* Delete semaphores */
vSemaphoreDelete(esp_dte->process_sem);
vSemaphoreDelete(esp_dte->exit_sem);
/* Delete event loop */
esp_event_loop_delete(esp_dte->event_loop_hdl);
/* Uninstall UART Driver */
uart_driver_delete(esp_dte->uart_port);
/* Free memory */
free(esp_dte->buffer);
if (dte->dce) {
dte->dce->dte = NULL;
}
free(esp_dte);
return ESP_OK;
}
modem_dte_t *esp_modem_dte_init(const esp_modem_dte_config_t *config)
{
esp_err_t res;
/* malloc memory for esp_dte object */
esp_modem_dte_t *esp_dte = calloc(1, sizeof(esp_modem_dte_t));
MODEM_CHECK(esp_dte, "calloc esp_dte failed", err_dte_mem);
/* malloc memory to storing lines from modem dce */
esp_dte->buffer_size = config->dte_buffer_size;
esp_dte->buffer = calloc(1, config->dte_buffer_size);
MODEM_CHECK(esp_dte->buffer, "calloc line memory failed", err_line_mem);
/* Set attributes */
esp_dte->uart_port = config->port_num;
esp_dte->parent.flow_ctrl = config->flow_control;
/* Bind methods */
esp_dte->parent.send_cmd = esp_modem_dte_send_cmd;
esp_dte->parent.send_data = esp_modem_dte_send_data;
esp_dte->parent.send_wait = esp_modem_dte_send_wait;
esp_dte->parent.change_mode = esp_modem_dte_change_mode;
esp_dte->parent.process_cmd_done = esp_modem_dte_process_cmd_done;
esp_dte->parent.deinit = esp_modem_dte_deinit;
/* Config UART */
uart_config_t uart_config = {
.baud_rate = config->baud_rate,
.data_bits = config->data_bits,
.parity = config->parity,
.stop_bits = config->stop_bits,
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
.source_clk = UART_SCLK_REF_TICK,
#else
.source_clk = UART_SCLK_XTAL,
#endif
.flow_ctrl = (config->flow_control == MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS : UART_HW_FLOWCTRL_DISABLE
};
MODEM_CHECK(uart_param_config(esp_dte->uart_port, &uart_config) == ESP_OK, "config uart parameter failed", err_uart_config);
if (config->flow_control == MODEM_FLOW_CONTROL_HW) {
res = uart_set_pin(esp_dte->uart_port, config->tx_io_num, config->rx_io_num,
config->rts_io_num, config->cts_io_num);
} else {
res = uart_set_pin(esp_dte->uart_port, config->tx_io_num, config->rx_io_num,
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
MODEM_CHECK(res == ESP_OK, "config uart gpio failed", err_uart_config);
/* Set flow control threshold */
if (config->flow_control == MODEM_FLOW_CONTROL_HW) {
res = uart_set_hw_flow_ctrl(esp_dte->uart_port, UART_HW_FLOWCTRL_CTS_RTS, UART_FIFO_LEN - 8);
} else if (config->flow_control == MODEM_FLOW_CONTROL_SW) {
res = uart_set_sw_flow_ctrl(esp_dte->uart_port, true, 8, UART_FIFO_LEN - 8);
}
MODEM_CHECK(res == ESP_OK, "config uart flow control failed", err_uart_config);
/* Install UART driver and get event queue used inside driver */
res = uart_driver_install(esp_dte->uart_port, config->rx_buffer_size, config->tx_buffer_size,
config->event_queue_size, &(esp_dte->event_queue), 0);
MODEM_CHECK(res == ESP_OK, "install uart driver failed", err_uart_config);
res = uart_set_rx_timeout(esp_dte->uart_port, 1);
MODEM_CHECK(res == ESP_OK, "set rx timeout failed", err_uart_config);
res = uart_set_rx_full_threshold(config->port_num, ESP_MODEM_UART_RX_FULL_THRESHOLD);
MODEM_CHECK(res == ESP_OK, "config rx full threshold failed", err_uart_config);
/* Create Event loop */
esp_event_loop_args_t loop_args = {
.queue_size = ESP_MODEM_EVENT_QUEUE_SIZE,
.task_name = NULL
};
MODEM_CHECK(esp_event_loop_create(&loop_args, &esp_dte->event_loop_hdl) == ESP_OK, "create event loop failed", err_eloop);
/* Create semaphore */
esp_dte->process_sem = xSemaphoreCreateBinary();
MODEM_CHECK(esp_dte->process_sem, "create process semaphore failed", err_sem1);
esp_dte->exit_sem = xSemaphoreCreateBinary();
MODEM_CHECK(esp_dte->exit_sem, "create exit semaphore failed", err_sem);
/* Create UART Event task */
BaseType_t ret = xTaskCreate(uart_event_task_entry, //Task Entry
"uart_event", //Task Name
config->event_task_stack_size, //Task Stack Size(Bytes)
esp_dte, //Task Parameter
config->event_task_priority, //Task Priority
& (esp_dte->uart_event_task_hdl) //Task Handler
);
MODEM_CHECK(ret == pdTRUE, "create uart event task failed", err_tsk_create);
return &(esp_dte->parent);
/* Error handling */
err_tsk_create:
vSemaphoreDelete(esp_dte->exit_sem);
err_sem:
vSemaphoreDelete(esp_dte->process_sem);
err_sem1:
esp_event_loop_delete(esp_dte->event_loop_hdl);
err_eloop:
uart_driver_delete(esp_dte->uart_port);
err_uart_config:
free(esp_dte->buffer);
err_line_mem:
free(esp_dte);
err_dte_mem:
return NULL;
}
esp_err_t esp_modem_set_event_handler(modem_dte_t *dte, esp_event_handler_t handler, int32_t event_id, void *handler_args)
{
esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent);
return esp_event_handler_register_with(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, event_id, handler, handler_args);
}
esp_err_t esp_modem_remove_event_handler(modem_dte_t *dte, esp_event_handler_t handler)
{
esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent);
return esp_event_handler_unregister_with(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_EVENT_ANY_ID, handler);
}
esp_err_t esp_modem_start_ppp(modem_dte_t *dte)
{
modem_dce_t *dce = dte->dce;
MODEM_CHECK(dce, "DTE has not yet bind with DCE", err);
esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent);
/* Set PDP Context */
MODEM_CHECK(dce->define_pdp_context(dce, 1, "IP", CONFIG_EXAMPLE_COMPONENT_MODEM_APN) == ESP_OK, "set MODEM APN failed", err);
/* Enter PPP mode */
MODEM_CHECK(dte->change_mode(dte, MODEM_PPP_MODE) == ESP_OK, "enter ppp mode failed", err);
/* post PPP mode started event */
esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_MODEM_EVENT_PPP_START, NULL, 0, 0);
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_stop_ppp(modem_dte_t *dte)
{
modem_dce_t *dce = dte->dce;
MODEM_CHECK(dce, "DTE has not yet bind with DCE", err);
esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent);
/* Enter command mode */
MODEM_CHECK(dte->change_mode(dte, MODEM_COMMAND_MODE) == ESP_OK, "enter command mode failed", err);
/* post PPP mode stopped event */
esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_MODEM_EVENT_PPP_STOP, NULL, 0, 0);
/* Hang up */
MODEM_CHECK(dce->hang_up(dce) == ESP_OK, "hang up failed", err);
/* wait for the PPP mode to exit gracefully */
if (xSemaphoreTake(esp_dte->exit_sem, pdMS_TO_TICKS(20000)) != pdTRUE) {
ESP_LOGW(MODEM_TAG, "Failed to exit the PPP mode gracefully");
}
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_notify_ppp_netif_closed(modem_dte_t *dte)
{
esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent);
return xSemaphoreGive(esp_dte->exit_sem) == pdTRUE ? ESP_OK : ESP_FAIL;
}

View File

@ -1,104 +0,0 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include "esp_netif.h"
#include "esp_netif_ppp.h"
#include "esp_modem.h"
#include "esp_modem_netif.h"
#include "esp_log.h"
static const char *TAG = "esp-modem-compat";
static void on_modem_compat_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
int32_t compat_event_id = MODEM_EVENT_UNKNOWN;
switch (event_id) {
case ESP_MODEM_EVENT_PPP_START:
compat_event_id = MODEM_EVENT_PPP_START;
break;
case ESP_MODEM_EVENT_PPP_STOP:
compat_event_id = MODEM_EVENT_PPP_STOP;
break;
default:
break;
}
esp_event_post(ESP_MODEM_EVENT, compat_event_id, NULL, 0, 0);
}
static void on_ip_event(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ESP_LOGI(TAG, "IP event! %d", event_id);
if (event_id == IP_EVENT_PPP_GOT_IP) {
esp_netif_dns_info_t dns_info;
ppp_client_ip_info_t ipinfo = {0};
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
esp_netif_t *netif = event->esp_netif;
ipinfo.ip.addr = event->ip_info.ip.addr;
ipinfo.gw.addr = event->ip_info.gw.addr;
ipinfo.netmask.addr = event->ip_info.netmask.addr;
esp_netif_get_dns_info(netif, 0, &dns_info);
ipinfo.ns1.addr = dns_info.ip.u_addr.ip4.addr;
ipinfo.ns2.addr = dns_info.ip.u_addr.ip4.addr;
esp_event_post(ESP_MODEM_EVENT, MODEM_EVENT_PPP_CONNECT, &ipinfo, sizeof(ipinfo), 0);
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
esp_event_post(ESP_MODEM_EVENT, MODEM_EVENT_PPP_DISCONNECT, NULL, 0, 0);
}
}
esp_err_t esp_modem_add_event_handler(modem_dte_t *dte, esp_event_handler_t handler, void *handler_args)
{
// event loop has to be created when using this API -- create and ignore failure if already created
esp_event_loop_create_default();
ESP_ERROR_CHECK(esp_event_handler_register(ESP_MODEM_EVENT, MODEM_EVENT_PPP_START, handler, handler_args));
ESP_ERROR_CHECK(esp_event_handler_register(ESP_MODEM_EVENT, MODEM_EVENT_PPP_CONNECT, handler, handler_args));
ESP_ERROR_CHECK(esp_event_handler_register(ESP_MODEM_EVENT, MODEM_EVENT_PPP_DISCONNECT, handler, handler_args));
ESP_ERROR_CHECK(esp_event_handler_register(ESP_MODEM_EVENT, MODEM_EVENT_PPP_STOP, handler, handler_args));
return esp_modem_set_event_handler(dte, on_modem_compat_handler, ESP_EVENT_ANY_ID, handler_args);
}
esp_err_t esp_modem_setup_ppp(modem_dte_t *dte)
{
#if CONFIG_LWIP_PPP_PAP_SUPPORT && defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME) && defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD)
esp_netif_auth_type_t auth_type = NETIF_PPP_AUTHTYPE_PAP;
#elif CONFIG_LWIP_PPP_CHAP_SUPPORT && defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME) && defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD)
esp_netif_auth_type_t auth_type = NETIF_PPP_AUTHTYPE_CHAP;
#elif defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME) && defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD)
#error "Unsupported AUTH Negotiation while AUTH_USERNAME and PASSWORD defined"
#endif
// Init netif object
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_PPP();
esp_netif_t *esp_netif = esp_netif_new(&cfg);
assert(esp_netif);
// event loop has to be created when using this API -- create and ignore failure if already created
esp_event_loop_create_default();
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event, NULL));
#if defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME) && defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD)
esp_netif_ppp_set_auth(esp_netif, auth_type, CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME, CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD);
#endif
void *modem_netif_adapter = esp_modem_netif_setup(dte);
esp_modem_netif_set_default_handlers(modem_netif_adapter, esp_netif);
/* attach the modem to the network interface */
return esp_netif_attach(esp_netif, modem_netif_adapter);
}
esp_err_t esp_modem_exit_ppp(modem_dte_t *dte)
{
// Note: A minor memory leak is expected when using esp-modem-compat
return esp_modem_stop_ppp(dte);
}

View File

@ -1,381 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include "esp_log.h"
#include "esp_modem_dce_service.h"
static const char *DCE_TAG = "dce_service";
/**
* @brief Macro defined for error checking
*
*/
#define DCE_CHECK(a, str, goto_tag, ...) \
do \
{ \
if (!(a)) \
{ \
ESP_LOGE(DCE_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
goto goto_tag; \
} \
} while (0)
esp_err_t esp_modem_dce_handle_response_default(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;
}
/**
* @brief Handle response from AT+CSQ (Get signal quality)
*
*/
static esp_err_t esp_modem_dce_handle_csq(modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
esp_modem_dce_t *esp_dce = __containerof(dce, esp_modem_dce_t, parent);
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, "+CSQ", strlen("+CSQ"))) {
/* store value of rssi and ber */
uint32_t **csq = esp_dce->priv_resource;
/* +CSQ: <rssi>,<ber> */
sscanf(line, "%*s%d,%d", csq[0], csq[1]);
err = ESP_OK;
}
return err;
}
/**
* @brief Handle response from AT+CBC (Get battery status)
*
*/
static esp_err_t esp_modem_dce_handle_cbc(modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
esp_modem_dce_t *esp_dce = __containerof(dce, esp_modem_dce_t, parent);
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, "+CBC", strlen("+CBC"))) {
/* store value of bcs, bcl, voltage */
uint32_t **cbc = esp_dce->priv_resource;
/* +CBC: <bcs>,<bcl>,<voltage> */
sscanf(line, "%*s%d,%d,%d", cbc[0], cbc[1], cbc[2]);
err = ESP_OK;
}
return err;
}
esp_err_t esp_modem_dce_handle_exit_data_mode(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_NO_CARRIER)) {
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;
}
esp_err_t esp_modem_dce_handle_atd_ppp(modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_CONNECT)) {
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;
}
/**
* @brief Handle response from AT+CGMM (Get DCE module name)
*
*/
static esp_err_t esp_modem_dce_handle_cgmm(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 {
int len = snprintf(dce->name, MODEM_MAX_NAME_LENGTH, "%s", line);
if (len > 2) {
/* Strip "\r\n" */
strip_cr_lf_tail(dce->name, len);
err = ESP_OK;
}
}
return err;
}
/**
* @brief Handle response from AT+CGSN (Get DCE module IMEI number)
*
*/
static esp_err_t esp_modem_dce_handle_cgsn(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 {
int len = snprintf(dce->imei, MODEM_IMEI_LENGTH + 1, "%s", line);
if (len > 2) {
/* Strip "\r\n" */
strip_cr_lf_tail(dce->imei, len);
err = ESP_OK;
}
}
return err;
}
/**
* @brief Handle response from AT+CIMI (Get DCE module IMSI number)
*
*/
static esp_err_t esp_modem_dce_handle_cimi(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 {
int len = snprintf(dce->imsi, MODEM_IMSI_LENGTH + 1, "%s", line);
if (len > 2) {
/* Strip "\r\n" */
strip_cr_lf_tail(dce->imsi, len);
err = ESP_OK;
}
}
return err;
}
/**
* @brief Handle response from AT+COPS? (Get Operator's name)
*
*/
static esp_err_t esp_modem_dce_handle_cops(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, "+COPS", strlen("+COPS"))) {
/* there might be some random spaces in operator's name, we can not use sscanf to parse the result */
/* strtok will break the string, we need to create a copy */
size_t len = strlen(line);
char *line_copy = malloc(len + 1);
strcpy(line_copy, line);
/* +COPS: <mode>[, <format>[, <oper>[, <Act>]]] */
char *str_ptr = NULL;
char *p[5];
uint8_t i = 0;
/* strtok will broke string by replacing delimiter with '\0' */
p[i] = strtok_r(line_copy, ",", &str_ptr);
while (p[i]) {
p[++i] = strtok_r(NULL, ",", &str_ptr);
}
if (i >= 3) {
int len = snprintf(dce->oper, MODEM_MAX_OPERATOR_LENGTH, "%s", p[2]);
if (len > 2) {
/* Strip "\r\n" */
strip_cr_lf_tail(dce->oper, len);
err = ESP_OK;
}
}
if (i >= 4) {
dce->act = (uint8_t)strtol(p[3], NULL, 0);
}
free(line_copy);
}
return err;
}
esp_err_t esp_modem_dce_sync(modem_dce_t *dce)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = esp_modem_dce_handle_response_default;
DCE_CHECK(dte->send_cmd(dte, "AT\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "sync failed", err);
ESP_LOGD(DCE_TAG, "sync ok");
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_echo(modem_dce_t *dce, bool on)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = esp_modem_dce_handle_response_default;
if (on) {
DCE_CHECK(dte->send_cmd(dte, "ATE1\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "enable echo failed", err);
ESP_LOGD(DCE_TAG, "enable echo ok");
} else {
DCE_CHECK(dte->send_cmd(dte, "ATE0\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "disable echo failed", err);
ESP_LOGD(DCE_TAG, "disable echo ok");
}
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_store_profile(modem_dce_t *dce)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = esp_modem_dce_handle_response_default;
DCE_CHECK(dte->send_cmd(dte, "AT&W\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "save settings failed", err);
ESP_LOGD(DCE_TAG, "save settings ok");
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_set_flow_ctrl(modem_dce_t *dce, modem_flow_ctrl_t flow_ctrl)
{
modem_dte_t *dte = dce->dte;
char command[16];
int len = snprintf(command, sizeof(command), "AT+IFC=%d,%d\r", dte->flow_ctrl, flow_ctrl);
DCE_CHECK(len < sizeof(command), "command too long: %s", err, command);
dce->handle_line = esp_modem_dce_handle_response_default;
DCE_CHECK(dte->send_cmd(dte, command, MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "set flow control failed", err);
ESP_LOGD(DCE_TAG, "set flow control ok");
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_define_pdp_context(modem_dce_t *dce, uint32_t cid, const char *type, const char *apn)
{
modem_dte_t *dte = dce->dte;
char command[64];
int len = snprintf(command, sizeof(command), "AT+CGDCONT=%d,\"%s\",\"%s\"\r", cid, type, apn);
DCE_CHECK(len < sizeof(command), "command too long: %s", err, command);
dce->handle_line = esp_modem_dce_handle_response_default;
DCE_CHECK(dte->send_cmd(dte, command, MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "define pdp context failed", err);
ESP_LOGD(DCE_TAG, "define pdp context ok");
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_get_signal_quality(modem_dce_t *dce, uint32_t *rssi, uint32_t *ber)
{
modem_dte_t *dte = dce->dte;
esp_modem_dce_t *esp_dce = __containerof(dce, esp_modem_dce_t, parent);
uint32_t *resource[2] = {rssi, ber};
esp_dce->priv_resource = resource;
dce->handle_line = esp_modem_dce_handle_csq;
DCE_CHECK(dte->send_cmd(dte, "AT+CSQ\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "inquire signal quality failed", err);
ESP_LOGD(DCE_TAG, "inquire signal quality ok");
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_get_battery_status(modem_dce_t *dce, uint32_t *bcs, uint32_t *bcl, uint32_t *voltage)
{
modem_dte_t *dte = dce->dte;
esp_modem_dce_t *esp_dce = __containerof(dce, esp_modem_dce_t, parent);
uint32_t *resource[3] = {bcs, bcl, voltage};
esp_dce->priv_resource = resource;
dce->handle_line = esp_modem_dce_handle_cbc;
DCE_CHECK(dte->send_cmd(dte, "AT+CBC\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "inquire battery status failed", err);
ESP_LOGD(DCE_TAG, "inquire battery status ok");
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_get_module_name(modem_dce_t *dce)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = esp_modem_dce_handle_cgmm;
DCE_CHECK(dte->send_cmd(dte, "AT+CGMM\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "get module name failed", err);
ESP_LOGD(DCE_TAG, "get module name ok");
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_get_imei_number(modem_dce_t *dce)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = esp_modem_dce_handle_cgsn;
DCE_CHECK(dte->send_cmd(dte, "AT+CGSN\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "get imei number failed", err);
ESP_LOGD(DCE_TAG, "get imei number ok");
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_get_imsi_number(modem_dce_t *dce)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = esp_modem_dce_handle_cimi;
DCE_CHECK(dte->send_cmd(dte, "AT+CIMI\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "get imsi number failed", err);
ESP_LOGD(DCE_TAG, "get imsi number ok");
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_get_operator_name(modem_dce_t *dce)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = esp_modem_dce_handle_cops;
DCE_CHECK(dte->send_cmd(dte, "AT+COPS?\r", MODEM_COMMAND_TIMEOUT_OPERATOR) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "get network operator failed", err);
ESP_LOGD(DCE_TAG, "get network operator ok");
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_hang_up(modem_dce_t *dce)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = esp_modem_dce_handle_response_default;
DCE_CHECK(dte->send_cmd(dte, "ATH\r", MODEM_COMMAND_TIMEOUT_HANG_UP) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "hang up failed", err);
ESP_LOGD(DCE_TAG, "hang up ok");
return ESP_OK;
err:
return ESP_FAIL;
}

View File

@ -1,190 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "esp_netif.h"
#include "esp_netif_ppp.h"
#include "esp_modem.h"
#include "esp_log.h"
static const char *TAG = "esp-modem-netif";
/**
* @brief ESP32 Modem handle to be used as netif IO object
*/
typedef struct esp_modem_netif_driver_s {
esp_netif_driver_base_t base; /*!< base structure reserved as esp-netif driver */
modem_dte_t *dte; /*!< ptr to the esp_modem objects (DTE) */
} esp_modem_netif_driver_t;
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
modem_dte_t *dte = arg;
if (event_id < NETIF_PP_PHASE_OFFSET) {
ESP_LOGI(TAG, "PPP state changed event %d", event_id);
// only notify the modem on state/error events, ignoring phase transitions
esp_modem_notify_ppp_netif_closed(dte);
}
}
/**
* @brief Transmit function called from esp_netif to output network stack data
*
* Note: This API has to conform to esp-netif transmit prototype
*
* @param h Opaque pointer representing esp-netif driver, esp_dte in this case of esp_modem
* @param data data buffer
* @param length length of data to send
*
* @return ESP_OK on success
*/
static esp_err_t esp_modem_dte_transmit(void *h, void *buffer, size_t len)
{
modem_dte_t *dte = h;
if (dte->send_data(dte, (const char *)buffer, len) > 0) {
return ESP_OK;
}
return ESP_FAIL;
}
/**
* @brief Post attach adapter for esp-modem
*
* Used to exchange internal callbacks, context between esp-netif nad modem-netif
*
* @param esp_netif handle to esp-netif object
* @param args pointer to modem-netif driver
*
* @return ESP_OK on success, modem-start error code if starting failed
*/
static esp_err_t esp_modem_post_attach_start(esp_netif_t * esp_netif, void * args)
{
esp_modem_netif_driver_t *driver = args;
modem_dte_t *dte = driver->dte;
const esp_netif_driver_ifconfig_t driver_ifconfig = {
.driver_free_rx_buffer = NULL,
.transmit = esp_modem_dte_transmit,
.handle = dte
};
driver->base.netif = esp_netif;
ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig));
// enable both events, so we could notify the modem layer if an error occurred/state changed
esp_netif_ppp_config_t ppp_config = {
.ppp_error_event_enabled = true,
.ppp_phase_event_enabled = true
};
esp_netif_ppp_set_params(esp_netif, &ppp_config);
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, dte));
return esp_modem_start_ppp(dte);
}
/**
* @brief Data path callback from esp-modem to pass data to esp-netif
*
* @param buffer data pointer
* @param len data length
* @param context context data used for esp-modem-netif handle
*
* @return ESP_OK on success
*/
static esp_err_t modem_netif_receive_cb(void *buffer, size_t len, void *context)
{
esp_modem_netif_driver_t *driver = context;
esp_netif_receive(driver->base.netif, buffer, len, NULL);
return ESP_OK;
}
void *esp_modem_netif_setup(modem_dte_t *dte)
{
esp_modem_netif_driver_t *driver = calloc(1, sizeof(esp_modem_netif_driver_t));
if (driver == NULL) {
ESP_LOGE(TAG, "Cannot allocate esp_modem_netif_driver_t");
goto drv_create_failed;
}
esp_err_t err = esp_modem_set_rx_cb(dte, modem_netif_receive_cb, driver);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_modem_set_rx_cb failed with: %d", err);
goto drv_create_failed;
}
driver->base.post_attach = esp_modem_post_attach_start;
driver->dte = dte;
return driver;
drv_create_failed:
return NULL;
}
void esp_modem_netif_teardown(void *h)
{
esp_modem_netif_driver_t *driver = h;
free(driver);
}
esp_err_t esp_modem_netif_clear_default_handlers(void *h)
{
esp_modem_netif_driver_t *driver = h;
esp_err_t ret;
ret = esp_modem_remove_event_handler(driver->dte, esp_netif_action_start);
if (ret != ESP_OK) {
goto clear_event_failed;
}
ret = esp_modem_remove_event_handler(driver->dte, esp_netif_action_stop);
if (ret != ESP_OK) {
goto clear_event_failed;
}
ret = esp_event_handler_unregister(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected);
if (ret != ESP_OK) {
goto clear_event_failed;
}
ret = esp_event_handler_unregister(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected);
if (ret != ESP_OK) {
goto clear_event_failed;
}
return ESP_OK;
clear_event_failed:
ESP_LOGE(TAG, "Failed to unregister event handlers");
return ESP_FAIL;
}
esp_err_t esp_modem_netif_set_default_handlers(void *h, esp_netif_t * esp_netif)
{
esp_modem_netif_driver_t *driver = h;
esp_err_t ret;
ret = esp_modem_set_event_handler(driver->dte, esp_netif_action_start, ESP_MODEM_EVENT_PPP_START, esp_netif);
if (ret != ESP_OK) {
goto set_event_failed;
}
ret = esp_modem_set_event_handler(driver->dte, esp_netif_action_stop, ESP_MODEM_EVENT_PPP_STOP, esp_netif);
if (ret != ESP_OK) {
goto set_event_failed;
}
ret = esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected, esp_netif);
if (ret != ESP_OK) {
goto set_event_failed;
}
ret = esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected, esp_netif);
if (ret != ESP_OK) {
goto set_event_failed;
}
return ESP_OK;
set_event_failed:
ESP_LOGE(TAG, "Failed to register event handlers");
esp_modem_netif_clear_default_handlers(driver);
return ESP_FAIL;
}

View File

@ -1,141 +0,0 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_modem_dce_service.h"
#include "bg96.h"
/**
* @brief This module supports SIM7600 module, which has a very similar interface
* to the BG96, so it just references most of the handlers from BG96 and implements
* only those that differ.
*/
static const char *DCE_TAG = "sim7600";
/**
* @brief Macro defined for error checking
*
*/
#define DCE_CHECK(a, str, goto_tag, ...) \
do \
{ \
if (!(a)) \
{ \
ESP_LOGE(DCE_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
goto goto_tag; \
} \
} while (0)
/**
* @brief Handle response from AT+CBC
*/
static esp_err_t sim7600_handle_cbc(modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
esp_modem_dce_t *esp_modem_dce = __containerof(dce, esp_modem_dce_t, parent);
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, "+CBC", strlen("+CBC"))) {
/* store value of bcs, bcl, voltage */
int32_t **cbc = esp_modem_dce->priv_resource;
int32_t volts = 0, fraction = 0;
/* +CBC: <voltage in Volts> V*/
sscanf(line, "+CBC: %d.%dV", &volts, &fraction);
/* Since the "read_battery_status()" API (besides voltage) returns also values for BCS, BCL (charge status),
* which are not applicable to this modem, we return -1 to indicate invalid value
*/
*cbc[0] = -1; // BCS
*cbc[1] = -1; // BCL
*cbc[2] = volts*1000 + fraction;
err = ESP_OK;
}
return err;
}
/**
* @brief Handle response from AT+CPOF
*/
static esp_err_t sim7600_handle_cpof(modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_OK;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_NO_CARRIER)) {
err = ESP_OK;
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, MODEM_STATE_FAIL);
}
return err;
}
/**
* @brief Get battery status
*
* @param dce Modem DCE object
* @param bcs Battery charge status
* @param bcl Battery connection level
* @param voltage Battery voltage
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t sim7600_get_battery_status(modem_dce_t *dce, uint32_t *bcs, uint32_t *bcl, uint32_t *voltage)
{
modem_dte_t *dte = dce->dte;
esp_modem_dce_t *esp_modem_dce = __containerof(dce, esp_modem_dce_t, parent);
uint32_t *resource[3] = {bcs, bcl, voltage};
esp_modem_dce->priv_resource = resource;
dce->handle_line = sim7600_handle_cbc;
DCE_CHECK(dte->send_cmd(dte, "AT+CBC\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "inquire battery status failed", err);
ESP_LOGD(DCE_TAG, "inquire battery status ok");
return ESP_OK;
err:
return ESP_FAIL;
}
/**
* @brief Set the SIM7600 device to power down mode
*
* @param dce common modem dce object (modem_dce_t)
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t sim7600_power_down(modem_dce_t *dce)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = sim7600_handle_cpof;
DCE_CHECK(dte->send_cmd(dte, "AT+CPOF\r", MODEM_COMMAND_TIMEOUT_POWEROFF) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "power down failed", err);
ESP_LOGD(DCE_TAG, "power down ok");
return ESP_OK;
err:
return ESP_FAIL;
}
/**
* @brief Create and initialize SIM7600 object
*
*/
modem_dce_t *sim7600_init(modem_dte_t *dte)
{
modem_dce_t *dce = bg96_init(dte);
dte->dce->get_battery_status = sim7600_get_battery_status;
dte->dce->power_down = sim7600_power_down;
return dce;
}

View File

@ -1,182 +0,0 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_modem_dce_service.h"
#include "sim800.h"
#define MODEM_RESULT_CODE_POWERDOWN "POWER DOWN"
static const char *DCE_TAG = "sim800";
/**
* @brief Macro defined for error checking
*
*/
#define DCE_CHECK(a, str, goto_tag, ...) \
do \
{ \
if (!(a)) \
{ \
ESP_LOGE(DCE_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
goto goto_tag; \
} \
} while (0)
/**
* @brief Handle response from AT+CPOWD=1
*/
static esp_err_t sim800_handle_power_down(modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_POWERDOWN)) {
err = esp_modem_process_command_done(dce, MODEM_STATE_SUCCESS);
}
return err;
}
/**
* @brief Power down
*
* @param sim800_dce sim800 object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t sim800_power_down(modem_dce_t *dce)
{
modem_dte_t *dte = dce->dte;
dce->handle_line = sim800_handle_power_down;
DCE_CHECK(dte->send_cmd(dte, "AT+CPOWD=1\r", MODEM_COMMAND_TIMEOUT_POWEROFF) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "power down failed", err);
ESP_LOGD(DCE_TAG, "power down ok");
return ESP_OK;
err:
return ESP_FAIL;
}
/**
* @brief Set Working Mode
*
* @param dce Modem DCE object
* @param mode woking mode
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t sim800_set_working_mode(modem_dce_t *dce, modem_mode_t mode)
{
modem_dte_t *dte = dce->dte;
switch (mode) {
case MODEM_COMMAND_MODE:
dce->handle_line = esp_modem_dce_handle_exit_data_mode;
vTaskDelay(pdMS_TO_TICKS(1000)); // spec: 1s delay for the modem to recognize the escape sequence
if (dte->send_cmd(dte, "+++", MODEM_COMMAND_TIMEOUT_MODE_CHANGE) != ESP_OK) {
// "+++" Could fail if we are already in the command mode.
// in that case we ignore the timeout and re-sync the modem
ESP_LOGI(DCE_TAG, "Sending \"+++\" command failed");
dce->handle_line = esp_modem_dce_handle_response_default;
DCE_CHECK(dte->send_cmd(dte, "AT\r", MODEM_COMMAND_TIMEOUT_DEFAULT) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "sync failed", err);
} else {
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "enter command mode failed", err);
}
ESP_LOGD(DCE_TAG, "enter command mode ok");
dce->mode = MODEM_COMMAND_MODE;
break;
case MODEM_PPP_MODE:
dce->handle_line = esp_modem_dce_handle_atd_ppp;
DCE_CHECK(dte->send_cmd(dte, "ATD*99#\r", MODEM_COMMAND_TIMEOUT_MODE_CHANGE) == ESP_OK, "send command failed", err);
if (dce->state != MODEM_STATE_SUCCESS) {
// Initiate PPP mode could fail, if we've already "dialed" the data call before.
// in that case we retry with "ATO" to just resume the data mode
ESP_LOGD(DCE_TAG, "enter ppp mode failed, retry with ATO");
dce->handle_line = esp_modem_dce_handle_atd_ppp;
DCE_CHECK(dte->send_cmd(dte, "ATO\r", MODEM_COMMAND_TIMEOUT_MODE_CHANGE) == ESP_OK, "send command failed", err);
DCE_CHECK(dce->state == MODEM_STATE_SUCCESS, "enter ppp mode failed", err);
}
ESP_LOGD(DCE_TAG, "enter ppp mode ok");
dce->mode = MODEM_PPP_MODE;
break;
default:
ESP_LOGW(DCE_TAG, "unsupported working mode: %d", mode);
goto err;
break;
}
return ESP_OK;
err:
return ESP_FAIL;
}
/**
* @brief Deinitialize SIM800 object
*
* @param dce Modem DCE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on fail
*/
static esp_err_t sim800_deinit(modem_dce_t *dce)
{
esp_modem_dce_t *esp_modem_dce = __containerof(dce, esp_modem_dce_t, parent);
if (dce->dte) {
dce->dte->dce = NULL;
}
free(esp_modem_dce);
return ESP_OK;
}
modem_dce_t *sim800_init(modem_dte_t *dte)
{
DCE_CHECK(dte, "DCE should bind with a DTE", err);
/* malloc memory for esp_modem_dce object */
esp_modem_dce_t *esp_modem_dce = calloc(1, sizeof(esp_modem_dce_t));
DCE_CHECK(esp_modem_dce, "calloc esp_modem_dce_t failed", err);
/* Bind DTE with DCE */
esp_modem_dce->parent.dte = dte;
dte->dce = &(esp_modem_dce->parent);
/* Bind methods */
esp_modem_dce->parent.handle_line = NULL;
esp_modem_dce->parent.sync = esp_modem_dce_sync;
esp_modem_dce->parent.echo_mode = esp_modem_dce_echo;
esp_modem_dce->parent.store_profile = esp_modem_dce_store_profile;
esp_modem_dce->parent.set_flow_ctrl = esp_modem_dce_set_flow_ctrl;
esp_modem_dce->parent.define_pdp_context = esp_modem_dce_define_pdp_context;
esp_modem_dce->parent.hang_up = esp_modem_dce_hang_up;
esp_modem_dce->parent.get_signal_quality = esp_modem_dce_get_signal_quality;
esp_modem_dce->parent.get_battery_status = esp_modem_dce_get_battery_status;
esp_modem_dce->parent.get_operator_name = esp_modem_dce_get_operator_name;
esp_modem_dce->parent.set_working_mode = sim800_set_working_mode;
esp_modem_dce->parent.power_down = sim800_power_down;
esp_modem_dce->parent.deinit = sim800_deinit;
/* Sync between DTE and DCE */
DCE_CHECK(esp_modem_dce_sync(&(esp_modem_dce->parent)) == ESP_OK, "sync failed", err_io);
/* Close echo */
DCE_CHECK(esp_modem_dce_echo(&(esp_modem_dce->parent), false) == ESP_OK, "close echo mode failed", err_io);
/* Get Module name */
DCE_CHECK(esp_modem_dce_get_module_name(&(esp_modem_dce->parent)) == ESP_OK, "get module name failed", err_io);
/* Get IMEI number */
DCE_CHECK(esp_modem_dce_get_imei_number(&(esp_modem_dce->parent)) == ESP_OK, "get imei failed", err_io);
/* Get IMSI number */
DCE_CHECK(esp_modem_dce_get_imsi_number(&(esp_modem_dce->parent)) == ESP_OK, "get imsi failed", err_io);
/* Get operator name */
DCE_CHECK(esp_modem_dce_get_operator_name(&(esp_modem_dce->parent)) == ESP_OK, "get operator name failed", err_io);
return &(esp_modem_dce->parent);
err_io:
free(esp_modem_dce);
dte->dce = NULL;
err:
return NULL;
}

View File

@ -1,104 +0,0 @@
from __future__ import unicode_literals
import os
import threading
import time
import serial
import ttfw_idf
from tiny_test_fw import Utility
class SerialThread(object):
'''
Connect to serial port and fake responses just like from a real modem
'''
# Dictionary for transforming received AT command to expected response
AT_FSM = {b'AT+CGMM': b'0G Dummy Model',
b'AT+CGSN': b'0123456789',
b'AT+CIMI': b'ESP',
b'AT+COPS?': b'+COPS: 0,0,"ESP Network"',
b'AT+CSQ': b'+CSQ: 4,0',
b'AT+CBC': b'+CBC: 0,50',
b'ATD*99***1#': b'CONNECT',
}
def run(self, log_path, exit_event):
with serial.Serial(self.port, 115200) as ser, open(log_path, 'w') as f:
buff = b''
while not exit_event.is_set():
time.sleep(0.1)
buff += ser.read(ser.in_waiting)
if not buff.endswith(b'\r'):
continue # read more because the complete command wasn't yet received
cmd_list = buff.split(b'\r')
buff = b''
for cmd in cmd_list:
if len(cmd) == 0:
continue
snd = self.AT_FSM.get(cmd, b'')
if snd != b'':
snd += b'\n'
snd += b'OK\n'
f.write('Received: {}\n'.format(repr(cmd.decode())))
f.write('Sent: {}\n'.format(repr(snd.decode())))
ser.write(snd)
def __init__(self, port, log_path):
self.port = port
self.exit_event = threading.Event()
self.t = threading.Thread(target=self.run, args=(log_path, self.exit_event,))
self.t.start()
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.exit_event.set()
self.t.join(60)
if self.t.is_alive():
Utility.console_log('The serial thread is still alive', 'O')
@ttfw_idf.idf_example_test(env_tag='Example_PPP')
def test_examples_pppos_client(env, extra_data):
rel_project_path = 'examples/protocols/pppos_client'
dut = env.get_dut('pppos_client', rel_project_path)
project_path = os.path.join(dut.app.get_sdk_path(), rel_project_path)
modem_port = '/dev/ttyUSB{}'.format(0 if dut.port.endswith('1') else 1)
with SerialThread(modem_port, os.path.join(project_path, 'serial.log')):
dut.start_app()
dut.expect_all('pppos_example: Module: 0G Dummy Model',
'pppos_example: Operator: "ESP Network"',
'pppos_example: IMEI: 0123456789',
'pppos_example: IMSI: ESP',
'pppos_example: rssi: 4, ber: 0',
'pppos_example: Battery voltage: 0 mV',
'pppos_example: Modem PPP Started',
timeout=60)
cmd = ('pppd {} 115200 10.0.0.1:10.0.0.2 logfile {} local noauth debug nocrtscts nodetach +ipv6'
''.format(modem_port, os.path.join(project_path, 'ppp.log')))
with ttfw_idf.CustomProcess(cmd, '/dev/null'): # Nothing is printed here
dut.expect_all('pppos_example: Modem Connect to PPP Server',
'pppos_example: IP : 10.0.0.2',
'pppos_example: Netmask : 255.255.255.255',
'pppos_example: Gateway : 10.0.0.1',
'pppos_example: Name Server1: 0.0.0.0',
'pppos_example: Name Server2: 0.0.0.0',
'pppos_example: GOT ip event!!!',
'pppos_example: MQTT other event id: 7',
# There are no fake DNS server and MQTT server set up so the example fails at this point
'esp-tls: couldn\'t get hostname',
'MQTT_CLIENT: Error transport connect',
'pppos_example: MQTT_EVENT_ERROR',
'pppos_example: MQTT_EVENT_DISCONNECTED')
if __name__ == '__main__':
test_examples_pppos_client()

View File

@ -1,2 +0,0 @@
idf_component_register(SRCS "pppos_client_main.c"
INCLUDE_DIRS ".")

View File

@ -1,139 +0,0 @@
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_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
config EXAMPLE_UART_ISR_IN_RAM
bool "Use UART ISR in RAM"
default n
select UART_ISR_IN_IRAM
help
Enable placing UART ISR to IRAM.
This options is useful if PPPoS client needs to perform
flash operations (e.g. OTA) while keeping the network operational.
config EXAMPLE_LCP_ECHO
bool "Enable LCP ECHO"
default n
select LWIP_ENABLE_LCP_ECHO
help
Enable this option to make use of LCP keepalive using
LCP_ECHO_INTERVAL and LCP_MAXECHOFAILS to default values
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 3072
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_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

View File

@ -1,328 +0,0 @@
/* 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"
#include "sim800.h"
#include "bg96.h"
#include "sim7600.h"
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io"
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(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(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 (100)
static esp_err_t example_send_message_text(modem_dce_t *dce, const char *phone_num, const char *text)
{
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, "Unknown 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 = *(esp_netif_t**)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));
}
}
void app_main(void)
{
#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;
#elif !defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_NONE)
#error "Unsupported AUTH Negotiation"
#endif
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();
/* create dte object */
esp_modem_dte_config_t config = ESP_MODEM_DTE_DEFAULT_CONFIG();
/* setup UART specific configuration based on kconfig options */
config.tx_io_num = CONFIG_EXAMPLE_MODEM_UART_TX_PIN;
config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
config.rts_io_num = CONFIG_EXAMPLE_MODEM_UART_RTS_PIN;
config.cts_io_num = CONFIG_EXAMPLE_MODEM_UART_CTS_PIN;
config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
config.event_task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE;
config.event_task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY;
config.dte_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2;
modem_dte_t *dte = esp_modem_dte_init(&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_config_t cfg = ESP_NETIF_DEFAULT_PPP();
esp_netif_t *esp_netif = esp_netif_new(&cfg);
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, 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))
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));
}

View File

@ -1 +0,0 @@
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y

View File

@ -1,7 +0,0 @@
# 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