mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-16 03:52:13 +02:00
esp_modem: Moved to component folder
This commit is contained in:
committed by
David Cermak
parent
61f264f97a
commit
90641c89eb
90
components/esp_modem/.gitignore
vendored
Normal file
90
components/esp_modem/.gitignore
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
.config
|
||||
*.o
|
||||
*.pyc
|
||||
|
||||
# gtags
|
||||
GTAGS
|
||||
GRTAGS
|
||||
GPATH
|
||||
|
||||
# emacs
|
||||
.dir-locals.el
|
||||
|
||||
# emacs temp file suffixes
|
||||
*~
|
||||
.#*
|
||||
\#*#
|
||||
|
||||
# eclipse setting
|
||||
.settings
|
||||
|
||||
# MacOS directory files
|
||||
.DS_Store
|
||||
|
||||
# Components Unit Test Apps files
|
||||
components/**/build
|
||||
components/**/sdkconfig
|
||||
components/**/sdkconfig.old
|
||||
|
||||
# Example project files
|
||||
examples/**/sdkconfig
|
||||
examples/**/sdkconfig.old
|
||||
examples/**/build
|
||||
|
||||
# Doc build artifacts
|
||||
docs/_build/
|
||||
docs/doxygen_sqlite3.db
|
||||
|
||||
# Downloaded font files
|
||||
docs/_static/DejaVuSans.ttf
|
||||
docs/_static/NotoSansSC-Regular.otf
|
||||
|
||||
# Unit test app files
|
||||
tools/unit-test-app/sdkconfig
|
||||
tools/unit-test-app/sdkconfig.old
|
||||
tools/unit-test-app/build
|
||||
tools/unit-test-app/builds
|
||||
tools/unit-test-app/output
|
||||
tools/unit-test-app/test_configs
|
||||
|
||||
# Unit Test CMake compile log folder
|
||||
log_ut_cmake
|
||||
|
||||
# test application build files
|
||||
tools/test_apps/**/build
|
||||
tools/test_apps/**/sdkconfig
|
||||
tools/test_apps/**/sdkconfig.old
|
||||
|
||||
# IDF monitor test
|
||||
tools/test_idf_monitor/outputs
|
||||
|
||||
TEST_LOGS
|
||||
|
||||
# gcov coverage reports
|
||||
*.gcda
|
||||
*.gcno
|
||||
coverage.info
|
||||
coverage_report/
|
||||
|
||||
test_multi_heap_host
|
||||
|
||||
# VS Code Settings
|
||||
.vscode/
|
||||
|
||||
# VIM files
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Clion IDE CMake build & config
|
||||
.idea/
|
||||
cmake-build-*/
|
||||
|
||||
# Results for the checking of the Python coding style and static analysis
|
||||
.mypy_cache
|
||||
flake8_output.txt
|
||||
|
||||
# ESP-IDF default build directory name
|
||||
build
|
||||
|
||||
# lock files for examples and components
|
||||
dependencies.lock
|
39
components/esp_modem/CMakeLists.txt
Normal file
39
components/esp_modem/CMakeLists.txt
Normal file
@ -0,0 +1,39 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
set(platform_srcs src/esp_modem_primitives_linux.cpp
|
||||
src/esp_modem_uart_linux.cpp
|
||||
src/esp_modem_netif_linux.cpp)
|
||||
set(dependencies esp_system_protocols_linux)
|
||||
else()
|
||||
set(platform_srcs src/esp_modem_primitives_freertos.cpp
|
||||
src/esp_modem_uart.cpp
|
||||
src/esp_modem_term_uart.cpp
|
||||
src/esp_modem_netif.cpp)
|
||||
set(dependencies driver)
|
||||
endif()
|
||||
|
||||
set(srcs ${platform_srcs}
|
||||
"src/esp_modem_dte.cpp"
|
||||
"src/esp_modem_dce.cpp"
|
||||
"src/esp_modem_api.cpp"
|
||||
"src/esp_modem_c_api.cpp"
|
||||
"src/esp_modem_factory.cpp"
|
||||
"src/esp_modem_cmux.cpp"
|
||||
"src/esp_modem_command_library.cpp"
|
||||
"src/esp_modem_term_fs.cpp"
|
||||
"src/esp_modem_modules.cpp")
|
||||
|
||||
set(include_dirs "include")
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS private_include
|
||||
REQUIRES ${dependencies})
|
||||
|
||||
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
# This is needed for ESP_LOGx() macros, as integer formats differ on ESP32(..) and x64
|
||||
set_target_properties(${COMPONENT_LIB} PROPERTIES COMPILE_FLAGS -Wno-format)
|
||||
endif()
|
202
components/esp_modem/LICENSE
Normal file
202
components/esp_modem/LICENSE
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
19
components/esp_modem/README.md
Normal file
19
components/esp_modem/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# ESP MODEM
|
||||
|
||||
The `esp-modem` component is a managed component for `esp-idf` that could be used for communication with GSM/LTE modems
|
||||
that support AT commands and PPP protocol as a network interface.
|
||||
|
||||
## Examples
|
||||
|
||||
Get started with one of the examples:
|
||||
* `examples/pppos_client` -- simple client implemented in C
|
||||
* `examples/modem_console` -- C++ example implementing simple terminal console with DCE commands
|
||||
* `examples/ap_to_pppos` -- this example focuses on the network connectivity of the esp-modem and provides a WiFi AP
|
||||
that forwards packets (and uses NAT) to and from the PPPoS connection.
|
||||
* `examples/simple_cmux_client` -- this example sets up the CMUX mode to talk to the modem using AT commands
|
||||
with simultaneously maintaining active network connection.
|
||||
|
||||
## Documentation
|
||||
|
||||
* Continue with esp-modem [brief overview](docs/README.md)
|
||||
* View the full [html documentation ](docs/html/index.html)
|
BIN
components/esp_modem/docs/CMux_collaboration.png
Normal file
BIN
components/esp_modem/docs/CMux_collaboration.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
components/esp_modem/docs/DCE_DTE_collaboration.png
Normal file
BIN
components/esp_modem/docs/DCE_DTE_collaboration.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 139 KiB |
2525
components/esp_modem/docs/Doxyfile
Normal file
2525
components/esp_modem/docs/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
79
components/esp_modem/docs/README.md
Normal file
79
components/esp_modem/docs/README.md
Normal file
@ -0,0 +1,79 @@
|
||||
# ESP MODEM
|
||||
|
||||
This component is used to communicate with modems in the command mode (using AT commands), as well as the data mode
|
||||
(over PPPoS protocol).
|
||||
The modem device is modeled with a DCE (Data Communication Equipment) object, which is composed of:
|
||||
* DTE (Data Terminal Equipment), which abstracts the terminal (currently only UART implemented).
|
||||
* PPP Netif representing a network interface communicating with the DTE using PPP protocol.
|
||||
* Module abstracting the specific device model and its commands.
|
||||
|
||||
```
|
||||
+-----+
|
||||
| DTE |--+
|
||||
+-----+ | +-------+
|
||||
+-->| DCE |
|
||||
+-------+ | |o--- set_mode(command/data)
|
||||
| Module|--->| |
|
||||
+-------+ | |o--- send_commands
|
||||
+->| |
|
||||
+------+ | +-------+
|
||||
| PPP |--+
|
||||
| netif|------------------> network events
|
||||
+------+
|
||||
```
|
||||
|
||||
## Modem components
|
||||
### DCE
|
||||
|
||||
This is the basic operational unit of the esp_modem component, abstracting a specific module in software,
|
||||
which is basically configured by
|
||||
* the I/O communication media (UART), defined by the DTE configuration
|
||||
* the specific command library supported by the device model, defined with the module type
|
||||
* network interface configuration (PPPoS config in lwip)
|
||||
|
||||
After the object is created, the application interaction with the DCE is in
|
||||
* issuing specific commands to the modem
|
||||
* switching between data and command mode
|
||||
|
||||
### DTE
|
||||
Is an abstraction of the connected interface. Current implementation supports only UART
|
||||
|
||||
### PPP
|
||||
|
||||
Is used to connect the specific network interface to the modem data mode. Currently implementation supports only PPPoS protocol.
|
||||
|
||||
### Module
|
||||
|
||||
Abstraction of the specific modem device. Currently the component supports SIM800, BG96, SIM7600.
|
||||
|
||||
## Use cases
|
||||
|
||||
Users could interact with the esp-modem using the DCE's interface, to basically
|
||||
* Switch between command and data mode to connect to the internet via cellular network.
|
||||
* Send various commands to the device (e.g. send SMS)
|
||||
|
||||
The applications typically register handlers for network events to receive notification on the network availability and
|
||||
IP address changes.
|
||||
|
||||
Common use cases of the esp-modem are also listed as the examples:
|
||||
* `examples/pppos_client` -- simple client which reads some module properties and switches to the data mode to connect to a public mqtt broker.
|
||||
* `examples/modem_console` -- is an example to exercise all possible modules commands in a console application.
|
||||
* `examples/ap_to_pppos` -- this example focuses on the network connectivity of the esp-modem and provides a WiFi AP
|
||||
that forwards packets (and uses NAT) to and from the PPPoS connection.
|
||||
|
||||
## Extensibility
|
||||
|
||||
### CMUX
|
||||
|
||||
Implementation of virtual terminals is an experimental feature, which allows users to also issue commands in the data mode,
|
||||
after creating multiple virtual terminals, designating some of them solely to the data mode, while other to command mode.
|
||||
|
||||
### DTE's
|
||||
|
||||
Currently we support only UART, but modern modules support other communication interfaces, such as USB, SPI.
|
||||
|
||||
### Other devices
|
||||
|
||||
Adding a new device is a must-have requirement for the esp-component. Different modules support different commands,
|
||||
or some commands might have a different implementation. Adding a new device means to provide a new implementation
|
||||
as a class derived from `GenericModule`, where we could add new commands or modify the existing ones.
|
48
components/esp_modem/docs/advanced_api.rst
Normal file
48
components/esp_modem/docs/advanced_api.rst
Normal file
@ -0,0 +1,48 @@
|
||||
Advanced esp-modem use cases
|
||||
============================
|
||||
|
||||
This chapter outlines basic extensibility of the esp-modem component.
|
||||
|
||||
.. _dce_factory:
|
||||
|
||||
Custom instantiation with DCE factory
|
||||
--------------------------------------
|
||||
|
||||
It is possible to create a modem handle in many different ways:
|
||||
|
||||
- Build a DCE on top a generic module, user defined module or build the module only (in case the application will only use AT command interface)
|
||||
- Create the DCE as a shared, unique or a vanilla pointer
|
||||
- Create a generic DCE or a templated DCE_T of a specific module (this could be one of the supported modules or a user defined module)
|
||||
|
||||
All the functionality is provided by the DCE factory
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_DCE_FACTORY
|
||||
:members:
|
||||
|
||||
|
||||
Create custom module
|
||||
--------------------
|
||||
|
||||
Creating a custom module is necessary if the application needs to use a specific device that is not supported
|
||||
and their commands differ from any of the supported devices. In this case it is recommended to define a new class
|
||||
representing this specific device and derive from the :cpp:class:`GenericModule`. In order to instantiate
|
||||
the appropriate DCE of this module, application could use :ref:`the DCE factory<dce_factory>`, but build the DCE with
|
||||
the specific module, using :cpp:func:`esp_modem::dce_factory::Factory::build`.
|
||||
|
||||
Please refer to the implementation of the existing modules.
|
||||
|
||||
Please note that the ``modem_console`` example defines a trivial custom modem DCE which overrides one command,
|
||||
for demonstration purposes only.
|
||||
|
||||
|
||||
Create new communication interface
|
||||
----------------------------------
|
||||
|
||||
In order to connect to a device using an unsupported interface (e.g. SPI or I2C), it is necessary to implement
|
||||
a custom DTE object and supply it into :ref:`the DCE factory<dce_factory>`. The DCE is typically created in two steps:
|
||||
|
||||
- Define and create the corresponding terminal, which can communicate on the custom interface. This terminal should support basic IO methods defined in :cpp:class:`esp_modem::Terminal` and derive from it.
|
||||
- Create the DTE which uses the custom Terminal
|
||||
|
||||
Please refer to the implementation of the existing UART DTE.
|
||||
|
54
components/esp_modem/docs/api_docs.rst
Normal file
54
components/esp_modem/docs/api_docs.rst
Normal file
@ -0,0 +1,54 @@
|
||||
.. _c_api:
|
||||
|
||||
API Guide for C interface
|
||||
=========================
|
||||
|
||||
|
||||
C API is very simple and consist of these two basic parts:
|
||||
|
||||
- :ref:`lifecycle_api`
|
||||
- :ref:`modem_commands`
|
||||
|
||||
Typical application workflow is to:
|
||||
|
||||
- Create a DCE instance (using :cpp:func:`esp_modem_new`)
|
||||
- Call specific functions to issue AT commands (:ref:`modem_commands`)
|
||||
- Switch to the data mode (using :cpp:func:`esp_modem_set_mode`)
|
||||
- Perform desired network operations (using standard networking API, unrelated to ESP-MODEM)
|
||||
- Optionally switch back to command mode (again :cpp:func:`esp_modem_set_mode`)
|
||||
- Destroy the DCE handle (sing :cpp:func:`esp_modem_destroy`)
|
||||
|
||||
Note the configuration structures for DTE and DCE, needed for creating the DCE instance, is documented in :ref:`api_config`
|
||||
|
||||
.. _lifecycle_api:
|
||||
|
||||
Lifecycle API
|
||||
-------------
|
||||
|
||||
These functions are used to create, destroy and set modem working mode.
|
||||
|
||||
- :cpp:func:`esp_modem_new`
|
||||
- :cpp:func:`esp_modem_destroy`
|
||||
- :cpp:func:`esp_modem_set_mode`
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_C_API
|
||||
|
||||
|
||||
.. _modem_commands:
|
||||
|
||||
Modem commands
|
||||
--------------
|
||||
|
||||
These functions are the actual commands to communicate with the modem using AT command interface.
|
||||
|
||||
|
||||
.. doxygenfile:: esp_modem_api_commands.h
|
||||
|
||||
.. _api_config:
|
||||
|
||||
Configuration structures
|
||||
------------------------
|
||||
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_CONFIG
|
||||
:members:
|
27
components/esp_modem/docs/conf.py
Normal file
27
components/esp_modem/docs/conf.py
Normal file
@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# English Language RTD & Sphinx config file
|
||||
#
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# General information about the project.
|
||||
project = u'esp-modem'
|
||||
copyright = u'2016 - 2021, Espressif Systems (Shanghai) Co., Ltd'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
language = 'en'
|
||||
|
||||
extensions = ['breathe']
|
||||
|
||||
breathe_projects = {'esp_modem': 'xml'}
|
||||
|
||||
breathe_default_project = "esp_modem"
|
||||
|
||||
source_suffix = ['.rst', '.md']
|
||||
|
||||
source_parsers = {'.md': 'recommonmark.parser.CommonMarkParser', }
|
44
components/esp_modem/docs/cxx_api_docs.rst
Normal file
44
components/esp_modem/docs/cxx_api_docs.rst
Normal file
@ -0,0 +1,44 @@
|
||||
C++ API Documentation
|
||||
=====================
|
||||
|
||||
Similar to the :ref:`c_api`, the basic application workflow consist of
|
||||
|
||||
.. toctree::
|
||||
|
||||
- :ref:`Construction of the DCE<cpp_init>`
|
||||
- :ref:`Switching modes<cpp_mode_switch>`
|
||||
- :ref:`Sending (AT) commands<cpp_modem_commands>`
|
||||
- :ref:`Destroying the DCE<cpp_destroy>`
|
||||
|
||||
.. _cpp_init:
|
||||
|
||||
Create DTE and DCE
|
||||
------------------
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_INIT_DTE
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_INIT_DCE
|
||||
|
||||
|
||||
.. _cpp_mode_switch:
|
||||
|
||||
Mode switching commands
|
||||
-----------------------
|
||||
|
||||
.. doxygenclass:: esp_modem::DCE_T
|
||||
:members:
|
||||
|
||||
.. _cpp_modem_commands:
|
||||
|
||||
Modem commands
|
||||
--------------
|
||||
|
||||
.. include:: cxx_api_links.rst
|
||||
|
||||
.. _cpp_destroy:
|
||||
|
||||
Destroy the DCE
|
||||
---------------
|
||||
|
||||
The DCE object is created as ``std::unique_ptr`` by default and as such doesn't have to be explicitly destroyed.
|
||||
It simply gets destroyed and cleaned-up automatically if the object goes out of the block scope.
|
25
components/esp_modem/docs/cxx_api_links.rst
Normal file
25
components/esp_modem/docs/cxx_api_links.rst
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
- :cpp:func:`esp_modem::DCE::sync`
|
||||
- :cpp:func:`esp_modem::DCE::get_operator_name`
|
||||
- :cpp:func:`esp_modem::DCE::store_profile`
|
||||
- :cpp:func:`esp_modem::DCE::set_pin`
|
||||
- :cpp:func:`esp_modem::DCE::read_pin`
|
||||
- :cpp:func:`esp_modem::DCE::set_echo`
|
||||
- :cpp:func:`esp_modem::DCE::sms_txt_mode`
|
||||
- :cpp:func:`esp_modem::DCE::sms_character_set`
|
||||
- :cpp:func:`esp_modem::DCE::send_sms`
|
||||
- :cpp:func:`esp_modem::DCE::resume_data_mode`
|
||||
- :cpp:func:`esp_modem::DCE::set_pdp_context`
|
||||
- :cpp:func:`esp_modem::DCE::set_command_mode`
|
||||
- :cpp:func:`esp_modem::DCE::set_cmux`
|
||||
- :cpp:func:`esp_modem::DCE::get_imsi`
|
||||
- :cpp:func:`esp_modem::DCE::get_imei`
|
||||
- :cpp:func:`esp_modem::DCE::get_module_name`
|
||||
- :cpp:func:`esp_modem::DCE::set_data_mode`
|
||||
- :cpp:func:`esp_modem::DCE::get_signal_quality`
|
||||
- :cpp:func:`esp_modem::DCE::set_flow_control`
|
||||
- :cpp:func:`esp_modem::DCE::hang_up`
|
||||
- :cpp:func:`esp_modem::DCE::get_battery_status`
|
||||
- :cpp:func:`esp_modem::DCE::power_down`
|
||||
- :cpp:func:`esp_modem::DCE::reset`
|
||||
- :cpp:func:`esp_modem::DCE::set_baud`
|
99
components/esp_modem/docs/esp_modem_api_commands.h
Normal file
99
components/esp_modem/docs/esp_modem_api_commands.h
Normal file
@ -0,0 +1,99 @@
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
|
||||
|
||||
// call parametrs by names for documentation
|
||||
|
||||
|
||||
// --- DCE command documentation starts here ---
|
||||
/**
|
||||
* @brief Sends the initial AT sequence to sync up with the device
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_sync (); /**
|
||||
* @brief Reads the operator name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_operator_name (char* name); /**
|
||||
* @brief Stores current user profile
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_store_profile (); /**
|
||||
* @brief Sets the supplied PIN code
|
||||
* @param[in] pin Pin
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/command_result esp_modem_set_pin (const char* pin); /**
|
||||
* @brief Checks if the SIM needs a PIN
|
||||
* @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_read_pin (bool* pin_ok); /**
|
||||
* @brief Sets echo mode
|
||||
* @param[in] echo_on true if echo mode on (repeats the commands)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_echo (const bool echo_on); /**
|
||||
* @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
|
||||
* @param[in] txt true if txt mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_sms_txt_mode (const bool txt); /**
|
||||
* @brief Sets the default (GSM) charater set
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_sms_character_set (); /**
|
||||
* @brief Sends SMS message in txt mode
|
||||
* @param[in] number Phone number to send the message to
|
||||
* @param[in] message Text message to be sent
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_send_sms (const char* number, const char* message); /**
|
||||
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_resume_data_mode (); /**
|
||||
* @brief Sets php context
|
||||
* @param[in] x PdP context struct to setup modem cellular connection
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_pdp_context (struct PdpContext* x); /**
|
||||
* @brief Switches to the command mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_command_mode (); /**
|
||||
* @brief Switches to the CMUX mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_cmux (); /**
|
||||
* @brief Reads the IMSI number
|
||||
* @param[out] imsi Module's IMSI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_imsi (char* imsi); /**
|
||||
* @brief Reads the IMEI number
|
||||
* @param[out] imei Module's IMEI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_imei (char* imei); /**
|
||||
* @brief Reads the module name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_module_name (char* name); /**
|
||||
* @brief Sets the modem to data mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_data_mode (); /**
|
||||
* @brief Get Signal quality
|
||||
* @param[out] rssi signal strength indication
|
||||
* @param[out] ber channel bit error rate
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_signal_quality (int* rssi, int* ber); /**
|
||||
* @brief Sets HW control flow
|
||||
* @param[in] dce_flow 0=none, 2=RTS hw flow control of DCE
|
||||
* @param[in] dte_flow 0=none, 2=CTS hw flow control of DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_flow_control (int dce_flow, int dte_flow); /**
|
||||
* @brief Hangs up current data call
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_hang_up (); /**
|
||||
* @brief Get voltage levels of modem power up circuitry
|
||||
* @param[out] voltage Current status in mV
|
||||
* @param[out] bcs charge status (-1-Not available, 0-Not charging, 1-Charging, 2-Charging done)
|
||||
* @param[out] bcl 1-100% battery capacity, -1-Not available
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_get_battery_status (int* voltage, int* bcs, int* bcl); /**
|
||||
* @brief Power down the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_power_down (); /**
|
||||
* @brief Reset the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_reset (); /**
|
||||
* @brief Configures the baudrate
|
||||
* @param[in] baud Desired baud rate of the DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result esp_modem_set_baud (int baud);
|
111
components/esp_modem/docs/esp_modem_dce.hpp
Normal file
111
components/esp_modem/docs/esp_modem_dce.hpp
Normal file
@ -0,0 +1,111 @@
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
|
||||
|
||||
// call parametrs by names for documentation
|
||||
|
||||
|
||||
// --- DCE command documentation starts here ---
|
||||
|
||||
class esp_modem::DCE: public DCE_T<GenericModule> {
|
||||
public:
|
||||
using DCE_T<GenericModule>::DCE_T;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sends the initial AT sequence to sync up with the device
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result sync (); /**
|
||||
* @brief Reads the operator name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_operator_name (std::string& name); /**
|
||||
* @brief Stores current user profile
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result store_profile (); /**
|
||||
* @brief Sets the supplied PIN code
|
||||
* @param[in] pin Pin
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/command_result set_pin (const std::string& pin); /**
|
||||
* @brief Checks if the SIM needs a PIN
|
||||
* @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result read_pin (bool& pin_ok); /**
|
||||
* @brief Sets echo mode
|
||||
* @param[in] echo_on true if echo mode on (repeats the commands)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_echo (const bool echo_on); /**
|
||||
* @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
|
||||
* @param[in] txt true if txt mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result sms_txt_mode (const bool txt); /**
|
||||
* @brief Sets the default (GSM) charater set
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result sms_character_set (); /**
|
||||
* @brief Sends SMS message in txt mode
|
||||
* @param[in] number Phone number to send the message to
|
||||
* @param[in] message Text message to be sent
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result send_sms (const std::string& number, const std::string& message); /**
|
||||
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result resume_data_mode (); /**
|
||||
* @brief Sets php context
|
||||
* @param[in] x PdP context struct to setup modem cellular connection
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_pdp_context (PdpContext& x); /**
|
||||
* @brief Switches to the command mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_command_mode (); /**
|
||||
* @brief Switches to the CMUX mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_cmux (); /**
|
||||
* @brief Reads the IMSI number
|
||||
* @param[out] imsi Module's IMSI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_imsi (std::string& imsi); /**
|
||||
* @brief Reads the IMEI number
|
||||
* @param[out] imei Module's IMEI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_imei (std::string& imei); /**
|
||||
* @brief Reads the module name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_module_name (std::string& name); /**
|
||||
* @brief Sets the modem to data mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_data_mode (); /**
|
||||
* @brief Get Signal quality
|
||||
* @param[out] rssi signal strength indication
|
||||
* @param[out] ber channel bit error rate
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_signal_quality (int& rssi, int& ber); /**
|
||||
* @brief Sets HW control flow
|
||||
* @param[in] dce_flow 0=none, 2=RTS hw flow control of DCE
|
||||
* @param[in] dte_flow 0=none, 2=CTS hw flow control of DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_flow_control (int dce_flow, int dte_flow); /**
|
||||
* @brief Hangs up current data call
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result hang_up (); /**
|
||||
* @brief Get voltage levels of modem power up circuitry
|
||||
* @param[out] voltage Current status in mV
|
||||
* @param[out] bcs charge status (-1-Not available, 0-Not charging, 1-Charging, 2-Charging done)
|
||||
* @param[out] bcl 1-100% battery capacity, -1-Not available
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result get_battery_status (int& voltage, int& bcs, int& bcl); /**
|
||||
* @brief Power down the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result power_down (); /**
|
||||
* @brief Reset the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result reset (); /**
|
||||
* @brief Configures the baudrate
|
||||
* @param[in] baud Desired baud rate of the DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ command_result set_baud (int baud);
|
||||
};
|
23
components/esp_modem/docs/generate_docs
Executable file
23
components/esp_modem/docs/generate_docs
Executable file
@ -0,0 +1,23 @@
|
||||
# Cleanup the generated html
|
||||
rm -rf html
|
||||
|
||||
# Cleans example and test build dirs (to reduce the component size before upload)
|
||||
rm -rf ../examples/ap_to_pppos/build/ ../examples/simple_cmux_client/build/ ../examples/pppos_client/build/ ../examples/linux_modem/build/ ../examples/modem_console/build ../test/host_test/build/ ../test/target/build/
|
||||
|
||||
# Generate C++ API header of the DCE
|
||||
cat ../include/generate/esp_modem_command_declare.inc | clang++ -E -P -CC -xc++ -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > esp_modem_dce.hpp
|
||||
|
||||
# Generate C API header of the modem_api.h
|
||||
cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > esp_modem_api_commands.h
|
||||
|
||||
# RST with links to C++ API
|
||||
cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
|
||||
|
||||
# Run doxygen
|
||||
doxygen
|
||||
|
||||
# Generate the docs
|
||||
python -u -m sphinx.cmd.build -b html . html
|
||||
|
||||
# Cleanup the doxygen xml's
|
||||
rm -rf xml
|
11
components/esp_modem/docs/index.rst
Normal file
11
components/esp_modem/docs/index.rst
Normal file
@ -0,0 +1,11 @@
|
||||
ESP-MODEM Programmers manual
|
||||
============================
|
||||
|
||||
.. toctree::
|
||||
|
||||
Brief intro <README>
|
||||
C interface <api_docs>
|
||||
C++ interface <cxx_api_docs>
|
||||
Advanced use cases <advanced_api>
|
||||
Internal design <internal_design>
|
||||
Internal implementation <internal_docs>
|
36
components/esp_modem/docs/internal_design.md
Normal file
36
components/esp_modem/docs/internal_design.md
Normal file
@ -0,0 +1,36 @@
|
||||
# Internal design
|
||||
|
||||
## Design decisions
|
||||
|
||||
* Use C++ with additional C API
|
||||
|
||||
* Use exceptions
|
||||
- Use macro wrapper over `try-catch` blocks when exceptions off (use `abort()` if `THROW()`)
|
||||
|
||||
* Initializes and allocates in the constructor (might throw)
|
||||
- easier code with exceptions ON, with exceptions OFF alloc/init failures are not treated as runtime error (program aborts)
|
||||
- break down long initialization in constructor into more private methods
|
||||
|
||||
* Implements different devices using inheritance from `GenericModule`, which is the most general implementation of a common modem
|
||||
- Internally uses templates with device specialization (modeled as `DCE<SpecificModule>`) which could be used as well for some special cases,
|
||||
such as implantation of a minimal device (ModuleIf), add new AT commands (oOnly in compile time), or using the Module with DTE only (no DCE, no Netif) for sending AT commands without network
|
||||
|
||||
## DCE collaboration model
|
||||
|
||||
The diagram describes how the DCE class collaborates with DTE, PPP and the device abstraction
|
||||
|
||||

|
||||
|
||||
## Terminal inheritance
|
||||
|
||||
Terminal is a class which can read or write data, and can handle callbacks when data are available. UART specialization
|
||||
is provided implementing these method using the uart driver.
|
||||
|
||||
## CMUX terminal
|
||||
|
||||
The below diagram depicts the idea of using CMUX terminal mode using the CMuxInstance class which is a terminal
|
||||
(it implements the basic read/write methods) interfacing arbitrary number of virtual terminals,
|
||||
but at the same time it is also composed of CMux class, which consumes the original terminal and uses its read/write methods
|
||||
to multiplex the terminal.
|
||||
|
||||

|
85
components/esp_modem/docs/internal_docs.rst
Normal file
85
components/esp_modem/docs/internal_docs.rst
Normal file
@ -0,0 +1,85 @@
|
||||
DCE Internal implementation
|
||||
===========================
|
||||
|
||||
This chapter provides a detailed description of the classes and building blocks of the esp-modem component and their responsibilities.
|
||||
|
||||
The esp-modem actually implements the DCE class, which in turn aggregates these thee units:
|
||||
|
||||
- :ref:`DTE<dte_impl>` to communicate with the device on a specific Terminal interface such as UART.
|
||||
- :ref:`Netif<netif_impl>` to provide the network connectivity
|
||||
- :ref:`Module<module_impl>` to define the specific command library
|
||||
|
||||
------------
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_DCE
|
||||
:members:
|
||||
|
||||
.. _dte_impl:
|
||||
|
||||
DTE abstraction
|
||||
---------------
|
||||
|
||||
DTE is a basic unit to talk to the module using a Terminal interface. It also implements and uses the CMUX to multiplex
|
||||
terminals. Besides the DTE documentation, this section also refers to the
|
||||
|
||||
- :ref:`Terminal interface<term_impl>`
|
||||
- :ref:`CMUX implementation<cmux_impl>`
|
||||
|
||||
|
||||
------------
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_DTE
|
||||
:members:
|
||||
|
||||
.. _term_impl:
|
||||
|
||||
Terminal interface
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_TERMINAL
|
||||
:members:
|
||||
|
||||
.. _cmux_impl:
|
||||
|
||||
CMUX implementation
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_CMUX
|
||||
:members:
|
||||
|
||||
.. _netif_impl:
|
||||
|
||||
Netif
|
||||
-----
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_NETIF
|
||||
:members:
|
||||
|
||||
.. _module_impl:
|
||||
|
||||
Module abstraction
|
||||
------------------
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_MODULE
|
||||
:members:
|
||||
|
||||
Command library
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
This is a namespace holding a library of typical AT commands used by supported devices.
|
||||
Please refer to the :ref:`c_api` for the list of supported commands.
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_DCE_COMMAND
|
||||
:members:
|
||||
|
||||
|
||||
Modem types
|
||||
-----------
|
||||
|
||||
.. doxygengroup:: ESP_MODEM_TYPES
|
||||
:members:
|
||||
|
||||
|
||||
|
||||
|
||||
|
8
components/esp_modem/examples/ap_to_pppos/CMakeLists.txt
Normal file
8
components/esp_modem/examples/ap_to_pppos/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
# The following five lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(ap-to-pppos)
|
17
components/esp_modem/examples/ap_to_pppos/README.md
Normal file
17
components/esp_modem/examples/ap_to_pppos/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# AP to PPPoS example
|
||||
|
||||
## Overview
|
||||
|
||||
This example focuses on the networking part, enables forwarding packets between network interfaces. It creates a WiFi soft AP, which uses NAT to forward packets to and from the PPP network
|
||||
interface.
|
||||
|
||||
### Specific network DCE
|
||||
|
||||
Note, that this example could use of a minimal Network DCE, defined in the `network_dce.cpp` file.
|
||||
Please set `EXAMPLE_USE_MINIMAL_DCE` to `y` in order to demonstrate this functionality.
|
||||
|
||||
By default, this example simply connects to the PPP server using a supported device with C-API modem interface.
|
||||
|
||||
This example however, doesn't rely on sending specific AT commands, just the bare minimum to setup the cellular network.
|
||||
Thus, if the `EXAMPLE_USE_MINIMAL_DCE` option is enabled, we directly inherit from the `ModuleIf` and implement only the basic commands.
|
||||
Also, to demonstrate the dce_factory functionality, a new `NetDCE_Factory` is implemented for creating the network module and the DCE.
|
@ -0,0 +1,9 @@
|
||||
if(CONFIG_EXAMPLE_USE_MINIMAL_DCE)
|
||||
set(NETWORK_DCE "network_dce.cpp")
|
||||
else()
|
||||
set(NETWORK_DCE "network_dce.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "ap_to_pppos.c"
|
||||
${NETWORK_DCE}
|
||||
INCLUDE_DIRS ".")
|
@ -0,0 +1,47 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config ESP_WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) for the example to connect to.
|
||||
|
||||
config ESP_WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
|
||||
config ESP_WIFI_CHANNEL
|
||||
int "WiFi Channel"
|
||||
range 1 13
|
||||
default 1
|
||||
help
|
||||
WiFi channel (network channel) for the example to use.
|
||||
|
||||
config ESP_MAX_STA_CONN
|
||||
int "Maximal STA connections"
|
||||
default 4
|
||||
help
|
||||
Max number of the STA connects to AP.
|
||||
|
||||
config EXAMPLE_MODEM_PPP_APN
|
||||
string "Set MODEM APN"
|
||||
default "internet"
|
||||
help
|
||||
Set APN (Access Point Name), a logical name to choose data network
|
||||
|
||||
config EXAMPLE_SIM_PIN
|
||||
string "Set SIM PIN"
|
||||
default "1234"
|
||||
help
|
||||
Pin to unlock the SIM
|
||||
|
||||
config EXAMPLE_USE_MINIMAL_DCE
|
||||
bool "Use minimal network DCE"
|
||||
default n
|
||||
help
|
||||
Define a specific network only DCE class and
|
||||
create it using DCE factory
|
||||
|
||||
endmenu
|
183
components/esp_modem/examples/ap_to_pppos/main/ap_to_pppos.c
Normal file
183
components/esp_modem/examples/ap_to_pppos/main/ap_to_pppos.c
Normal file
@ -0,0 +1,183 @@
|
||||
/* softAP to PPPoS Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "lwip/lwip_napt.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "network_dce.h"
|
||||
|
||||
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
|
||||
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
|
||||
#define EXAMPLE_ESP_WIFI_CHANNEL CONFIG_ESP_WIFI_CHANNEL
|
||||
#define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN
|
||||
|
||||
|
||||
static const char *TAG = "ap_to_pppos";
|
||||
|
||||
static EventGroupHandle_t event_group = NULL;
|
||||
static const int CONNECT_BIT = BIT0;
|
||||
static const int DISCONNECT_BIT = BIT1;
|
||||
|
||||
static void on_ip_event(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == IP_EVENT) {
|
||||
ESP_LOGD(TAG, "IP event! %d", event_id);
|
||||
if (event_id == IP_EVENT_PPP_GOT_IP) {
|
||||
esp_netif_dns_info_t dns_info;
|
||||
|
||||
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
esp_netif_t *netif = event->esp_netif;
|
||||
|
||||
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
||||
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
||||
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
||||
esp_netif_get_dns_info(netif, 0, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
esp_netif_get_dns_info(netif, 1, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||
|
||||
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||
xEventGroupSetBits(event_group, DISCONNECT_BIT);
|
||||
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||
ESP_LOGI(TAG, "GOT IPv6 event!");
|
||||
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
||||
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t set_dhcps_dns(esp_netif_t *netif, uint32_t addr)
|
||||
{
|
||||
esp_netif_dns_info_t dns;
|
||||
dns.ip.u_addr.ip4.addr = addr;
|
||||
dns.ip.type = IPADDR_TYPE_V4;
|
||||
dhcps_offer_t dhcps_dns_value = OFFER_DNS;
|
||||
ESP_ERROR_CHECK(esp_netif_dhcps_option(netif, ESP_NETIF_OP_SET, ESP_NETIF_DOMAIN_NAME_SERVER, &dhcps_dns_value, sizeof(dhcps_dns_value)));
|
||||
ESP_ERROR_CHECK(esp_netif_set_dns_info(netif, ESP_NETIF_DNS_MAIN, &dns));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
|
||||
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
|
||||
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wifi_init_softap(void)
|
||||
{
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&wifi_event_handler,
|
||||
NULL,
|
||||
NULL));
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.ap = {
|
||||
.ssid = EXAMPLE_ESP_WIFI_SSID,
|
||||
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
|
||||
.channel = EXAMPLE_ESP_WIFI_CHANNEL,
|
||||
.password = EXAMPLE_ESP_WIFI_PASS,
|
||||
.max_connection = EXAMPLE_MAX_STA_CONN,
|
||||
.authmode = WIFI_AUTH_WPA_WPA2_PSK
|
||||
},
|
||||
};
|
||||
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
|
||||
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
|
||||
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// Initialize NVS
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
// Initialize esp_netif and default event loop
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
event_group = xEventGroupCreate();
|
||||
|
||||
// Initialize lwip network interface in PPP mode
|
||||
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
|
||||
esp_netif_t *ppp_netif = esp_netif_new(&ppp_netif_config);
|
||||
assert(ppp_netif);
|
||||
|
||||
// Initialize the PPP network and register for IP event
|
||||
ESP_ERROR_CHECK(modem_init_network(ppp_netif));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event, NULL));
|
||||
|
||||
// Start the PPP network and wait for connection
|
||||
modem_start_network();
|
||||
EventBits_t bits;
|
||||
do {
|
||||
bits = xEventGroupWaitBits(event_group, (CONNECT_BIT | DISCONNECT_BIT), pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
if (bits & DISCONNECT_BIT) {
|
||||
ESP_LOGW(TAG, "Modem got disconnected from the PPP server: retrying...");
|
||||
modem_stop_network();
|
||||
modem_start_network();
|
||||
}
|
||||
} while ((bits & CONNECT_BIT) == 0);
|
||||
|
||||
// Initialize the AP and setup the NAT
|
||||
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
|
||||
assert(ap_netif);
|
||||
esp_netif_dns_info_t dns;
|
||||
ESP_ERROR_CHECK(esp_netif_get_dns_info(ppp_netif, ESP_NETIF_DNS_MAIN, &dns));
|
||||
set_dhcps_dns(ap_netif, dns.ip.u_addr.ip4.addr);
|
||||
|
||||
wifi_init_softap();
|
||||
ip_napt_enable(_g_esp_netif_soft_ap_ip.ip.addr, 1);
|
||||
|
||||
// Provide a recovery if disconnection of some kind registered
|
||||
while (true) {
|
||||
bits = xEventGroupWaitBits(event_group, DISCONNECT_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
if (bits & DISCONNECT_BIT) {
|
||||
ESP_LOGW(TAG, "Modem got disconnected from the PPP server: restarting the network...");
|
||||
modem_stop_network();
|
||||
modem_start_network();
|
||||
}
|
||||
}
|
||||
}
|
56
components/esp_modem/examples/ap_to_pppos/main/network_dce.c
Normal file
56
components/esp_modem/examples/ap_to_pppos/main/network_dce.c
Normal file
@ -0,0 +1,56 @@
|
||||
/* softAP to PPPoS Example (network_dce)
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_netif.h"
|
||||
#include "esp_modem_api.h"
|
||||
|
||||
|
||||
static esp_modem_dce_t *dce = NULL;
|
||||
|
||||
|
||||
esp_err_t modem_init_network(esp_netif_t *netif)
|
||||
{
|
||||
// setup the DCE
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
|
||||
dce = esp_modem_new(&dte_config, &dce_config, netif);
|
||||
if (!dce) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// configure the PIN
|
||||
bool pin_ok = false;
|
||||
if (esp_modem_read_pin(dce, &pin_ok) == ESP_OK && pin_ok == false) {
|
||||
if (esp_modem_set_pin(dce, CONFIG_EXAMPLE_SIM_PIN) == ESP_OK) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void modem_deinit_network(void)
|
||||
{
|
||||
if (dce) {
|
||||
esp_modem_destroy(dce);
|
||||
dce = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void modem_start_network()
|
||||
{
|
||||
esp_modem_set_mode(dce, ESP_MODEM_MODE_DATA);
|
||||
}
|
||||
|
||||
void modem_stop_network()
|
||||
{
|
||||
esp_modem_set_mode(dce, ESP_MODEM_MODE_COMMAND);
|
||||
}
|
176
components/esp_modem/examples/ap_to_pppos/main/network_dce.cpp
Normal file
176
components/esp_modem/examples/ap_to_pppos/main/network_dce.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
/* softAP to PPPoS Example (network_dce)
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_modem_config.h"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#include "cxx_include/esp_modem_dce_factory.hpp"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include "network_dce.h"
|
||||
|
||||
using namespace esp_modem;
|
||||
using namespace esp_modem::dce_factory;
|
||||
|
||||
class NetModule;
|
||||
typedef DCE_T<NetModule> NetDCE;
|
||||
|
||||
/**
|
||||
* @brief Local network object used to setup PPP network
|
||||
*/
|
||||
class PPPNetwork {
|
||||
public:
|
||||
esp_err_t init(esp_netif_t *netif, const std::string& apn, const std::string &pin_number);
|
||||
void deinit();
|
||||
NetDCE * get_dce();
|
||||
private:
|
||||
NetDCE *dce;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The PPP network is a singleton, allocate statically here
|
||||
*/
|
||||
static PPPNetwork ppp_network;
|
||||
|
||||
/**
|
||||
* @brief Custom factory for creating NetDCE and NetModule
|
||||
*/
|
||||
class NetDCE_Factory: public Factory {
|
||||
public:
|
||||
template <typename T, typename ...Args>
|
||||
static DCE_T<T>* create(const config *cfg, Args&&... args)
|
||||
{
|
||||
return build_generic_DCE<T>(cfg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename ...Args>
|
||||
static std::shared_ptr<T> create_module(const config *cfg, Args&&... args)
|
||||
{
|
||||
return build_shared_module<T>(cfg, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This is an example of implementing minimal network module functionality
|
||||
*
|
||||
* This does only include those AT commands, that are needed for setting the network up
|
||||
* and also initialization part (set pin, ...)
|
||||
*/
|
||||
class NetModule: public ModuleIf {
|
||||
public:
|
||||
explicit NetModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config *cfg):
|
||||
dte(std::move(dte)), apn(std::string(cfg->apn)) {}
|
||||
|
||||
bool setup_data_mode() override
|
||||
{
|
||||
PdpContext pdp(apn);
|
||||
if (set_pdp_context(pdp) != command_result::OK)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_mode(modem_mode mode) override
|
||||
{
|
||||
if (mode == modem_mode::DATA_MODE) {
|
||||
if (set_data_mode() != command_result::OK)
|
||||
return resume_data_mode() == command_result::OK;
|
||||
return true;
|
||||
}
|
||||
if (mode == modem_mode::COMMAND_MODE) {
|
||||
return set_command_mode() == command_result::OK;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool init(const std::string& pin)
|
||||
{
|
||||
// switch to command mode (in case we were in PPP mode)
|
||||
static_cast<void>(set_command_mode()); // ignore the potential failure, as we might be in command mode after startup
|
||||
bool is_pin_ok;
|
||||
if (read_pin(is_pin_ok) != command_result::OK)
|
||||
return false;
|
||||
if (!is_pin_ok) {
|
||||
if (set_pin(pin) != command_result::OK)
|
||||
return false;
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
if (read_pin(is_pin_ok) != command_result::OK || !is_pin_ok)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DTE> dte;
|
||||
std::string apn;
|
||||
|
||||
[[nodiscard]] command_result set_pdp_context(PdpContext& pdp) { return dce_commands::set_pdp_context(dte.get(),pdp); }
|
||||
[[nodiscard]] command_result set_pin(const std::string &pin) { return dce_commands::set_pin(dte.get(), pin); }
|
||||
[[nodiscard]] command_result read_pin(bool& pin_ok) { return dce_commands::read_pin(dte.get(), pin_ok); }
|
||||
[[nodiscard]] command_result set_data_mode() { return dce_commands::set_data_mode(dte.get()); }
|
||||
[[nodiscard]] command_result resume_data_mode() { return dce_commands::resume_data_mode(dte.get()); }
|
||||
[[nodiscard]] command_result set_command_mode() { return dce_commands::set_command_mode(dte.get()); }
|
||||
};
|
||||
|
||||
|
||||
esp_err_t PPPNetwork::init(esp_netif_t *netif, const std::string& apn, const std::string &pin_number)
|
||||
{
|
||||
// configure
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
dte_config.uart_config.rx_buffer_size = 16384;
|
||||
dte_config.uart_config.tx_buffer_size = 2048;
|
||||
esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(apn.c_str());
|
||||
|
||||
// create DTE and minimal network DCE
|
||||
auto uart_dte = create_uart_dte(&dte_config);
|
||||
|
||||
// create the specific device (and initialize it)
|
||||
auto dev = NetDCE_Factory::create_module<NetModule>(&dce_config, uart_dte, netif);
|
||||
if (!dev->init(pin_number))
|
||||
return ESP_FAIL;
|
||||
|
||||
// now create the DCE from our already existent device
|
||||
dce = NetDCE_Factory::create<NetModule>(&dce_config, uart_dte, netif, dev);
|
||||
if (dce == nullptr)
|
||||
return ESP_FAIL;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void PPPNetwork::deinit()
|
||||
{
|
||||
free(dce);
|
||||
dce = nullptr;
|
||||
}
|
||||
|
||||
NetDCE *PPPNetwork::get_dce()
|
||||
{
|
||||
return dce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implement the C-API for the AP-2-PPP functionality
|
||||
*/
|
||||
extern "C" esp_err_t modem_init_network(esp_netif_t *netif)
|
||||
{
|
||||
return ppp_network.init(netif, CONFIG_EXAMPLE_MODEM_PPP_APN, CONFIG_EXAMPLE_SIM_PIN);
|
||||
}
|
||||
|
||||
extern "C" void modem_start_network()
|
||||
{
|
||||
ppp_network.get_dce()->set_mode(esp_modem::modem_mode::DATA_MODE);
|
||||
}
|
||||
|
||||
extern "C" void modem_stop_network()
|
||||
{
|
||||
ppp_network.get_dce()->set_mode(esp_modem::modem_mode::COMMAND_MODE);
|
||||
}
|
||||
|
||||
extern "C" void modem_deinit_network()
|
||||
{
|
||||
ppp_network.deinit();
|
||||
}
|
47
components/esp_modem/examples/ap_to_pppos/main/network_dce.h
Normal file
47
components/esp_modem/examples/ap_to_pppos/main/network_dce.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* softAP to PPPoS Example (network_dce)
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#ifndef _NETWORK_DCE_H_
|
||||
#define _NETWORK_DCE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize a singleton covering the PPP network provided by the connected modem device
|
||||
*
|
||||
* @param netif Already created network interface in PPP mode
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t modem_init_network(esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @brief Destroys the single network DCE
|
||||
*/
|
||||
void modem_deinit_network();
|
||||
|
||||
/**
|
||||
* @brief Starts the PPP network
|
||||
*/
|
||||
void modem_start_network();
|
||||
|
||||
/**
|
||||
* @brief Stops the PPP network
|
||||
*/
|
||||
void modem_stop_network();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_NETWORK_DCE_H_
|
@ -0,0 +1,8 @@
|
||||
CONFIG_LWIP_PPP_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_PAP_SUPPORT=y
|
||||
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
|
||||
CONFIG_LWIP_PPP_ENABLE_IPV6=n
|
||||
CONFIG_UART_ISR_IN_IRAM=y
|
||||
# Enable NAPT
|
||||
CONFIG_LWIP_IP_FORWARD=y
|
||||
CONFIG_LWIP_IPV4_NAPT=y
|
13
components/esp_modem/examples/linux_modem/CMakeLists.txt
Normal file
13
components/esp_modem/examples/linux_modem/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS ../.. ../../port/linux)
|
||||
|
||||
set(COMPONENTS main)
|
||||
project(linux_modem)
|
||||
|
||||
|
||||
idf_component_get_property(esp_modem esp_modem COMPONENT_LIB)
|
||||
target_compile_definitions(${esp_modem} PRIVATE "-DCONFIG_COMPILER_CXX_EXCEPTIONS")
|
||||
target_compile_definitions(${esp_modem} PRIVATE "-DCONFIG_IDF_TARGET_LINUX")
|
19
components/esp_modem/examples/linux_modem/README.md
Normal file
19
components/esp_modem/examples/linux_modem/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Linux modem example
|
||||
|
||||
This is an experimental port of the esp_modem to linux.
|
||||
It mocks some IDF functionality with `port/linux` layers (used for modem host test suite) and implements `esp_netif`,
|
||||
which supports `tun` interface and uses lwIP `ppp` implementation to parse or wrap IP packets to be send/receive
|
||||
over PPPoS, i.e. over the modem serial line.
|
||||
|
||||
## Configuration
|
||||
|
||||
* Set path to the lwip and lwip_contrib repositories as environmental variables:
|
||||
- `LWIP_PATH`: path to the lwip repository
|
||||
- `LWIP_CONTRIB_PATH`: path to the lwip_contrib repository
|
||||
* Create a `tun` interface using `make_tun_netif` script.
|
||||
* Set SIO dev name directly in the code: This is the serial port which is the modem connected to
|
||||
* (Set the tun device na interface name in the code: Not needed if the device was created using the script above.)
|
||||
* Build and run the example (no elevated privileges needed)
|
||||
* Experiment with the network, after getting the IP from the modem device
|
||||
- directly in the code
|
||||
- in the system (need to set `tun` interface IP, dns servers, and routing the desired traffic over the tun interface)
|
@ -0,0 +1,9 @@
|
||||
idf_component_register(SRCS "modem_main.cpp"
|
||||
REQUIRES esp_modem)
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE Threads::Threads)
|
||||
|
||||
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE "-DCONFIG_IDF_TARGET_LINUX")
|
@ -0,0 +1,65 @@
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
#include <unistd.h>
|
||||
#include <esp_log.h>
|
||||
#include "cxx_include/esp_modem_terminal.hpp"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_modem_config.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
|
||||
#define CONFIG_EXAMPLE_SIM_PIN "1234"
|
||||
|
||||
using namespace esp_modem;
|
||||
|
||||
[[maybe_unused]] static const char *TAG = "linux_modem_main";
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
// init the DTE
|
||||
esp_modem_dte_config_t dte_config = {
|
||||
.dte_buffer_size = 512,
|
||||
.task_stack_size = 1024,
|
||||
.task_priority = 10,
|
||||
.uart_config = { },
|
||||
.vfs_config = { }
|
||||
};
|
||||
dte_config.vfs_config.dev_name = "/dev/ttyUSB0";
|
||||
dte_config.vfs_config.resource = ESP_MODEM_VFS_IS_UART; // This tells the VFS to init the UART (use termux to setup baudrate, etc.)
|
||||
|
||||
esp_netif_config_t netif_config = {
|
||||
.dev_name = "/dev/net/tun",
|
||||
.if_name = "tun0"
|
||||
};
|
||||
esp_netif_t *tun_netif = esp_netif_new(&netif_config);
|
||||
auto uart_dte = create_vfs_dte(&dte_config);
|
||||
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet");
|
||||
|
||||
auto dce = create_SIM7600_dce(&dce_config, uart_dte, tun_netif);
|
||||
assert(dce != nullptr);
|
||||
|
||||
dce->set_command_mode();
|
||||
|
||||
bool pin_ok = true;
|
||||
if (dce->read_pin(pin_ok) == command_result::OK && !pin_ok) {
|
||||
throw_if_false(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
|
||||
usleep(1000000);
|
||||
}
|
||||
std::string str;
|
||||
dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
|
||||
dce->get_imsi(str);
|
||||
ESP_LOGI(TAG, "Modem IMSI number: %s",str.c_str());
|
||||
dce->get_imei(str);
|
||||
ESP_LOGI(TAG, "Modem IMEI number: %s",str.c_str());
|
||||
dce->get_operator_name(str);
|
||||
ESP_LOGI(TAG, "Operator name: %s",str.c_str());
|
||||
|
||||
dce->set_mode(esp_modem::modem_mode::DATA_MODE);
|
||||
|
||||
usleep(100'000'000);
|
||||
esp_netif_destroy(tun_netif);
|
||||
}
|
3
components/esp_modem/examples/linux_modem/make_tun_netif
Executable file
3
components/esp_modem/examples/linux_modem/make_tun_netif
Executable file
@ -0,0 +1,3 @@
|
||||
sudo ip tuntap add mode tun user `whoami`
|
||||
sudo ip link set dev tun0 up
|
||||
sudo ifconfig tun0 10.184.178.109 netmask 255.255.255.255 up
|
@ -0,0 +1,5 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
CONFIG_COMPILER_CXX_EXCEPTIONS=y
|
||||
CONFIG_COMPILER_CXX_RTTI=y
|
||||
CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
|
||||
CONFIG_COMPILER_STACK_CHECK_NONE=y
|
@ -0,0 +1,8 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(modem-console)
|
11
components/esp_modem/examples/modem_console/Makefile
Normal file
11
components/esp_modem/examples/modem_console/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := modem-console
|
||||
|
||||
EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
17
components/esp_modem/examples/modem_console/README.md
Normal file
17
components/esp_modem/examples/modem_console/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# PPPoS simple client example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## Overview
|
||||
|
||||
This example is mainly targets experimenting with a modem device, sending custom commands and switching to PPP mode using esp-console, command line API.
|
||||
Please check the list of supported commands using `help` command.
|
||||
|
||||
This example implements two very simple network commands to demonstrate and test basic network functionality.
|
||||
* `httpget`: Connect and get http content
|
||||
* `ping`: Send ICMP pings
|
||||
|
||||
To demonstrate creating custom modem devices, this example creates a DCE object using a locally defined create method,
|
||||
that sets up the DCE based on a custom module implemented in the `my_module_dce.hpp` file. The module class only overrides
|
||||
`get_module_name()` method supplying a user defined name, but keeps all other commands the same as defined in the `GenericModule`
|
||||
class.
|
@ -0,0 +1,5 @@
|
||||
idf_component_register(SRCS "modem_console_main.cpp"
|
||||
"console_helper.cpp"
|
||||
"httpget_handle.c"
|
||||
"ping_handle.c"
|
||||
INCLUDE_DIRS ".")
|
@ -0,0 +1,4 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
@ -0,0 +1,132 @@
|
||||
/* Modem console example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include "console_helper.hpp"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "modem_console_helper";
|
||||
|
||||
ConsoleCommand::ConsoleCommand(const char* command, const char* help, const std::vector<CommandArgs>& args, std::function<bool(ConsoleCommand *)> f):
|
||||
func(std::move(f))
|
||||
{
|
||||
RegisterCommand(command, help, args);
|
||||
}
|
||||
|
||||
void ConsoleCommand::RegisterCommand(const char* command, const char* help, const std::vector<CommandArgs>& args)
|
||||
{
|
||||
assert(last_command <= MAX_REPEAT_NR);
|
||||
void * common_arg = nullptr;
|
||||
for (auto it: args) {
|
||||
switch(it.type) {
|
||||
case ARG_END:
|
||||
break;
|
||||
case STR0:
|
||||
common_arg = arg_str0(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case STR1:
|
||||
common_arg = arg_str1(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case INT0:
|
||||
common_arg = arg_int0(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case INT1:
|
||||
common_arg = arg_int1(it.shortopts, it.longopts, it.datatype, it.glossary);
|
||||
break;
|
||||
case LIT0:
|
||||
common_arg = arg_lit0(it.shortopts, it.longopts, it.glossary);
|
||||
break;
|
||||
}
|
||||
if (common_arg) {
|
||||
arg_table.emplace_back(common_arg);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Creating argument parser failed for %s", it.glossary);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
arg_table.emplace_back( arg_end(1));
|
||||
const esp_console_cmd_t command_def = {
|
||||
.command = command,
|
||||
.help = help,
|
||||
.hint = nullptr,
|
||||
.func = command_func_pts[last_command],
|
||||
.argtable = &arg_table[0]
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&command_def));
|
||||
last_command++;
|
||||
console_commands.emplace_back(this);
|
||||
}
|
||||
|
||||
int ConsoleCommand::get_count(int index)
|
||||
{
|
||||
return ((struct arg_str *)arg_table[index])->count;
|
||||
}
|
||||
|
||||
std::string ConsoleCommand::get_string(int index)
|
||||
{
|
||||
if (get_count(index) > 0) {
|
||||
return std::string(((struct arg_str *)arg_table[index])->sval[0]);
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
int ConsoleCommand::get_int(int index)
|
||||
{
|
||||
if (get_count(index) > 0) {
|
||||
return *((struct arg_int *)arg_table[index])->ival;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int ConsoleCommand::command_func(int argc, char **argv) {
|
||||
void * plain_arg_array = &arg_table[0];
|
||||
int nerrors = arg_parse(argc, argv, (void **)plain_arg_array);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, (struct arg_end *) arg_table.back(), argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (func) {
|
||||
return func(this);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This class holds definitions of static functions, numbered from 0 index,
|
||||
* that call indexed methods of ConsoleCommand (used to bridge from static esp-console
|
||||
* to object oriented ConsoleCommand class)
|
||||
*/
|
||||
class StaticCommands {
|
||||
friend class ConsoleCommand;
|
||||
#define ITEM_TO_REPEAT(index) \
|
||||
static inline int command_func_ ## index(int argc, char **argv) \
|
||||
{ return ConsoleCommand::console_commands[index]->command_func(argc, argv); }
|
||||
|
||||
_DO_REPEAT_ITEM()
|
||||
|
||||
#undef ITEM_TO_REPEAT
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief ConsoleCommand list of static callbacks used for getting object context to plain esp-console context
|
||||
*/
|
||||
const esp_console_cmd_func_t ConsoleCommand::command_func_pts[] = {
|
||||
|
||||
#define ITEM_TO_REPEAT(index) StaticCommands::command_func_ ## index ,
|
||||
|
||||
_DO_REPEAT_ITEM()
|
||||
|
||||
#undef ITEM_TO_REPEAT
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Static members defined for ConsoleCommand
|
||||
*/
|
||||
std::vector<ConsoleCommand*> ConsoleCommand::console_commands;
|
||||
int ConsoleCommand::last_command = 0;
|
@ -0,0 +1,103 @@
|
||||
/* Modem console example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#ifndef MODEM_CONSOLE_CONSOLE_HELPER_H
|
||||
#define MODEM_CONSOLE_CONSOLE_HELPER_H
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <esp_console.h>
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "repeat_helper.inc"
|
||||
|
||||
#define MAX_REPEAT_NR 20
|
||||
|
||||
/**
|
||||
* @brief Argument types used for ConsoleCommand
|
||||
*/
|
||||
enum arg_type {
|
||||
STR0,
|
||||
STR1,
|
||||
INT0,
|
||||
INT1,
|
||||
LIT0,
|
||||
ARG_END,
|
||||
};
|
||||
|
||||
/**
|
||||
* Command argument struct definition for list of arguments of one command
|
||||
*/
|
||||
struct CommandArgs {
|
||||
CommandArgs(arg_type t, const char * shopts, const char * lopts, const char * data, const char * glos):
|
||||
type(t), shortopts(shopts), longopts(lopts), datatype(data), glossary(glos) {}
|
||||
CommandArgs(arg_type t, const char * shopts, const char * lopts, const char * glos):
|
||||
type(t), shortopts(shopts), longopts(lopts), datatype(nullptr), glossary(glos) {}
|
||||
|
||||
arg_type type;
|
||||
const char *shortopts;
|
||||
const char *longopts;
|
||||
const char *datatype;
|
||||
const char *glossary;
|
||||
};
|
||||
|
||||
class StaticCommands;
|
||||
|
||||
/**
|
||||
* @brief This class simplifies console command definition in more object wise fashion
|
||||
*/
|
||||
class ConsoleCommand {
|
||||
friend class StaticCommands;
|
||||
public:
|
||||
/**
|
||||
* @brief This is how we define a generic Console command
|
||||
* @param command Textual console command
|
||||
* @param help Contextual help for the command
|
||||
* @param arg_struct List of argument struct
|
||||
* @param srg_struct_size Size of the argument struct
|
||||
* @param f Function callback for the command
|
||||
*/
|
||||
template<typename T> explicit ConsoleCommand(const char* command, const char* help, const T *arg_struct, size_t srg_struct_size,
|
||||
std::function<bool(ConsoleCommand *)> f): func(std::move(f))
|
||||
{
|
||||
size_t args_plain_size = srg_struct_size / sizeof(CommandArgs);
|
||||
auto first_arg = reinterpret_cast<const CommandArgs *>(arg_struct);
|
||||
std::vector<CommandArgs> args(first_arg, first_arg + args_plain_size);
|
||||
RegisterCommand(command, help, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Another method of Console command definitions using vector arg struct
|
||||
*/
|
||||
explicit ConsoleCommand(const char* command, const char* help, const std::vector<CommandArgs>& args, std::function<bool(ConsoleCommand *)> f);
|
||||
|
||||
/**
|
||||
* @brief Utility getters of various params from the argument list
|
||||
*/
|
||||
template<typename T> int get_count_of(CommandArgs T::*member) { return get_count(index_arg(member)); }
|
||||
template<typename T> std::string get_string_of(CommandArgs T::*member) { return get_string(index_arg(member)); }
|
||||
template<typename T> int get_int_of(CommandArgs T::*member) { return get_int(index_arg(member)); }
|
||||
std::string get_string(int index);
|
||||
int get_int(int index);
|
||||
|
||||
private:
|
||||
int get_count(int index);
|
||||
void RegisterCommand(const char* command, const char* help, const std::vector<CommandArgs>& args);
|
||||
template<typename T> static constexpr size_t index_arg(CommandArgs T::*member)
|
||||
{ return ((uint8_t *)&((T*)nullptr->*member) - (uint8_t *)nullptr)/sizeof(CommandArgs); }
|
||||
std::vector<void*> arg_table;
|
||||
int command_func(int argc, char **argv);
|
||||
|
||||
static int last_command;
|
||||
static std::vector<ConsoleCommand*> console_commands;
|
||||
std::function<bool(ConsoleCommand *)> func;
|
||||
const static esp_console_cmd_func_t command_func_pts[];
|
||||
};
|
||||
|
||||
#endif //MODEM_CONSOLE_CONSOLE_HELPER_H
|
@ -0,0 +1,108 @@
|
||||
/* Modem console example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_http_client.h"
|
||||
|
||||
static const char *TAG = "modem_console_httpget";
|
||||
|
||||
static esp_err_t http_event_handler(esp_http_client_event_t *evt)
|
||||
{
|
||||
switch(evt->event_id) {
|
||||
case HTTP_EVENT_ERROR:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
|
||||
break;
|
||||
case HTTP_EVENT_ON_CONNECTED:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
|
||||
break;
|
||||
case HTTP_EVENT_HEADER_SENT:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
|
||||
break;
|
||||
case HTTP_EVENT_ON_HEADER:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
|
||||
break;
|
||||
case HTTP_EVENT_ON_DATA:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
|
||||
if ((bool)evt->user_data &&
|
||||
!esp_http_client_is_chunked_response(evt->client)) {
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, evt->data, evt->data_len, ESP_LOG_INFO);
|
||||
}
|
||||
|
||||
break;
|
||||
case HTTP_EVENT_ON_FINISH:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
|
||||
break;
|
||||
case HTTP_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_str *host;
|
||||
struct arg_lit *hex;
|
||||
struct arg_end *end;
|
||||
} http_args;
|
||||
|
||||
static int do_http_client(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&http_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, http_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
esp_http_client_config_t config = {
|
||||
.event_handler = http_event_handler,
|
||||
};
|
||||
|
||||
if (http_args.host->count > 0) {
|
||||
config.url = http_args.host->sval[0];
|
||||
} else {
|
||||
config.url = "http://httpbin.org/get";
|
||||
}
|
||||
|
||||
if (http_args.hex->count > 0) {
|
||||
// show hex data from http-get
|
||||
config.user_data = (void*)true;
|
||||
}
|
||||
|
||||
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||
|
||||
esp_err_t err = esp_http_client_perform(client);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
|
||||
esp_http_client_get_status_code(client),
|
||||
esp_http_client_get_content_length(client));
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void modem_console_register_http(void)
|
||||
{
|
||||
http_args.host = arg_str0(NULL, NULL, "<host>", "address or host-name to send GET request (defaults to http://httpbin.org/get)");
|
||||
http_args.hex = arg_litn("p", "print-hex", 0, 1, "print hex output"),
|
||||
http_args.end = arg_end(1);
|
||||
const esp_console_cmd_t http_cmd = {
|
||||
.command = "httpget",
|
||||
.help = "http get command to test data mode",
|
||||
.hint = NULL,
|
||||
.func = &do_http_client,
|
||||
.argtable = &http_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&http_cmd));
|
||||
}
|
@ -0,0 +1,219 @@
|
||||
/* Modem console example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_event.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_modem_config.h"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#include "esp_log.h"
|
||||
#include "console_helper.hpp"
|
||||
#include "my_module_dce.hpp"
|
||||
|
||||
#define CHECK_ERR(cmd, success_action) do { \
|
||||
auto err = cmd; \
|
||||
if (err == command_result::OK) { \
|
||||
success_action; \
|
||||
return 0; \
|
||||
} else { \
|
||||
ESP_LOGE(TAG, "Failed with %s", err == command_result::TIMEOUT ? "TIMEOUT":"ERROR"); \
|
||||
return 1; \
|
||||
} } while (0)
|
||||
|
||||
/**
|
||||
* Please update the default APN name here (this could be updated runtime)
|
||||
*/
|
||||
#define DEFAULT_APN "my_apn"
|
||||
|
||||
extern "C" void modem_console_register_http(void);
|
||||
extern "C" void modem_console_register_ping(void);
|
||||
|
||||
static const char *TAG = "modem_console";
|
||||
static esp_console_repl_t *s_repl = nullptr;
|
||||
|
||||
using namespace esp_modem;
|
||||
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// init the netif, DTE and DCE respectively
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
|
||||
esp_netif_t *esp_netif = esp_netif_new(&ppp_netif_config);
|
||||
assert(esp_netif);
|
||||
auto uart_dte = create_uart_dte(&dte_config);
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(DEFAULT_APN);
|
||||
auto dce = create_shiny_dce(&dce_config, uart_dte, esp_netif);
|
||||
assert(dce != nullptr);
|
||||
|
||||
// init console REPL environment
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl));
|
||||
|
||||
modem_console_register_http();
|
||||
modem_console_register_ping();
|
||||
const struct SetModeArgs {
|
||||
SetModeArgs(): mode(STR1, nullptr, nullptr, "<mode>", "PPP, CMD or CMUX") {}
|
||||
CommandArgs mode;
|
||||
} set_mode_args;
|
||||
const ConsoleCommand SetModeParser("set_mode", "sets modem mode", &set_mode_args, sizeof(set_mode_args), [&](ConsoleCommand *c){
|
||||
if (c->get_count_of(&SetModeArgs::mode)) {
|
||||
auto mode = c->get_string_of(&SetModeArgs::mode);
|
||||
modem_mode dev_mode;
|
||||
if (mode == "CMD") {
|
||||
dev_mode = esp_modem::modem_mode::COMMAND_MODE;
|
||||
} else if (mode == "PPP") {
|
||||
dev_mode = esp_modem::modem_mode::DATA_MODE;
|
||||
} else if (mode == "CMUX") {
|
||||
dev_mode = esp_modem::modem_mode::CMUX_MODE;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unsupported mode: %s", mode.c_str());
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGI(TAG, "Switching to %s name...", mode.c_str());
|
||||
if (!dce->set_mode(dev_mode)) {
|
||||
ESP_LOGE(TAG, "Failed to set the desired mode");
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGI(TAG, "OK");
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const struct SetPinArgs {
|
||||
SetPinArgs(): pin(STR1, nullptr, nullptr, "<pin>", "PIN") {}
|
||||
CommandArgs pin;
|
||||
} set_pin_args;
|
||||
const ConsoleCommand SetPinParser("set_pin", "sets SIM card PIN", &set_pin_args, sizeof(set_pin_args), [&](ConsoleCommand *c){
|
||||
if (c->get_count_of(&SetPinArgs::pin)) {
|
||||
auto pin = c->get_string_of(&SetPinArgs::pin);
|
||||
ESP_LOGI(TAG, "Setting pin=%s...", pin.c_str());
|
||||
auto err = dce->set_pin(pin);
|
||||
if (err == command_result::OK) {
|
||||
ESP_LOGI(TAG, "OK");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT":"");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const std::vector<CommandArgs> no_args;
|
||||
const ConsoleCommand ReadPinArgs("read_pin", "checks if SIM is unlocked", no_args, [&](ConsoleCommand *c){
|
||||
bool pin_ok;
|
||||
ESP_LOGI(TAG, "Checking pin...");
|
||||
auto err = dce->read_pin(pin_ok);
|
||||
if (err == command_result::OK) {
|
||||
ESP_LOGI(TAG, "OK. Pin status: %s", pin_ok ? "true": "false");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed %s", err == command_result::TIMEOUT ? "TIMEOUT":"");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const ConsoleCommand GetModuleName("get_module_name", "reads the module name", no_args, [&](ConsoleCommand *c){
|
||||
std::string module_name;
|
||||
ESP_LOGI(TAG, "Reading module name...");
|
||||
CHECK_ERR(dce->get_module_name(module_name), ESP_LOGI(TAG, "OK. Module name: %s", module_name.c_str()));
|
||||
});
|
||||
|
||||
const ConsoleCommand GetOperatorName("get_operator_name", "reads the operator name", no_args, [&](ConsoleCommand *c){
|
||||
std::string operator_name;
|
||||
ESP_LOGI(TAG, "Reading operator name...");
|
||||
CHECK_ERR(dce->get_operator_name(operator_name), ESP_LOGI(TAG, "OK. Operator name: %s", operator_name.c_str()));
|
||||
});
|
||||
|
||||
const struct GenericCommandArgs {
|
||||
GenericCommandArgs():
|
||||
cmd(STR1, nullptr, nullptr, "<command>", "AT command to send to the modem"),
|
||||
timeout(INT0, "t", "timeout", "<timeout>", "command timeout"),
|
||||
pattern(STR0, "p", "pattern", "<pattern>", "command response to wait for"),
|
||||
no_cr(LIT0, "n", "no-cr", "do not add trailing CR to the command") {}
|
||||
CommandArgs cmd;
|
||||
CommandArgs timeout;
|
||||
CommandArgs pattern;
|
||||
CommandArgs no_cr;
|
||||
} send_cmd_args;
|
||||
const ConsoleCommand SendCommand("cmd", "sends generic AT command, no_args", &send_cmd_args, sizeof(send_cmd_args), [&](ConsoleCommand *c) {
|
||||
auto cmd = c->get_string_of(&GenericCommandArgs::cmd);
|
||||
auto timeout = c->get_count_of(&GenericCommandArgs::timeout) ? c->get_int_of(&GenericCommandArgs::timeout)
|
||||
: 1000;
|
||||
auto pattern = c->get_string_of(&GenericCommandArgs::pattern);
|
||||
if (c->get_count_of(&GenericCommandArgs::no_cr) == 0) {
|
||||
cmd += '\r';
|
||||
}
|
||||
ESP_LOGI(TAG, "Sending command %s with timeout %d", cmd.c_str(), timeout);
|
||||
CHECK_ERR(dce->command(cmd, [&](uint8_t *data, size_t len) {
|
||||
std::string response((char *) data, len);
|
||||
ESP_LOGI(TAG, "%s", response.c_str());
|
||||
if (pattern.empty() || response.find(pattern) != std::string::npos)
|
||||
return command_result::OK;
|
||||
if (response.find(pattern) != std::string::npos)
|
||||
return command_result::OK;
|
||||
return command_result::TIMEOUT;
|
||||
}, timeout),);
|
||||
});
|
||||
|
||||
const ConsoleCommand GetSignalQuality("get_signal_quality", "Gets signal quality", no_args, [&](ConsoleCommand *c){
|
||||
int rssi, ber;
|
||||
CHECK_ERR(dce->get_signal_quality(rssi, ber), ESP_LOGI(TAG, "OK. rssi=%d, ber=%d", rssi, ber));
|
||||
});
|
||||
const ConsoleCommand GetBatteryStatus("get_battery_status", "Reads voltage/battery status", no_args, [&](ConsoleCommand *c){
|
||||
int volt, bcl, bcs;
|
||||
CHECK_ERR(dce->get_battery_status(volt, bcl, bcs), ESP_LOGI(TAG, "OK. volt=%d, bcl=%d, bcs=%d", volt, bcl, bcs));
|
||||
});
|
||||
const ConsoleCommand PowerDown("power_down", "power down the module", no_args, [&](ConsoleCommand *c){
|
||||
ESP_LOGI(TAG, "Power down the module...");
|
||||
CHECK_ERR(dce->power_down(), ESP_LOGI(TAG, "OK"));
|
||||
});
|
||||
const ConsoleCommand Reset("reset", "reset the module", no_args, [&](ConsoleCommand *c){
|
||||
ESP_LOGI(TAG, "Resetting the module...");
|
||||
CHECK_ERR(dce->reset(), ESP_LOGI(TAG, "OK"));
|
||||
});
|
||||
const struct SetApn {
|
||||
SetApn(): apn(STR1, nullptr, nullptr, "<apn>", "APN (Access Point Name)") {}
|
||||
CommandArgs apn;
|
||||
} set_apn;
|
||||
const ConsoleCommand SetApnParser("set_apn", "sets APN", &set_apn, sizeof(set_apn), [&](ConsoleCommand *c){
|
||||
if (c->get_count_of(&SetApn::apn)) {
|
||||
auto apn = c->get_string_of(&SetApn::apn);
|
||||
ESP_LOGI(TAG, "Setting the APN=%s...", apn.c_str());
|
||||
auto new_pdp = std::unique_ptr<PdpContext>(new PdpContext(apn));
|
||||
dce->get_module()->configure_pdp_context(std::move(new_pdp));
|
||||
ESP_LOGI(TAG, "OK");
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
SignalGroup exit_signal;
|
||||
const ConsoleCommand ExitConsole("exit", "exit the console application", no_args, [&](ConsoleCommand *c){
|
||||
ESP_LOGI(TAG, "Exiting...");
|
||||
exit_signal.set(1);
|
||||
s_repl->del(s_repl);
|
||||
return 0;
|
||||
});
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(s_repl));
|
||||
// wait for exit
|
||||
exit_signal.wait_any(1, UINT32_MAX);
|
||||
ESP_LOGI(TAG, "Exiting...%d", esp_get_free_heap_size());
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/* Modem console example: Custom DCE
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#ifndef __MY_MODULE_DCE_HPP__
|
||||
#define __MY_MODULE_DCE_HPP__
|
||||
|
||||
|
||||
#include "cxx_include/esp_modem_dce_factory.hpp"
|
||||
#include "cxx_include/esp_modem_dce_module.hpp"
|
||||
|
||||
/**
|
||||
* @brief Definition of a custom modem which inherits from the GenericModule, uses all its methods
|
||||
* and could override any of them. Here, for demonstration purposes only, we redefine just `get_module_name()`
|
||||
*/
|
||||
class MyShinyModem: public esp_modem::GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
public:
|
||||
esp_modem::command_result get_module_name(std::string& name) override
|
||||
{
|
||||
name = "Custom Shiny Module";
|
||||
return esp_modem::command_result::OK;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper create method which employs the DCE factory for creating DCE objects templated by a custom module
|
||||
* @return unique pointer of the resultant DCE
|
||||
*/
|
||||
std::unique_ptr<esp_modem::DCE> create_shiny_dce(const esp_modem::dce_config *config,
|
||||
std::shared_ptr<esp_modem::DTE> dte,
|
||||
esp_netif_t *netif)
|
||||
{
|
||||
return esp_modem::dce_factory::Factory::build_unique<MyShinyModem>(config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
|
||||
#endif //__MY_MODULE_DCE_HPP__
|
141
components/esp_modem/examples/modem_console/main/ping_handle.c
Normal file
141
components/esp_modem/examples/modem_console/main/ping_handle.c
Normal file
@ -0,0 +1,141 @@
|
||||
/* Ping handle example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_log.h"
|
||||
#include "ping/ping_sock.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
static const char *TAG = "modem_console_ping";
|
||||
|
||||
static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint8_t ttl;
|
||||
uint16_t seqno;
|
||||
uint32_t elapsed_time, recv_len;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
|
||||
ESP_LOGI(TAG, "%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n",
|
||||
recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time);
|
||||
}
|
||||
|
||||
static void cmd_ping_on_ping_timeout(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint16_t seqno;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
ESP_LOGE(TAG, "From %s icmp_seq=%d timeout\n", inet_ntoa(target_addr.u_addr.ip4), seqno);
|
||||
}
|
||||
|
||||
static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
ip_addr_t target_addr;
|
||||
uint32_t transmitted;
|
||||
uint32_t received;
|
||||
uint32_t total_time_ms;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
|
||||
uint32_t loss = (uint32_t)((1 - ((float)received) / transmitted) * 100);
|
||||
if (IP_IS_V4(&target_addr)) {
|
||||
ESP_LOGI(TAG, "\n--- %s ping statistics ---\n", inet_ntoa(*ip_2_ip4(&target_addr)));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "\n--- %s ping statistics ---\n", inet6_ntoa(*ip_2_ip6(&target_addr)));
|
||||
}
|
||||
ESP_LOGI(TAG, "%d packets transmitted, %d received, %d%% packet loss, time %dms\n",
|
||||
transmitted, received, loss, total_time_ms);
|
||||
// delete the ping sessions, so that we clean up all resources and can create a new ping session
|
||||
// we don't have to call delete function in the callback, instead we can call delete function from other tasks
|
||||
esp_ping_delete_session(hdl);
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_dbl *timeout;
|
||||
struct arg_int *count;
|
||||
struct arg_str *host;
|
||||
struct arg_end *end;
|
||||
} ping_args;
|
||||
|
||||
static int do_ping_cmd(int argc, char **argv)
|
||||
{
|
||||
esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG();
|
||||
|
||||
int nerrors = arg_parse(argc, argv, (void **)&ping_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, ping_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ping_args.timeout->count > 0) {
|
||||
config.timeout_ms = (uint32_t)(ping_args.timeout->dval[0] * 1000);
|
||||
}
|
||||
|
||||
if (ping_args.count->count > 0) {
|
||||
config.count = (uint32_t)(ping_args.count->ival[0]);
|
||||
}
|
||||
|
||||
// parse IP address
|
||||
ip_addr_t target_addr;
|
||||
struct addrinfo hint;
|
||||
struct addrinfo *res = NULL;
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
memset(&target_addr, 0, sizeof(target_addr));
|
||||
/* convert domain name to IP address */
|
||||
if (getaddrinfo(ping_args.host->sval[0], NULL, &hint, &res) != 0) {
|
||||
printf("ping: unknown host %s\n", ping_args.host->sval[0]);
|
||||
return 1;
|
||||
}
|
||||
if (res->ai_family == AF_INET) {
|
||||
struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr;
|
||||
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
|
||||
} else {
|
||||
struct in6_addr addr6 = ((struct sockaddr_in6 *) (res->ai_addr))->sin6_addr;
|
||||
inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6);
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
config.target_addr = target_addr;
|
||||
|
||||
/* set callback functions */
|
||||
esp_ping_callbacks_t cbs = {
|
||||
.on_ping_success = cmd_ping_on_ping_success,
|
||||
.on_ping_timeout = cmd_ping_on_ping_timeout,
|
||||
.on_ping_end = cmd_ping_on_ping_end,
|
||||
.cb_args = NULL
|
||||
};
|
||||
esp_ping_handle_t ping;
|
||||
esp_ping_new_session(&config, &cbs, &ping);
|
||||
esp_ping_start(ping);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void modem_console_register_ping(void)
|
||||
{
|
||||
ping_args.timeout = arg_dbl0("W", "timeout", "<t>", "Time to wait for a response, in seconds");
|
||||
ping_args.count = arg_int0("c", "count", "<n>", "Stop after sending count packets");
|
||||
ping_args.host = arg_str1(NULL, NULL, "<host>", "Host address");
|
||||
ping_args.end = arg_end(1);
|
||||
const esp_console_cmd_t ping_cmd = {
|
||||
.command = "ping",
|
||||
.help = "send ICMP ECHO_REQUEST to network hosts",
|
||||
.hint = NULL,
|
||||
.func = &do_ping_cmd,
|
||||
.argtable = &ping_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&ping_cmd));
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/* Modem console example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#ifndef MODEM_CONSOLE_REPEAT_HELPER_INC_H
|
||||
#define MODEM_CONSOLE_REPEAT_HELPER_INC_H
|
||||
|
||||
/**
|
||||
* @brief This header is used to generate a defined macro many times with iterator
|
||||
*/
|
||||
|
||||
#if MAX_REPEAT_NR > 20
|
||||
#error "Not enough items to repeat"
|
||||
#endif
|
||||
|
||||
#define _DO_REPEAT_ITEM(a) \
|
||||
ITEM_TO_REPEAT(0) \
|
||||
ITEM_TO_REPEAT(1) \
|
||||
ITEM_TO_REPEAT(2) \
|
||||
ITEM_TO_REPEAT(3) \
|
||||
ITEM_TO_REPEAT(4) \
|
||||
ITEM_TO_REPEAT(5) \
|
||||
ITEM_TO_REPEAT(6) \
|
||||
ITEM_TO_REPEAT(7) \
|
||||
ITEM_TO_REPEAT(8) \
|
||||
ITEM_TO_REPEAT(9) \
|
||||
ITEM_TO_REPEAT(10) \
|
||||
ITEM_TO_REPEAT(11) \
|
||||
ITEM_TO_REPEAT(12) \
|
||||
ITEM_TO_REPEAT(13) \
|
||||
ITEM_TO_REPEAT(14) \
|
||||
ITEM_TO_REPEAT(15) \
|
||||
ITEM_TO_REPEAT(16) \
|
||||
ITEM_TO_REPEAT(17) \
|
||||
ITEM_TO_REPEAT(18) \
|
||||
ITEM_TO_REPEAT(19) \
|
||||
ITEM_TO_REPEAT(20)
|
||||
|
||||
#endif //MODEM_CONSOLE_REPEAT_HELPER_INC_H
|
@ -0,0 +1,8 @@
|
||||
# Override some defaults to enable PPP
|
||||
CONFIG_LWIP_PPP_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_PAP_SUPPORT=y
|
||||
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
|
||||
# Do not enable IPV6 in dte<->dce link local
|
||||
CONFIG_LWIP_PPP_ENABLE_IPV6=n
|
||||
# Disable legacy API
|
||||
CONFIG_MODEM_LEGACY_API=n
|
10
components/esp_modem/examples/pppos_client/CMakeLists.txt
Normal file
10
components/esp_modem/examples/pppos_client/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(pppos_client)
|
||||
|
||||
|
10
components/esp_modem/examples/pppos_client/README.md
Normal file
10
components/esp_modem/examples/pppos_client/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# PPPoS simple client example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## Overview
|
||||
This example shows how to act as a MQTT client after the PPPoS channel created by using [ESP-MQTT](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/protocols/mqtt.html) APIs.
|
||||
|
||||
## How to use this example
|
||||
|
||||
See the README.md file in the upper level `pppos` directory for more information about the PPPoS examples.
|
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "pppos_client_main.c"
|
||||
INCLUDE_DIRS ".")
|
@ -0,0 +1,148 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
choice EXAMPLE_MODEM_DEVICE
|
||||
prompt "Choose supported modem device (DCE)"
|
||||
default EXAMPLE_MODEM_DEVICE_BG96
|
||||
help
|
||||
Select modem device connected to the ESP DTE.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM800
|
||||
bool "SIM800"
|
||||
help
|
||||
SIMCom SIM800L is a GSM/GPRS module.
|
||||
It supports Quad-band 850/900/1800/1900MHz.
|
||||
config EXAMPLE_MODEM_DEVICE_BG96
|
||||
bool "BG96"
|
||||
help
|
||||
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7600
|
||||
bool "SIM7600"
|
||||
help
|
||||
SIM7600 is Multi-Band LTE-TDD/LTE-FDD/HSPA+ and GSM/GPRS/EDGE module
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_MODEM_PPP_APN
|
||||
string "Set MODEM APN"
|
||||
default "internet"
|
||||
help
|
||||
Set APN (Access Point Name), a logical name to choose data network
|
||||
|
||||
config EXAMPLE_MODEM_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_NEED_SIM_PIN
|
||||
bool "SIM PIN needed"
|
||||
default n
|
||||
help
|
||||
Enable to set SIM PIN before starting the example
|
||||
|
||||
config EXAMPLE_SIM_PIN
|
||||
string "Set SIM PIN"
|
||||
default "1234"
|
||||
depends on EXAMPLE_NEED_SIM_PIN
|
||||
help
|
||||
Pin to unlock the SIM
|
||||
|
||||
menu "UART Configuration"
|
||||
config EXAMPLE_MODEM_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 25
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 26
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RTS_PIN
|
||||
int "RTS Pin Number"
|
||||
default 27
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RTS.
|
||||
|
||||
config EXAMPLE_MODEM_UART_CTS_PIN
|
||||
int "CTS Pin Number"
|
||||
default 23
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART CTS.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE
|
||||
int "UART Event Task Stack Size"
|
||||
range 2000 6000
|
||||
default 2048
|
||||
help
|
||||
Stack size of UART event task.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY
|
||||
int "UART Event Task Priority"
|
||||
range 3 22
|
||||
default 5
|
||||
help
|
||||
Priority of UART event task.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE
|
||||
int "UART Event Queue Size"
|
||||
range 10 40
|
||||
default 30
|
||||
help
|
||||
Length of UART event queue.
|
||||
|
||||
config EXAMPLE_MODEM_UART_PATTERN_QUEUE_SIZE
|
||||
int "UART Pattern Queue Size"
|
||||
range 10 40
|
||||
default 20
|
||||
help
|
||||
Length of UART pattern queue.
|
||||
|
||||
config EXAMPLE_MODEM_UART_TX_BUFFER_SIZE
|
||||
int "UART TX Buffer Size"
|
||||
range 256 2048
|
||||
default 512
|
||||
help
|
||||
Buffer size of UART TX buffer.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_BUFFER_SIZE
|
||||
int "UART RX Buffer Size"
|
||||
range 256 2048
|
||||
default 1024
|
||||
help
|
||||
Buffer size of UART RX buffer.
|
||||
endmenu
|
||||
|
||||
endmenu
|
@ -0,0 +1,212 @@
|
||||
/* 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_api.h"
|
||||
#include "esp_log.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 GOT_DATA_BIT = BIT2;
|
||||
|
||||
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
|
||||
{
|
||||
esp_mqtt_client_handle_t client = event->client;
|
||||
int msg_id;
|
||||
switch (event->event_id) {
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
|
||||
msg_id = esp_mqtt_client_subscribe(client, "/topic/esp-pppos", 0);
|
||||
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
|
||||
break;
|
||||
case MQTT_EVENT_SUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
msg_id = esp_mqtt_client_publish(client, "/topic/esp-pppos", "esp32-pppos", 0, 0, 0);
|
||||
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_UNSUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_PUBLISHED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
|
||||
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
||||
printf("DATA=%.*s\r\n", event->data_len, event->data);
|
||||
xEventGroupSetBits(event_group, GOT_DATA_BIT);
|
||||
break;
|
||||
case MQTT_EVENT_ERROR:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "MQTT other event id: %d", event->event_id);
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
ESP_LOGI(TAG, "PPP state changed event %d", event_id);
|
||||
if (event_id == NETIF_PPP_ERRORUSER) {
|
||||
/* User interrupted event from esp-netif */
|
||||
esp_netif_t *netif = event_data;
|
||||
ESP_LOGI(TAG, "User interrupted event from netif:%p", netif);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_ip_event(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
ESP_LOGD(TAG, "IP event! %d", event_id);
|
||||
if (event_id == IP_EVENT_PPP_GOT_IP) {
|
||||
esp_netif_dns_info_t dns_info;
|
||||
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
esp_netif_t *netif = event->esp_netif;
|
||||
|
||||
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
||||
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
||||
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
||||
esp_netif_get_dns_info(netif, 0, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
esp_netif_get_dns_info(netif, 1, &dns_info);
|
||||
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||
|
||||
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||
ESP_LOGI(TAG, "GOT IPv6 event!");
|
||||
|
||||
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
||||
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
|
||||
/* Init and register system/core components */
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, NULL));
|
||||
|
||||
event_group = xEventGroupCreate();
|
||||
|
||||
/* Configure the DTE */
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
/* setup UART specific configuration based on kconfig options */
|
||||
dte_config.uart_config.tx_io_num = CONFIG_EXAMPLE_MODEM_UART_TX_PIN;
|
||||
dte_config.uart_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
|
||||
dte_config.uart_config.rts_io_num = CONFIG_EXAMPLE_MODEM_UART_RTS_PIN;
|
||||
dte_config.uart_config.cts_io_num = CONFIG_EXAMPLE_MODEM_UART_CTS_PIN;
|
||||
dte_config.uart_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
|
||||
dte_config.uart_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
|
||||
dte_config.uart_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
|
||||
dte_config.task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE;
|
||||
dte_config.task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY;
|
||||
dte_config.dte_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2;
|
||||
|
||||
/* Configure the DCE */
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
|
||||
|
||||
/* Configure the PPP netif */
|
||||
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
||||
|
||||
/* Run the modem demo app */
|
||||
// Init netif object
|
||||
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
|
||||
assert(esp_netif);
|
||||
esp_modem_dce_t *dce = esp_modem_new(&dte_config, &dce_config, esp_netif);
|
||||
|
||||
#if CONFIG_EXAMPLE_NEED_SIM_PIN == 1
|
||||
// check if PIN needed
|
||||
bool pin_ok = false;
|
||||
if (esp_modem_read_pin(dce, &pin_ok) == ESP_OK && pin_ok == false) {
|
||||
if (esp_modem_set_pin(dce, CONFIG_EXAMPLE_SIM_PIN) == ESP_OK) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int rssi, ber;
|
||||
esp_err_t err = esp_modem_get_signal_quality(dce, &rssi, &ber);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_modem_get_signal_quality failed with %d", err);
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber);
|
||||
|
||||
#if CONFIG_EXAMPLE_SEND_MSG
|
||||
if (esp_modem_sms_txt_mode(dce, true) != ESP_OK || esp_modem_sms_character_set(dce) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Setting text mode or GSM character set failed");
|
||||
return;
|
||||
}
|
||||
|
||||
err = esp_modem_send_sms(dce, CONFIG_EXAMPLE_SEND_MSG_PEER_PHONE_NUMBER, "Text message from esp-modem");
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_modem_send_sms() failed with %d", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = esp_modem_set_mode(dce, ESP_MODEM_MODE_DATA);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_modem_set_mode(ESP_MODEM_MODE_DATA) failed with %d", err);
|
||||
return;
|
||||
}
|
||||
/* 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);
|
||||
err = esp_modem_set_mode(dce, ESP_MODEM_MODE_COMMAND);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_modem_set_mode(ESP_MODEM_MODE_COMMAND) failed with %d", err);
|
||||
return;
|
||||
}
|
||||
char imsi[32];
|
||||
err = esp_modem_get_imsi(dce, imsi);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_modem_get_imsi failed with %d", err);
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "IMSI=%s", imsi);
|
||||
|
||||
esp_modem_destroy(dce);
|
||||
esp_netif_destroy(esp_netif);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
# 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
|
||||
CONFIG_LWIP_PPP_ENABLE_IPV6=n
|
@ -0,0 +1,10 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../.." $ENV{IDF_PATH}/examples/cxx/experimental/experimental_cpp_component)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(simple_cmux_client)
|
||||
|
||||
|
17
components/esp_modem/examples/simple_cmux_client/README.md
Normal file
17
components/esp_modem/examples/simple_cmux_client/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Simple example of esp_modem component
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## Overview
|
||||
|
||||
This example demonstrates the use of the [esp-modem component](https://components.espressif.com/component/espressif/esp_modem) to connect to a network and send some AT commands.
|
||||
It uses modem CMUX mode so that commands and network could be used at the same time.
|
||||
|
||||
The example uses the following configuration options to demonstrate basic esp-modem capabilities:
|
||||
* `EXAMPLE_NEED_SIM_PIN`: To unlock the SIM card with a PIN code if needed
|
||||
* `EXAMPLE_PERFORM_OTA`: To start simple OTA at the end of the example to exercise basic CMUX/modem networking. Please note that the option `CONFIG_UART_ISR_IN_IRAM` is not enabled automatically, so that buffer overflows are expected and CMUX/PPP and networking should recover.
|
||||
* `EXAMPLE_USE_VFS_TERM`: To demonstrate using an abstract file descriptor to talk to the device (instead of the UART driver directly). This option could be used when implementing a custom VFS driver.
|
||||
|
||||
## About the esp_modem
|
||||
|
||||
Please check the component [README](../../README.md)
|
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "simple_client.cpp" "simple_mqtt_client.cpp"
|
||||
INCLUDE_DIRS ".")
|
@ -0,0 +1,64 @@
|
||||
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 a Multi-Band LTE-TDD/LTE-FDD/HSPA+ and GSM/GPRS/EDGE module.
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_MODEM_PPP_APN
|
||||
string "Set MODEM APN"
|
||||
default "internet"
|
||||
help
|
||||
Set APN (Access Point Name), a logical name to choose data network
|
||||
|
||||
config EXAMPLE_NEED_SIM_PIN
|
||||
bool "SIM PIN needed"
|
||||
default n
|
||||
help
|
||||
Enable to set SIM PIN before starting the example
|
||||
|
||||
config EXAMPLE_SIM_PIN
|
||||
string "Set SIM PIN"
|
||||
default "1234"
|
||||
depends on EXAMPLE_NEED_SIM_PIN
|
||||
help
|
||||
Pin to unlock the SIM
|
||||
|
||||
config EXAMPLE_USE_VFS_TERM
|
||||
bool "Use VFS terminal"
|
||||
default n
|
||||
help
|
||||
Demonstrate use of VFS as a communication terminal of the DTE.
|
||||
VFS driver implements non-block reads, writes and selects to communicate with esp-modem,
|
||||
but this implementation uses UART resource only.
|
||||
|
||||
config EXAMPLE_PERFORM_OTA
|
||||
bool "Perform OTA in the example"
|
||||
default n
|
||||
help
|
||||
Perform the OTA update after connecting to the network and mqtt broker.
|
||||
This option is used only to exercise network stability in CMUX mode.
|
||||
|
||||
config EXAMPLE_PERFORM_OTA_URI
|
||||
string "URI of the binary"
|
||||
default "https://my.code/esp32.bin"
|
||||
depends on EXAMPLE_PERFORM_OTA
|
||||
help
|
||||
HTTPS address of the update binary.
|
||||
|
||||
endmenu
|
@ -0,0 +1,167 @@
|
||||
/* 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 <cstring>
|
||||
#include <iostream>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_log.h"
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_modem_config.h"
|
||||
#include "cxx_include/esp_modem_api.hpp"
|
||||
#include "esp_event_cxx.hpp"
|
||||
#include "simple_mqtt_client.hpp"
|
||||
#include "esp_vfs_dev.h" // For optional VFS support
|
||||
#include "esp_https_ota.h" // For potential OTA configuration
|
||||
|
||||
|
||||
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io"
|
||||
|
||||
|
||||
using namespace esp_modem;
|
||||
using namespace idf::event;
|
||||
|
||||
|
||||
static const char *TAG = "cmux_example";
|
||||
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
/* Init and register system/core components */
|
||||
auto loop = std::make_shared<ESPEventLoop>();
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
|
||||
/* Configure and create the DTE */
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
#if CONFIG_EXAMPLE_USE_VFS_TERM == 1
|
||||
/* The VFS terminal is just a demonstration of using an abstract file descriptor
|
||||
* which implements non-block reads, writes and selects to communicate with esp-modem.
|
||||
* This configuration uses the same UART driver as the terminal created by `create_uart_dte()`,
|
||||
* so doesn't give any practical benefit besides the FD use demonstration and a placeholder
|
||||
* to use FD terminal for other devices
|
||||
*/
|
||||
dte_config.vfs_config.dev_name = "/dev/uart/1";
|
||||
dte_config.vfs_config.resource = ESP_MODEM_VFS_IS_UART;
|
||||
dte_config.uart_config.event_queue_size = 0;
|
||||
auto dte = create_vfs_dte(&dte_config);
|
||||
esp_vfs_dev_uart_use_driver(dte_config.uart_config.port_num);
|
||||
#else
|
||||
auto dte = create_uart_dte(&dte_config);
|
||||
#endif // CONFIG_EXAMPLE_USE_VFS_TERM
|
||||
assert(dte);
|
||||
|
||||
/* Configure the DCE */
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
|
||||
|
||||
/* Configure the PPP netif */
|
||||
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
||||
|
||||
/* Create the PPP and DCE objects */
|
||||
|
||||
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
|
||||
assert(esp_netif);
|
||||
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
|
||||
std::unique_ptr<DCE> dce = create_BG96_dce(&dce_config, dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM800 == 1
|
||||
std::unique_ptr<DCE> dce = create_SIM800_dce(&dce_config, uart_dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
|
||||
std::unique_ptr<DCE> dce = create_SIM7600_dce(&dce_config, uart_dte, esp_netif);
|
||||
#else
|
||||
#error "Unsupported device"
|
||||
#endif
|
||||
assert(dce);
|
||||
|
||||
/* Setup basic operation mode for the DCE (pin if used, CMUX mode) */
|
||||
#if CONFIG_EXAMPLE_NEED_SIM_PIN == 1
|
||||
bool pin_ok = true;
|
||||
if (dce->read_pin(pin_ok) == command_result::OK && !pin_ok) {
|
||||
throw_if_false(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000)); // Need to wait for some time after unlocking the SIM
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dce->set_mode(esp_modem::modem_mode::CMUX_MODE) && dce->set_mode(esp_modem::modem_mode::DATA_MODE)) {
|
||||
std::cout << "Modem has correctly entered multiplexed command/data mode" << std::endl;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to configure desired mode... exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read some data from the modem */
|
||||
std::string str;
|
||||
while (dce->get_operator_name(str) != esp_modem::command_result::OK) {
|
||||
// Getting operator name could fail... retry after 500 ms
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
std::cout << "Operator name:" << str << std::endl;
|
||||
|
||||
/* Try to connect to the network and publish an mqtt topic */
|
||||
ESPEventHandlerSync event_handler(loop);
|
||||
event_handler.listen_to(ESPEvent(IP_EVENT, ESPEventID(ESP_EVENT_ANY_ID)));
|
||||
auto result = event_handler.wait_event_for(std::chrono::milliseconds(60000));
|
||||
if (result.timeout) {
|
||||
ESP_LOGE(TAG, "Cannot get IP within specified timeout... exiting");
|
||||
return;
|
||||
} else if (result.event.id == ESPEventID(IP_EVENT_PPP_GOT_IP)) {
|
||||
auto *event = (ip_event_got_ip_t *)result.ev_data;
|
||||
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));
|
||||
std::cout << "Got IP address" << std::endl;
|
||||
|
||||
/* When connected to network, subscribe and publish some MQTT data */
|
||||
MqttClient mqtt(BROKER_URL);
|
||||
event_handler.listen_to(MqttClient::get_event(MqttClient::Event::CONNECT));
|
||||
event_handler.listen_to(MqttClient::get_event(MqttClient::Event::DATA));
|
||||
|
||||
auto reg = loop->register_event(MqttClient::get_event(MqttClient::Event::DATA),
|
||||
[&mqtt](const ESPEvent &event, void *data) {
|
||||
std::cout << " TOPIC:" << mqtt.get_topic(data) << std::endl;
|
||||
std::cout << " DATA:" << mqtt.get_data(data) << std::endl;
|
||||
});
|
||||
mqtt.connect();
|
||||
while (true) {
|
||||
result = event_handler.wait_event_for(std::chrono::milliseconds(60000));
|
||||
if (result.event == MqttClient::get_event(MqttClient::Event::CONNECT)) {
|
||||
mqtt.subscribe("/topic/esp-modem");
|
||||
mqtt.publish("/topic/esp-modem", "Hello modem");
|
||||
continue;
|
||||
} else if (result.event == MqttClient::get_event(MqttClient::Event::DATA)) {
|
||||
std::cout << "Data received" << std::endl;
|
||||
break; /* Continue with CMUX example after getting data from MQTT */
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (result.event.id == ESPEventID(IP_EVENT_PPP_LOST_IP)) {
|
||||
ESP_LOGE(TAG, "PPP client has lost connection... exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Again reading some data from the modem */
|
||||
if (dce->get_imsi(str) == esp_modem::command_result::OK) {
|
||||
std::cout << "Modem IMSI number:" << str << std::endl;
|
||||
}
|
||||
|
||||
#if CONFIG_EXAMPLE_PERFORM_OTA == 1
|
||||
esp_http_client_config_t config = { };
|
||||
config.skip_cert_common_name_check = true;
|
||||
config.url = CONFIG_EXAMPLE_PERFORM_OTA_URI;
|
||||
|
||||
esp_err_t ret = esp_https_ota(&config);
|
||||
if (ret == ESP_OK) {
|
||||
esp_restart();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Firmware upgrade failed");
|
||||
return;
|
||||
}
|
||||
#endif // CONFIG_EXAMPLE_PERFORM_OTA
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/* 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 <memory>
|
||||
#include "mqtt_client.h"
|
||||
#include "esp_event_cxx.hpp"
|
||||
#include "simple_mqtt_client.hpp"
|
||||
|
||||
using namespace idf::event;
|
||||
|
||||
/**
|
||||
* Reference to the MQTT event base
|
||||
*/
|
||||
ESP_EVENT_DECLARE_BASE(MQTT_EVENTS);
|
||||
|
||||
/**
|
||||
* Thin wrapper around C mqtt_client
|
||||
*/
|
||||
struct MqttClientHandle
|
||||
{
|
||||
explicit MqttClientHandle(const std::string & uri)
|
||||
{
|
||||
esp_mqtt_client_config_t config = { };
|
||||
config.uri = uri.c_str();
|
||||
client = esp_mqtt_client_init(&config);
|
||||
esp_mqtt_client_register_event(client, MQTT_EVENT_ANY, mqtt_event_handler, this);
|
||||
}
|
||||
|
||||
~MqttClientHandle()
|
||||
{
|
||||
esp_mqtt_client_destroy(client);
|
||||
}
|
||||
|
||||
static void mqtt_event_handler(void *args, esp_event_base_t base, int32_t id, void *data)
|
||||
{
|
||||
// forwards the internal event to the global ESPEvent
|
||||
esp_event_post(base, id, data, sizeof(esp_mqtt_event_t), portMAX_DELAY);
|
||||
}
|
||||
|
||||
esp_mqtt_client_handle_t client;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Definitions of MqttClient methods
|
||||
*/
|
||||
MqttClient::MqttClient(const std::string & uri):
|
||||
h(std::unique_ptr<MqttClientHandle>(new MqttClientHandle(uri)))
|
||||
{}
|
||||
|
||||
void MqttClient::connect()
|
||||
{
|
||||
esp_mqtt_client_start(h->client);
|
||||
}
|
||||
|
||||
idf::event::ESPEvent MqttClient::get_event(MqttClient::Event ev)
|
||||
{
|
||||
switch (ev) {
|
||||
case Event::CONNECT: {
|
||||
return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_CONNECTED) };
|
||||
}
|
||||
case Event::DATA:
|
||||
return { MQTT_EVENTS, ESPEventID(MQTT_EVENT_DATA) };
|
||||
}
|
||||
return { };
|
||||
}
|
||||
|
||||
int MqttClient::publish(const std::string &topic, const std::string &data, int qos)
|
||||
{
|
||||
return esp_mqtt_client_publish(h->client, topic.c_str(), data.c_str(), 0, qos, 0);
|
||||
}
|
||||
|
||||
int MqttClient::subscribe(const std::string &topic, int qos)
|
||||
{
|
||||
return esp_mqtt_client_subscribe(h->client, topic.c_str(), qos);
|
||||
}
|
||||
|
||||
std::string MqttClient::get_topic(void * event_data)
|
||||
{
|
||||
auto event = (esp_mqtt_event_handle_t)event_data;
|
||||
if (event == nullptr || event->client != h->client)
|
||||
return {};
|
||||
|
||||
return std::string(event->topic, event->topic_len);
|
||||
}
|
||||
|
||||
std::string MqttClient::get_data(void * event_data)
|
||||
{
|
||||
auto event = (esp_mqtt_event_handle_t)event_data;
|
||||
if (event == nullptr || event->client != h->client)
|
||||
return {};
|
||||
|
||||
return std::string(event->data, event->data_len);
|
||||
}
|
||||
|
||||
MqttClient::~MqttClient() = default;
|
@ -0,0 +1,77 @@
|
||||
/* 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.
|
||||
*/
|
||||
#ifndef _SIMPLE_MQTT_CLIENT_H_
|
||||
#define _SIMPLE_MQTT_CLIENT_H_
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "esp_event_cxx.hpp"
|
||||
|
||||
struct MqttClientHandle;
|
||||
|
||||
/**
|
||||
* @brief Simple MQTT client wrapper
|
||||
*/
|
||||
class MqttClient {
|
||||
public:
|
||||
enum class Event {
|
||||
CONNECT,
|
||||
DATA,
|
||||
};
|
||||
|
||||
explicit MqttClient(const std::string & uri);
|
||||
~MqttClient();
|
||||
|
||||
/**
|
||||
* @brief Start the mqtt-client
|
||||
*/
|
||||
void connect();
|
||||
|
||||
/**
|
||||
* @brief Publish to topic
|
||||
* @param topic Topic to publish
|
||||
* @param data Data to publish
|
||||
* @param qos QoS (0 by default)
|
||||
* @return message id
|
||||
*/
|
||||
int publish(const std::string & topic, const std::string & data, int qos = 0);
|
||||
|
||||
/**
|
||||
* @brief Subscribe to a topic
|
||||
* @param topic Topic to subscribe
|
||||
* @param qos QoS (0 by default)
|
||||
* @return message id
|
||||
*/
|
||||
int subscribe(const std::string & topic, int qos = 0);
|
||||
|
||||
/**
|
||||
* @brief Get topic from event data
|
||||
* @return String topic
|
||||
*/
|
||||
std::string get_topic(void *);
|
||||
|
||||
/**
|
||||
* @brief Get published data from event
|
||||
* @return String representation of the data
|
||||
*/
|
||||
std::string get_data(void *);
|
||||
|
||||
/**
|
||||
* @brief Convert internal MQTT event to standard ESPEvent
|
||||
* @param ev internal mqtt event
|
||||
* @return corresponding ESPEvent
|
||||
*/
|
||||
static idf::event::ESPEvent get_event(Event ev);
|
||||
|
||||
private:
|
||||
std::unique_ptr<MqttClientHandle> h;
|
||||
};
|
||||
|
||||
|
||||
#endif //_SIMPLE_MQTT_CLIENT_H_
|
@ -0,0 +1,10 @@
|
||||
# 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
|
||||
CONFIG_LWIP_PPP_ENABLE_IPV6=n
|
||||
CONFIG_COMPILER_CXX_EXCEPTIONS=y
|
||||
CONFIG_PARTITION_TABLE_TWO_OTA=y
|
||||
CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF=y
|
||||
CONFIG_NEWLIB_STDIN_LINE_ENDING_LF=y
|
6
components/esp_modem/idf_component.yml
Normal file
6
components/esp_modem/idf_component.yml
Normal file
@ -0,0 +1,6 @@
|
||||
version: "0.1.5"
|
||||
description: esp modem
|
||||
dependencies:
|
||||
# Required IDF version
|
||||
idf:
|
||||
version: ">=4.1"
|
107
components/esp_modem/include/cxx_include/esp_modem_api.hpp
Normal file
107
components/esp_modem/include/cxx_include/esp_modem_api.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_API_HPP_
|
||||
#define _ESP_MODEM_API_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include "cxx_include/esp_modem_dce.hpp"
|
||||
#include "cxx_include/esp_modem_dce_module.hpp"
|
||||
|
||||
struct esp_modem_dte_config;
|
||||
struct esp_modem_dce_config;
|
||||
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
class DTE;
|
||||
typedef struct esp_netif_obj esp_netif_t;
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_INIT_DTE ESP_MODEM Initialization API for DTE
|
||||
* @brief Create DTE's
|
||||
*/
|
||||
/** @addtogroup ESP_MODEM_INIT_DTE
|
||||
* @{
|
||||
*/
|
||||
|
||||
using dce_config = ::esp_modem_dce_config;
|
||||
using dte_config = ::esp_modem_dte_config;
|
||||
|
||||
/**
|
||||
* @brief Create UART DTE
|
||||
* @param config DTE configuration
|
||||
* @return shared ptr to DTE on success
|
||||
* nullptr on failure (either due to insufficient memory or wrong dte configuration)
|
||||
* if exceptions are disabled the API abort()'s on error
|
||||
*/
|
||||
std::shared_ptr<DTE> create_uart_dte(const dte_config *config);
|
||||
|
||||
/**
|
||||
* @brief Create VFS DTE
|
||||
* @param config DTE configuration
|
||||
* @return shared ptr to DTE on success
|
||||
* nullptr on failure (either due to insufficient memory or wrong dte configuration)
|
||||
* if exceptions are disabled the API abort()'s on error
|
||||
*/
|
||||
std::shared_ptr<DTE> create_vfs_dte(const dte_config *config);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_INIT_DCE ESP_MODEM Initialization API for DCE
|
||||
* @brief ESP_MODEM Initialization API for DCE
|
||||
*/
|
||||
/** @addtogroup ESP_MODEM_INIT_DCE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Create DCE based on SIM7600 module
|
||||
* @param config DCE configuration
|
||||
* @param DTE reference to the communicating DTE
|
||||
* @param netif reference to the network interface
|
||||
*
|
||||
* @return unique ptr to the created DCE on success
|
||||
* nullptr on failure
|
||||
* if exceptions are disabled the API abort()'s on error
|
||||
*/
|
||||
std::unique_ptr<DCE> create_SIM7600_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @brief Create DCE based on SIM800 module
|
||||
*/
|
||||
std::unique_ptr<DCE> create_SIM800_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @brief Create DCE based on BG96 module
|
||||
*/
|
||||
std::unique_ptr<DCE> create_BG96_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @brief Create generic DCE
|
||||
*/
|
||||
std::unique_ptr<DCE> create_generic_dce(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_API_HPP_
|
112
components/esp_modem/include/cxx_include/esp_modem_cmux.hpp
Normal file
112
components/esp_modem/include/cxx_include/esp_modem_cmux.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_CMUX_HPP_
|
||||
#define _ESP_MODEM_CMUX_HPP_
|
||||
|
||||
#include "esp_modem_terminal.hpp"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
constexpr size_t max_terms = 2;
|
||||
/**
|
||||
* @defgroup ESP_MODEM_CMUX ESP_MODEM CMUX class
|
||||
* @brief Definition of CMUX terminal
|
||||
*/
|
||||
/** @addtogroup ESP_MODEM_CMUX
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief CMUX state machine
|
||||
*/
|
||||
enum class cmux_state {
|
||||
INIT,
|
||||
HEADER,
|
||||
PAYLOAD,
|
||||
FOOTER,
|
||||
RECOVER,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief CMUX terminal abstraction
|
||||
*
|
||||
* This class inherits from Terminal class, as it is a Terminal, but is also composed of another Terminal,
|
||||
* which is used to communicate with the modem, i.e. the original Terminal which has been multiplexed.
|
||||
*
|
||||
* @note Implementation of CMUX protocol is experimental
|
||||
*/
|
||||
class CMuxInstance;
|
||||
|
||||
/**
|
||||
* @brief CMux class which consumes the original terminal and creates multiple virtual terminals from it.
|
||||
* This class is not usable applicable as a DTE terminal
|
||||
*/
|
||||
class CMux {
|
||||
public:
|
||||
explicit CMux(std::unique_ptr<Terminal> t, std::unique_ptr<uint8_t[]> b, size_t buff_size):
|
||||
term(std::move(t)), buffer_size(buff_size), buffer(std::move(b)), payload_start(nullptr), total_payload_size(0) {}
|
||||
~CMux() = default;
|
||||
[[nodiscard]] bool init();
|
||||
void set_read_cb(int inst, std::function<bool(uint8_t *data, size_t len)> f);
|
||||
|
||||
int write(int i, uint8_t *data, size_t len);
|
||||
private:
|
||||
std::function<bool(uint8_t *data, size_t len)> read_cb[max_terms];
|
||||
void data_available(uint8_t *data, size_t len);
|
||||
void send_sabm(size_t i);
|
||||
std::unique_ptr<Terminal> term;
|
||||
cmux_state state;
|
||||
uint8_t dlci;
|
||||
uint8_t type;
|
||||
size_t payload_len;
|
||||
uint8_t frame_header[6];
|
||||
size_t frame_header_offset;
|
||||
size_t buffer_size;
|
||||
std::unique_ptr<uint8_t[]> buffer;
|
||||
bool on_cmux(uint8_t *data, size_t len);
|
||||
static uint8_t fcs_crc(const uint8_t frame[6]);
|
||||
Lock lock;
|
||||
int instance;
|
||||
int sabm_ack;
|
||||
uint8_t *payload_start;
|
||||
size_t total_payload_size;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This represents a specific instance of a CMUX virtual terminal. This class also implements Terminal interface
|
||||
* and as such could be used as a DTE's terminal.
|
||||
*/
|
||||
class CMuxInstance: public Terminal {
|
||||
public:
|
||||
explicit CMuxInstance(std::shared_ptr<CMux> parent, int i): cmux(std::move(parent)), instance(i) {}
|
||||
|
||||
int write(uint8_t *data, size_t len) override { return cmux->write(instance, data, len); }
|
||||
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) override { return cmux->set_read_cb(instance, std::move(f)); }
|
||||
int read(uint8_t *data, size_t len) override { return 0; }
|
||||
void start() override { }
|
||||
void stop() override { }
|
||||
private:
|
||||
std::shared_ptr<CMux> cmux;
|
||||
int instance;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_CMUX_HPP_
|
@ -0,0 +1,59 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_COMMAND_LIBRARY_HPP_
|
||||
#define _ESP_MODEM_COMMAND_LIBRARY_HPP_
|
||||
|
||||
#include "esp_modem_dte.hpp"
|
||||
#include "esp_modem_dce_module.hpp"
|
||||
#include "esp_modem_types.hpp"
|
||||
#include "generate/esp_modem_command_declare.inc"
|
||||
|
||||
namespace esp_modem {
|
||||
namespace dce_commands {
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_DCE_COMMAND ESP_MODEM DCE command library
|
||||
* @brief Library of the most useful DCE commands
|
||||
*/
|
||||
/** @addtogroup ESP_MODEM_DCE_COMMAND
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Declaration of all commands is generated from esp_modem_command_declare.inc
|
||||
*/
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
|
||||
return_type name(CommandableIf *t, ## __VA_ARGS__);
|
||||
|
||||
DECLARE_ALL_COMMAND_APIS(declare name(Commandable *p, ...);)
|
||||
|
||||
#undef ESP_MODEM_DECLARE_DCE_COMMAND
|
||||
|
||||
/**
|
||||
* @brief Following commands that are different for some specific modules
|
||||
*/
|
||||
command_result get_battery_status_sim7xxx(CommandableIf* t, int& voltage, int &bcs, int &bcl);
|
||||
command_result power_down_sim7xxx(CommandableIf* t);
|
||||
command_result power_down_sim8xx(CommandableIf* t);
|
||||
command_result set_data_mode_sim8xx(CommandableIf* t);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // dce_commands
|
||||
} // esp_modem
|
||||
|
||||
#endif //_ESP_MODEM_COMMAND_LIBRARY_HPP_
|
114
components/esp_modem/include/cxx_include/esp_modem_dce.hpp
Normal file
114
components/esp_modem/include/cxx_include/esp_modem_dce.hpp
Normal file
@ -0,0 +1,114 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_DCE_HPP_
|
||||
#define _ESP_MODEM_DCE_HPP_
|
||||
|
||||
#include <utility>
|
||||
#include "cxx_include/esp_modem_netif.hpp"
|
||||
#include "cxx_include/esp_modem_dce_module.hpp"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_DCE
|
||||
* @brief Definition of DCE abstraction
|
||||
*/
|
||||
/** @addtogroup ESP_MODEM_DCE
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Helper class responsible for switching modes of the DCE's
|
||||
*/
|
||||
class DCE_Mode {
|
||||
public:
|
||||
DCE_Mode(): mode(modem_mode::COMMAND_MODE) {}
|
||||
~DCE_Mode() = default;
|
||||
bool set(DTE *dte, ModuleIf *module, Netif &netif, modem_mode m);
|
||||
modem_mode get();
|
||||
|
||||
private:
|
||||
modem_mode mode;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief General DCE class templated on a specific module. It is responsible for all the necessary transactions
|
||||
* related to switching modes and consequent synergy with aggregated objects of DTE, Netif and a specific Module
|
||||
*/
|
||||
template<class SpecificModule>
|
||||
class DCE_T {
|
||||
static_assert(std::is_base_of<ModuleIf, SpecificModule>::value, "DCE must be instantiated with Module class only");
|
||||
public:
|
||||
explicit DCE_T(const std::shared_ptr<DTE>& dte, std::shared_ptr<SpecificModule> dev, esp_netif_t * netif):
|
||||
dte(dte), device(std::move(dev)), netif(dte, netif)
|
||||
{ }
|
||||
|
||||
~DCE_T() = default;
|
||||
|
||||
/**
|
||||
* @brief Set data mode!
|
||||
*/
|
||||
void set_data() { set_mode(modem_mode::DATA_MODE); }
|
||||
|
||||
void exit_data() { set_mode(modem_mode::COMMAND_MODE); }
|
||||
|
||||
void set_cmux() { set_mode(modem_mode::CMUX_MODE); }
|
||||
|
||||
SpecificModule* get_module() { return device.get(); }
|
||||
|
||||
command_result command(const std::string& command, got_line_cb got_line, uint32_t time_ms)
|
||||
{
|
||||
return dte->command(command, std::move(got_line), time_ms);
|
||||
}
|
||||
|
||||
bool set_mode(modem_mode m) { return mode.set(dte.get(), device.get(), netif, m); }
|
||||
|
||||
protected:
|
||||
std::shared_ptr<DTE> dte;
|
||||
std::shared_ptr<SpecificModule> device;
|
||||
Netif netif;
|
||||
DCE_Mode mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Common abstraction of the modem DCE, specialized by the GenericModule which is a parent class for the supported
|
||||
* defices and most common modems, as well.
|
||||
*/
|
||||
class DCE: public DCE_T<GenericModule> {
|
||||
public:
|
||||
|
||||
using DCE_T<GenericModule>::DCE_T;
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
|
||||
template <typename ...Agrs> \
|
||||
return_type name(Agrs&&... args) \
|
||||
{ \
|
||||
return device->name(std::forward<Agrs>(args)...); \
|
||||
}
|
||||
|
||||
DECLARE_ALL_COMMAND_APIS(forwards name(...) { device->name(...); } )
|
||||
|
||||
#undef ESP_MODEM_DECLARE_DCE_COMMAND
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_DCE_HPP_
|
@ -0,0 +1,249 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_DCE_FACTORY_HPP_
|
||||
#define _ESP_MODEM_DCE_FACTORY_HPP_
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_DCE_FACTORY
|
||||
* @brief DCE modem factory
|
||||
*/
|
||||
|
||||
|
||||
namespace esp_modem::dce_factory {
|
||||
|
||||
using config = ::esp_modem_dce_config;
|
||||
|
||||
/** @addtogroup ESP_MODEM_DCE_FACTORY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Helper class for creating a uder define pointer in a specific way, either as a plain pointer, shared_ptr or unique_ptr
|
||||
*/
|
||||
class FactoryHelper {
|
||||
public:
|
||||
static std::unique_ptr<PdpContext> create_pdp_context(std::string &apn);
|
||||
|
||||
template <typename T, typename Ptr, typename ...Args>
|
||||
static auto make(Args&&... args) -> typename std::enable_if<std::is_same<Ptr, T*>::value, T*>::type
|
||||
{
|
||||
return new T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename Ptr, typename ...Args>
|
||||
static auto make(Args&&... args) -> typename std::enable_if<std::is_same<Ptr, std::shared_ptr<T>>::value, std::shared_ptr<T>>::type
|
||||
{
|
||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename Ptr = std::unique_ptr<T>, typename ...Args>
|
||||
static auto make(Args&&... args) -> typename std::enable_if<std::is_same<Ptr, std::unique_ptr<T>>::value, std::unique_ptr<T>>::type
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Builder class for building a DCE_T<Module> in a specific way, either form a Module object or by default from the DTE and netif
|
||||
*/
|
||||
template<typename Module>
|
||||
class Builder {
|
||||
static_assert(std::is_base_of<ModuleIf, Module>::value, "Builder must be used only for Module classes");
|
||||
public:
|
||||
Builder(std::shared_ptr<DTE> x, esp_netif_t* esp_netif): dte(std::move(x)), device(nullptr), netif(esp_netif)
|
||||
{
|
||||
throw_if_false(netif != nullptr, "Null netif");
|
||||
}
|
||||
|
||||
Builder(std::shared_ptr<DTE> dte, esp_netif_t* esp_netif, std::shared_ptr<Module> dev): dte(std::move(dte)), device(std::move(dev)), netif(esp_netif)
|
||||
{
|
||||
throw_if_false(netif != nullptr, "Null netif");
|
||||
}
|
||||
|
||||
~Builder()
|
||||
{
|
||||
throw_if_false(device == nullptr, "module was captured or created but never used");
|
||||
}
|
||||
|
||||
template<typename Ptr>
|
||||
auto create_module(const esp_modem_dce_config *config) -> Ptr
|
||||
{
|
||||
return FactoryHelper::make<Module, Ptr>(dte, config);
|
||||
}
|
||||
|
||||
template<typename DceT, typename Ptr>
|
||||
auto create(const esp_modem_dce_config *config) -> Ptr
|
||||
{
|
||||
if (dte == nullptr)
|
||||
return nullptr;
|
||||
if (device == nullptr) {
|
||||
device = create_module<decltype(device)>(config);
|
||||
if (device == nullptr)
|
||||
return nullptr;
|
||||
}
|
||||
return FactoryHelper::make<DceT, Ptr>(std::move(dte), std::move(device), netif);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DTE> dte;
|
||||
std::shared_ptr<Module> device;
|
||||
esp_netif_t *netif;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specific modem choice when creating by the Factory
|
||||
*/
|
||||
enum class Modem {
|
||||
GenericModule, /*!< Default generic module with the most common commands */
|
||||
SIM7600, /*!< Derived from the GenericModule, specifics applied to SIM7600 model */
|
||||
BG96, /*!< Derived from the GenericModule, specifics applied to BG69 model */
|
||||
SIM800, /*!< Derived from the GenericModule with specifics applied to SIM800 model */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Factory class for creating virtual DCE objects based on the configuration of the supplied module.
|
||||
* This could also be used to create a custom module or a DCE_T<module>, provided user app derives from this factory.
|
||||
*/
|
||||
class Factory {
|
||||
public:
|
||||
explicit Factory(Modem modem): m(modem) {}
|
||||
|
||||
/**
|
||||
* @brief Create a default unique_ptr DCE in a specific way (from the module)
|
||||
* @tparam Module Specific Module used in this DCE
|
||||
* @tparam Args Arguments to the builder, i.e. constructor of esp_modem::DCE_T class
|
||||
* @param cfg DCE configuration structure ::esp_modem_dte_config
|
||||
* @param args typically a DTE object and a netif handle for PPP network
|
||||
* @return unique_ptr DCE of the created DCE on success
|
||||
*/
|
||||
template <typename Module, typename ...Args>
|
||||
static std::unique_ptr<DCE> build_unique(const config *cfg, Args&&... args)
|
||||
{
|
||||
return build_generic_DCE<Module, DCE, std::unique_ptr<DCE>>(cfg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a DCE
|
||||
* @tparam Module Specific Module used in this DCE
|
||||
* @tparam Args Arguments to the builder, i.e. constructor of esp_modem::DCE_T class
|
||||
* @param cfg DCE configuration structure ::esp_modem_dte_config
|
||||
* @param args typically a DTE object and a netif handle for PPP network
|
||||
* @return DCE pointer the created DCE on success
|
||||
*/
|
||||
template <typename Module, typename ...Args>
|
||||
static DCE* build(const config *cfg, Args&&... args)
|
||||
{
|
||||
return build_generic_DCE<Module, DCE>(cfg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
template <typename Module, typename ...Args>
|
||||
static std::shared_ptr<Module> build_shared_module(const config *cfg, Args&&... args)
|
||||
{
|
||||
return build_module_T<Module>(cfg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
template <typename ...Args>
|
||||
std::shared_ptr<GenericModule> build_shared_module(const config *cfg, Args&&... args)
|
||||
{
|
||||
switch (m) {
|
||||
case Modem::SIM800:
|
||||
return build_shared_module<SIM800>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::SIM7600:
|
||||
return build_shared_module<SIM7600>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::BG96:
|
||||
return build_shared_module<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::GenericModule:
|
||||
return build_shared_module<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a default unique_ptr DCE generically, with the chosen module derived from the GenericModule
|
||||
* @tparam Args Arguments to the builder, i.e. constructor of esp_modem::DCE_T class
|
||||
* @param cfg DCE configuration structure ::esp_modem_dte_config
|
||||
* @param args typically a DTE object and a netif handle for PPP network
|
||||
* @return unique_ptr DCE of the created DCE on success
|
||||
*/
|
||||
template <typename ...Args>
|
||||
std::unique_ptr<DCE> build_unique(const config *cfg, Args&&... args)
|
||||
{
|
||||
switch (m) {
|
||||
case Modem::SIM800:
|
||||
return build_unique<SIM800>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::SIM7600:
|
||||
return build_unique<SIM7600>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::BG96:
|
||||
return build_unique<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::GenericModule:
|
||||
return build_unique<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
DCE* build(const config *cfg, Args&&... args)
|
||||
{
|
||||
switch (m) {
|
||||
case Modem::SIM800:
|
||||
return build<SIM800>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::SIM7600:
|
||||
return build<SIM7600>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::BG96:
|
||||
return build<BG96>(cfg, std::forward<Args>(args)...);
|
||||
case Modem::GenericModule:
|
||||
return build<GenericModule>(cfg, std::forward<Args>(args)...);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Modem m;
|
||||
|
||||
protected:
|
||||
template <typename Module, typename Ptr = std::shared_ptr<Module>, typename ...Args>
|
||||
static Ptr build_module_T(const config *cfg, Args&&... args)
|
||||
{
|
||||
Builder<Module> b(std::forward<Args>(args)...);
|
||||
return b.template create_module<Ptr>(cfg);
|
||||
}
|
||||
|
||||
|
||||
template <typename Module, typename Dce = DCE_T<Module>, typename DcePtr = Dce*, typename ...Args>
|
||||
static DcePtr build_generic_DCE(const config *cfg, Args&&... args)
|
||||
{
|
||||
Builder<Module> b(std::forward<Args>(args)...);
|
||||
return b.template create<Dce, DcePtr>(cfg);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace esp_modem::dce_factory
|
||||
|
||||
|
||||
#endif // _ESP_MODEM_DCE_FACTORY_HPP_
|
@ -0,0 +1,150 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_DCE_MODULE_
|
||||
#define _ESP_MODEM_DCE_MODULE_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include "generate/esp_modem_command_declare.inc"
|
||||
#include "cxx_include/esp_modem_command_library.hpp"
|
||||
#include "cxx_include/esp_modem_types.hpp"
|
||||
#include "esp_modem_dce_config.h"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_MODULE
|
||||
* @brief Definition of modules representing specific modem devices
|
||||
*/
|
||||
|
||||
/** @addtogroup ESP_MODEM_MODULE
|
||||
* @{
|
||||
*/
|
||||
|
||||
enum class command_result;
|
||||
class DTE;
|
||||
struct PdpContext;
|
||||
|
||||
/**
|
||||
* @brief This is a basic building block for custom modules as well as for the supported modules in the esp-modem component
|
||||
* It derives from the ModuleIf.
|
||||
*/
|
||||
class GenericModule: public ModuleIf {
|
||||
public:
|
||||
/**
|
||||
* @brief We can construct a generic device with an existent DTE and it's configuration
|
||||
* The configuration could be either the dce-config struct or just a pdp context
|
||||
*/
|
||||
explicit GenericModule(std::shared_ptr<DTE> dte, std::unique_ptr<PdpContext> pdp):
|
||||
dte(std::move(dte)), pdp(std::move(pdp)) {}
|
||||
explicit GenericModule(std::shared_ptr<DTE> dte, const esp_modem_dce_config* config);
|
||||
|
||||
/**
|
||||
* @brief This is a mandatory method for ModuleIf class, which sets up the device
|
||||
* to be able to connect to the network. This typically consists of setting basic
|
||||
* communication parameters and setting the PDP (defining logical access point
|
||||
* to cellular network)
|
||||
*/
|
||||
bool setup_data_mode() override
|
||||
{
|
||||
if (set_echo(false) != command_result::OK)
|
||||
return false;
|
||||
if (set_pdp_context(*pdp) != command_result::OK)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This is a mandatory method of ModuleIf class, which defines
|
||||
* basic commands for switching between DATA, COMMAND and CMUX modes
|
||||
*/
|
||||
bool set_mode(modem_mode mode) override
|
||||
{
|
||||
if (mode == modem_mode::DATA_MODE) {
|
||||
if (set_data_mode() != command_result::OK)
|
||||
return resume_data_mode() == command_result::OK;
|
||||
return true;
|
||||
} else if (mode == modem_mode::COMMAND_MODE) {
|
||||
return set_command_mode() == command_result::OK;
|
||||
} else if (mode == modem_mode::CMUX_MODE) {
|
||||
return set_cmux() == command_result::OK;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Additional method providing runtime configuration of PDP context
|
||||
*/
|
||||
void configure_pdp_context(std::unique_ptr<PdpContext> new_pdp)
|
||||
{
|
||||
pdp = std::move(new_pdp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common DCE commands generated from the API AT list
|
||||
*/
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
|
||||
virtual return_type name(__VA_ARGS__);
|
||||
|
||||
DECLARE_ALL_COMMAND_APIS(virtual return_type name(...); )
|
||||
|
||||
#undef ESP_MODEM_DECLARE_DCE_COMMAND
|
||||
|
||||
|
||||
protected:
|
||||
std::shared_ptr<DTE> dte; /*!< Generic device needs the DTE as a channel talk to the module using AT commands */
|
||||
std::unique_ptr<PdpContext> pdp; /*!< It also needs a PDP data, const information used for setting up cellular network */
|
||||
};
|
||||
|
||||
// Definitions of other supported modules with some specific commands overwritten
|
||||
|
||||
/**
|
||||
* @brief Specific definition of the SIM7600 module
|
||||
*/
|
||||
class SIM7600: public GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
public:
|
||||
command_result get_module_name(std::string& name) override;
|
||||
command_result get_battery_status(int& voltage, int &bcs, int &bcl) override;
|
||||
command_result power_down() override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specific definition of the SIM800 module
|
||||
*/
|
||||
class SIM800: public GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
public:
|
||||
command_result get_module_name(std::string& name) override;
|
||||
command_result power_down() override;
|
||||
command_result set_data_mode() override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Specific definition of the BG96 module
|
||||
*/
|
||||
class BG96: public GenericModule {
|
||||
using GenericModule::GenericModule;
|
||||
public:
|
||||
command_result get_module_name(std::string& name) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_DCE_MODULE_
|
121
components/esp_modem/include/cxx_include/esp_modem_dte.hpp
Normal file
121
components/esp_modem/include/cxx_include/esp_modem_dte.hpp
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_DTE_HPP_
|
||||
#define _ESP_MODEM_DTE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include "cxx_include/esp_modem_primitives.hpp"
|
||||
#include "cxx_include/esp_modem_terminal.hpp"
|
||||
#include "cxx_include/esp_modem_cmux.hpp"
|
||||
#include "cxx_include/esp_modem_types.hpp"
|
||||
|
||||
struct esp_modem_dte_config;
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_DTE
|
||||
* @brief Definition of DTE and related classes
|
||||
*/
|
||||
/** @addtogroup ESP_MODEM_DTE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* DTE (Data Terminal Equipment) class
|
||||
*/
|
||||
class DTE : public CommandableIf {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Creates a DTE instance from the terminal
|
||||
* @param config DTE config structure
|
||||
* @param t unique-ptr to Terminal
|
||||
*/
|
||||
explicit DTE(const esp_modem_dte_config *config, std::unique_ptr<Terminal> t);
|
||||
explicit DTE(std::unique_ptr<Terminal> t);
|
||||
|
||||
~DTE() = default;
|
||||
|
||||
/**
|
||||
* @brief Writing to the underlying terminal
|
||||
* @param data Data pointer to write
|
||||
* @param len Data len to write
|
||||
* @return number of bytes written
|
||||
*/
|
||||
int write(uint8_t *data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Reading from the underlying terminal
|
||||
* @param d Returning the data pointer of the received payload
|
||||
* @param len Length of the data payload
|
||||
* @return number of bytes read
|
||||
*/
|
||||
int read(uint8_t **d, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Sets read callback with valid data and length
|
||||
* @param f Function to be called on data available
|
||||
*/
|
||||
void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f);
|
||||
|
||||
/**
|
||||
* @brief Sets the DTE to desired mode (Command/Data/Cmux)
|
||||
* @param m Desired operation mode
|
||||
* @return true on success
|
||||
*/
|
||||
[[nodiscard]] bool set_mode(modem_mode m);
|
||||
|
||||
/**
|
||||
* @brief Sends command and provides callback with responding line
|
||||
* @param command String parameter representing command
|
||||
* @param got_line Function to be called after line available as a response
|
||||
* @param time_ms Time in ms to wait for the answer
|
||||
* @return OK, FAIL, TIMEOUT
|
||||
*/
|
||||
command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms) override;
|
||||
|
||||
/**
|
||||
* @brief Sends the command (same as above) but with a specific separator
|
||||
*/
|
||||
command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms, char separator) override;
|
||||
|
||||
private:
|
||||
static const size_t GOT_LINE = SignalGroup::bit0; /*!< Bit indicating response available */
|
||||
|
||||
[[nodiscard]] bool setup_cmux(); /*!< Internal setup of CMUX mode */
|
||||
|
||||
Lock lock{}; /*!< Locks DTE operations */
|
||||
size_t buffer_size; /*!< Size of available DTE buffer */
|
||||
size_t consumed; /*!< Indication of already processed portion in DTE buffer */
|
||||
std::unique_ptr<uint8_t[]> buffer; /*!< DTE buffer */
|
||||
std::unique_ptr<Terminal> term; /*!< Primary terminal for this DTE */
|
||||
Terminal *command_term; /*!< Reference to the terminal used for sending commands */
|
||||
std::unique_ptr<Terminal> other_term; /*!< Secondary terminal for this DTE */
|
||||
modem_mode mode; /*!< DTE operation mode */
|
||||
SignalGroup signal; /*!< Event group used to signal request-response operations */
|
||||
std::function<bool(uint8_t *data, size_t len)> on_data; /*!< on data callback for current terminal */
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_DTE_HPP_
|
@ -0,0 +1,66 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_EXCEPTION_HPP_
|
||||
#define _ESP_MODEM_EXCEPTION_HPP_
|
||||
|
||||
#include <string>
|
||||
#include "esp_err.h"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
#define THROW(exception) throw(exception)
|
||||
class esp_err_exception: virtual public std::exception {
|
||||
public:
|
||||
explicit esp_err_exception(esp_err_t err): esp_err(err) {}
|
||||
explicit esp_err_exception(std::string msg): esp_err(ESP_FAIL), message(std::move(msg)) {}
|
||||
explicit esp_err_exception(std::string msg, esp_err_t err): esp_err(err), message(std::move(msg)) {}
|
||||
virtual esp_err_t get_err_t() { return esp_err; }
|
||||
~esp_err_exception() noexcept override = default;
|
||||
virtual const char* what() const noexcept {
|
||||
return message.c_str();
|
||||
}
|
||||
private:
|
||||
esp_err_t esp_err;
|
||||
std::string message;
|
||||
};
|
||||
#else
|
||||
#define THROW(exception) abort()
|
||||
#endif
|
||||
|
||||
static inline void throw_if_false(bool condition, std::string message)
|
||||
{
|
||||
if (!condition) {
|
||||
THROW(esp_err_exception(std::move(message)));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void throw_if_esp_fail(esp_err_t err, std::string message)
|
||||
{
|
||||
if (err != ESP_OK) {
|
||||
THROW(esp_err_exception(std::move(message), err));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void throw_if_esp_fail(esp_err_t err)
|
||||
{
|
||||
if (err != ESP_OK) {
|
||||
THROW(esp_err_exception(err));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif //_ESP_MODEM_EXCEPTION_HPP_
|
89
components/esp_modem/include/cxx_include/esp_modem_netif.hpp
Normal file
89
components/esp_modem/include/cxx_include/esp_modem_netif.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_NETIF_HPP
|
||||
#define _ESP_MODEM_NETIF_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <cstddef>
|
||||
#include "esp_netif.h"
|
||||
#include "cxx_include/esp_modem_primitives.hpp"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
class DTE;
|
||||
class Netif;
|
||||
|
||||
struct ppp_netif_driver {
|
||||
esp_netif_driver_base_t base;
|
||||
Netif *ppp;
|
||||
};
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_NETIF
|
||||
* @brief Network interface layer of the esp-modem
|
||||
*/
|
||||
|
||||
/** @addtogroup ESP_MODEM_NETIF
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Network interface class responsible to glue the esp-netif to the modem's DCE
|
||||
*/
|
||||
class Netif {
|
||||
public:
|
||||
explicit Netif(std::shared_ptr<DTE> e, esp_netif_t *netif);
|
||||
|
||||
~Netif();
|
||||
|
||||
/**
|
||||
* @brief Start the network interface
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* @brief Blocks until the network interface closes
|
||||
*/
|
||||
void wait_until_ppp_exits();
|
||||
|
||||
/**
|
||||
* @brief Stop the network interface
|
||||
*/
|
||||
void stop();
|
||||
|
||||
private:
|
||||
void receive(uint8_t *data, size_t len);
|
||||
|
||||
static esp_err_t esp_modem_dte_transmit(void *h, void *buffer, size_t len);
|
||||
|
||||
static esp_err_t esp_modem_post_attach(esp_netif_t *esp_netif, void *args);
|
||||
|
||||
static void on_ppp_changed(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
|
||||
|
||||
std::shared_ptr<DTE> ppp_dte;
|
||||
esp_netif_t *netif;
|
||||
struct ppp_netif_driver driver{};
|
||||
SignalGroup signal;
|
||||
static const size_t PPP_STARTED = SignalGroup::bit0;
|
||||
static const size_t PPP_EXIT = SignalGroup::bit1;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_NETIF_HPP
|
@ -0,0 +1,106 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_PRIMITIVES_HPP_
|
||||
#define _ESP_MODEM_PRIMITIVES_HPP_
|
||||
#include "esp_modem_exception.hpp"
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_LINUX)
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#else
|
||||
// forward declarations of FreeRTOS primitives
|
||||
struct QueueDefinition;
|
||||
typedef void * EventGroupHandle_t;
|
||||
#endif
|
||||
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
// Forward declaration for both linux/FreeRTOS targets
|
||||
//
|
||||
using TaskFunction_t = void (*)(void*);
|
||||
#if !defined(CONFIG_IDF_TARGET_LINUX)
|
||||
struct Lock {
|
||||
using MutexT = QueueDefinition*;
|
||||
explicit Lock();
|
||||
~Lock();
|
||||
void lock();
|
||||
void unlock();
|
||||
private:
|
||||
MutexT m{};
|
||||
};
|
||||
using TaskT = void*;
|
||||
using SignalT = void*;
|
||||
#else
|
||||
using Lock = std::mutex;
|
||||
struct SignalGroupInternal;
|
||||
using SignalT = std::unique_ptr<SignalGroupInternal>;
|
||||
using TaskT = std::thread;
|
||||
static constexpr uint32_t portMAX_DELAY = UINT32_MAX;
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
class Scoped {
|
||||
public:
|
||||
explicit Scoped(T &l):lock(l) { lock.lock(); }
|
||||
~Scoped() { lock.unlock(); }
|
||||
|
||||
private:
|
||||
T& lock;
|
||||
};
|
||||
|
||||
class Task {
|
||||
public:
|
||||
explicit Task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t task_function);
|
||||
~Task();
|
||||
|
||||
static void Delete();
|
||||
static void Relinquish();
|
||||
private:
|
||||
TaskT task_handle;
|
||||
};
|
||||
|
||||
|
||||
class SignalGroup {
|
||||
public:
|
||||
static constexpr size_t bit0 = 1 << 0;
|
||||
static constexpr size_t bit1 = 1 << 1;
|
||||
static constexpr size_t bit2 = 1 << 2;
|
||||
static constexpr size_t bit3 = 1 << 3;
|
||||
|
||||
explicit SignalGroup();
|
||||
|
||||
void set(uint32_t bits);
|
||||
|
||||
void clear(uint32_t bits);
|
||||
|
||||
// waiting for all and clearing if set
|
||||
bool wait(uint32_t flags, uint32_t time_ms);
|
||||
|
||||
bool is_any(uint32_t flags);
|
||||
|
||||
// waiting for any bit, not clearing them
|
||||
bool wait_any(uint32_t flags, uint32_t time_ms);
|
||||
|
||||
~SignalGroup();
|
||||
|
||||
private:
|
||||
SignalT event_group;
|
||||
};
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_PRIMITIVES_HPP_
|
@ -0,0 +1,89 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_TERMINAL_HPP_
|
||||
#define _ESP_MODEM_TERMINAL_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <exception>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include "esp_err.h"
|
||||
#include "esp_modem_primitives.hpp"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_TERMINAL
|
||||
* @brief Definition of an abstract terminal to be attached to DTE class
|
||||
*/
|
||||
|
||||
/** @addtogroup ESP_MODEM_TERMINAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Terminal errors
|
||||
*/
|
||||
enum class terminal_error {
|
||||
BUFFER_OVERFLOW,
|
||||
CHECKSUM_ERROR,
|
||||
UNEXPECTED_CONTROL_FLOW,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Terminal interface. All communication interfaces must comply this interface in order to be used as a DTE
|
||||
*/
|
||||
class Terminal {
|
||||
public:
|
||||
virtual ~Terminal() = default;
|
||||
|
||||
void set_error_cb(std::function<void(terminal_error)> f) { on_error = std::move(f); }
|
||||
|
||||
virtual void set_read_cb(std::function<bool(uint8_t *data, size_t len)> f) { on_data = std::move(f); }
|
||||
|
||||
/**
|
||||
* @brief Writes data to the terminal
|
||||
* @param data Data pointer
|
||||
* @param len Data len
|
||||
* @return length of data written
|
||||
*/
|
||||
virtual int write(uint8_t *data, size_t len) = 0;
|
||||
|
||||
/**
|
||||
* @brief Read from the terminal. This function doesn't block, but return all available data.
|
||||
* @param data Data pointer to store the read payload
|
||||
* @param len Maximum data len to read
|
||||
* @return length of data actually read
|
||||
*/
|
||||
virtual int read(uint8_t *data, size_t len) = 0;
|
||||
|
||||
virtual void start() = 0;
|
||||
|
||||
virtual void stop() = 0;
|
||||
|
||||
protected:
|
||||
std::function<bool(uint8_t *data, size_t len)> on_data;
|
||||
std::function<void(terminal_error)> on_error;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_TERMINAL_HPP_
|
107
components/esp_modem/include/cxx_include/esp_modem_types.hpp
Normal file
107
components/esp_modem/include/cxx_include/esp_modem_types.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_TYPES_HPP_
|
||||
#define _ESP_MODEM_TYPES_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_TYPES
|
||||
* @brief Basic type definitions used in esp-modem
|
||||
*/
|
||||
|
||||
/** @addtogroup ESP_MODEM_TYPES
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Modem working mode
|
||||
*/
|
||||
enum class modem_mode {
|
||||
UNDEF,
|
||||
COMMAND_MODE, /*!< Command mode -- the modem is supposed to send AT commands in this mode */
|
||||
DATA_MODE, /*!< Data mode -- the modem communicates with network interface on PPP protocol */
|
||||
CMUX_MODE /*!< CMUX (Multiplex mode) -- Simplified CMUX mode, which creates two virtual terminals,
|
||||
* assigning one solely to command interface and the other to the data mode */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Module command result
|
||||
*/
|
||||
enum class command_result {
|
||||
OK, /*!< The command completed successfully */
|
||||
FAIL, /*!< The command explicitly failed */
|
||||
TIMEOUT /*!< The device didn't respond in the specified timeline */
|
||||
};
|
||||
|
||||
typedef std::function<command_result(uint8_t *data, size_t len)> got_line_cb;
|
||||
|
||||
/**
|
||||
* @brief PDP context used for configuring and setting the data mode up
|
||||
*/
|
||||
struct PdpContext {
|
||||
explicit PdpContext(std::string apn) : apn(std::move(apn)) {}
|
||||
size_t context_id = 1;
|
||||
std::string protocol_type = "IP";
|
||||
std::string apn;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface for classes eligible to send AT commands (Modules, DCEs, DTEs)
|
||||
*/
|
||||
class CommandableIf {
|
||||
public:
|
||||
/**
|
||||
* @brief Sends custom AT command
|
||||
* @param command Command to be sent
|
||||
* @param got_line callback if a line received
|
||||
* @param time_ms timeout in milliseconds
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/
|
||||
virtual command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms, const char separator) = 0;
|
||||
virtual command_result command(const std::string &command, got_line_cb got_line, uint32_t time_ms) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface for classes implementing a module for the modem
|
||||
*/
|
||||
class ModuleIf {
|
||||
public:
|
||||
/**
|
||||
* @brief Sets the data mode up (provides the necessary configuration to connect to the cellular network
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool setup_data_mode() = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the operation mode
|
||||
* @param mode Desired mode
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool set_mode(modem_mode mode) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _ESP_MODEM_TYPES_HPP_
|
40
components/esp_modem/include/esp_modem_api.h
Normal file
40
components/esp_modem/include/esp_modem_api.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_API_H_
|
||||
#define _ESP_MODEM_API_H_
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "generate/esp_modem_command_declare.inc"
|
||||
#include "esp_modem_c_api_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
|
||||
esp_err_t esp_modem_ ## name(esp_modem_dce_t *dce, ##__VA_ARGS__);
|
||||
|
||||
DECLARE_ALL_COMMAND_APIS(declares esp_modem_<API>(esp_modem_t * dce, ...);)
|
||||
|
||||
#undef ESP_MODEM_DECLARE_DCE_COMMAND
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _CLIENT_ESP_MODEM_API_H_
|
102
components/esp_modem/include/esp_modem_c_api_types.h
Normal file
102
components/esp_modem/include/esp_modem_c_api_types.h
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_C_API_TYPES_H_
|
||||
#define _ESP_MODEM_C_API_TYPES_H_
|
||||
|
||||
#include "esp_modem_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct esp_modem_dce_wrap esp_modem_dce_t;
|
||||
|
||||
struct PdpContext;
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_C_API ESP_MODEM C API
|
||||
* @brief Set of basic C API for ESP-MODEM
|
||||
*/
|
||||
/** @addtogroup ESP_MODEM_C_API
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DCE mode: This enum is used to set desired operation mode of the DCE
|
||||
*/
|
||||
typedef enum esp_modem_dce_mode
|
||||
{
|
||||
ESP_MODEM_MODE_COMMAND, /**< Default mode after modem startup, used for sending AT commands */
|
||||
ESP_MODEM_MODE_DATA, /**< Used for switching to PPP mode for the modem to connect to a network */
|
||||
} esp_modem_dce_mode_t;
|
||||
|
||||
/**
|
||||
* @brief DCE devices: Enum list of supported devices
|
||||
*/
|
||||
typedef enum esp_modem_dce_device
|
||||
{
|
||||
ESP_MODEM_DCE_GENETIC, /**< The most generic device */
|
||||
ESP_MODEM_DCE_SIM7600,
|
||||
ESP_MODEM_DCE_BG96,
|
||||
ESP_MODEM_DCE_SIM800,
|
||||
} esp_modem_dce_device_t;
|
||||
|
||||
/**
|
||||
* @brief Create a generic DCE handle for new modem API
|
||||
*
|
||||
* @param dte_config DTE configuration (UART config for now)
|
||||
* @param dce_config DCE configuration
|
||||
* @param netif Network interface handle for the data mode
|
||||
*
|
||||
* @return DCE pointer on success, NULL on failure
|
||||
*/
|
||||
esp_modem_dce_t *esp_modem_new(const esp_modem_dte_config_t *dte_config, const esp_modem_dce_config_t *dce_config, esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @brief Create a DCE handle using the supplied device
|
||||
*
|
||||
* @param module Specific device for creating this DCE
|
||||
* @param dte_config DTE configuration (UART config for now)
|
||||
* @param dce_config DCE configuration
|
||||
* @param netif Network interface handle for the data mode
|
||||
*
|
||||
* @return DCE pointer on success, NULL on failure
|
||||
*/
|
||||
esp_modem_dce_t *esp_modem_new_dev(esp_modem_dce_device_t module, const esp_modem_dte_config_t *dte_config, const esp_modem_dce_config_t *dce_config, esp_netif_t *netif);
|
||||
|
||||
/**
|
||||
* @brief Destroys modem's DCE handle
|
||||
*
|
||||
* @param dce DCE to destroy
|
||||
*/
|
||||
void esp_modem_destroy(esp_modem_dce_t * dce);
|
||||
|
||||
/**
|
||||
* @brief Set operation mode for this DCE
|
||||
* @param dce Modem DCE handle
|
||||
* @param mode Desired MODE
|
||||
* @return ESP_OK on success, ESP_FAIL on failure
|
||||
*/
|
||||
esp_err_t esp_modem_set_mode(esp_modem_dce_t * dce, esp_modem_dce_mode_t mode);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_ESP_MODEM_C_API_TYPES_H_
|
130
components/esp_modem/include/esp_modem_config.h
Normal file
130
components/esp_modem/include/esp_modem_config.h
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_CONFIG_H_
|
||||
#define _ESP_MODEM_CONFIG_H_
|
||||
#include "driver/uart.h"
|
||||
#include "esp_modem_dce_config.h"
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_CONFIG
|
||||
* @brief Configuration structures for DTE and DCE
|
||||
*/
|
||||
|
||||
/** @addtogroup ESP_MODEM_CONFIG
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Modem flow control type
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_MODEM_FLOW_CONTROL_NONE = 0,
|
||||
ESP_MODEM_FLOW_CONTROL_SW,
|
||||
ESP_MODEM_FLOW_CONTROL_HW
|
||||
} esp_modem_flow_ctrl_t;
|
||||
|
||||
/**
|
||||
* @brief UART configuration structure
|
||||
*
|
||||
*/
|
||||
struct esp_modem_uart_term_config {
|
||||
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 */
|
||||
esp_modem_flow_ctrl_t flow_control; /*!< Flow control type */
|
||||
int 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, set to 0 if no event queue needed */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Resources used by VFS terminal
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_MODEM_VFS_IS_EXTERN = 0, /*!< External resource: internal VFS terminal takes no action to setup this */
|
||||
ESP_MODEM_VFS_IS_UART, /*!< VFS uses UART: internal VFS initializes UART based on esp_modem_uart_term_config */
|
||||
} esp_modem_vfs_resource_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief VFS configuration structure
|
||||
*
|
||||
*/
|
||||
struct esp_modem_vfs_term_config {
|
||||
const char* dev_name; /*!< VFS device name, e.g. /dev/uart/n */
|
||||
esp_modem_vfs_resource_t resource; /*!< Underlying device which gets initialized during VFS init */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Complete DTE configuration structure
|
||||
*
|
||||
* Note that the generic part is common for DTE and its SW resources
|
||||
* The following portions for config is dedicated to the chosen HW resource
|
||||
* used as a communication terminal for this DTE
|
||||
*/
|
||||
struct esp_modem_dte_config {
|
||||
size_t dte_buffer_size; /*!< DTE buffer size */
|
||||
uint32_t task_stack_size; /*!< Terminal task stack size */
|
||||
int task_priority; /*!< Terminal task priority */
|
||||
struct esp_modem_uart_term_config uart_config; /*!< Configuration for UART Terminal */
|
||||
struct esp_modem_vfs_term_config vfs_config; /*!< Configuration for VFS Terminal */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief ESP Modem DTE Default Configuration
|
||||
*
|
||||
*/
|
||||
#define ESP_MODEM_DTE_DEFAULT_CONFIG() \
|
||||
{ \
|
||||
.dte_buffer_size = 512, \
|
||||
.task_stack_size = 4096, \
|
||||
.task_priority = 5, \
|
||||
.uart_config = { \
|
||||
.port_num = UART_NUM_1, \
|
||||
.data_bits = UART_DATA_8_BITS, \
|
||||
.stop_bits = UART_STOP_BITS_1, \
|
||||
.parity = UART_PARITY_DISABLE, \
|
||||
.flow_control = ESP_MODEM_FLOW_CONTROL_NONE,\
|
||||
.baud_rate = 115200, \
|
||||
.tx_io_num = 25, \
|
||||
.rx_io_num = 26, \
|
||||
.rts_io_num = 27, \
|
||||
.cts_io_num = 23, \
|
||||
.rx_buffer_size = 4096, \
|
||||
.tx_buffer_size = 512, \
|
||||
.event_queue_size = 30, \
|
||||
}, \
|
||||
.vfs_config = { \
|
||||
.dev_name = "/null", \
|
||||
.resource = ESP_MODEM_VFS_IS_EXTERN \
|
||||
}\
|
||||
}
|
||||
|
||||
typedef struct esp_modem_dte_config esp_modem_dte_config_t;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // _ESP_MODEM_CONFIG_H_
|
45
components/esp_modem/include/esp_modem_dce_config.h
Normal file
45
components/esp_modem/include/esp_modem_dce_config.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_DCE_CONFIG_H_
|
||||
#define _ESP_MODEM_DCE_CONFIG_H_
|
||||
|
||||
/** @addtogroup ESP_MODEM_CONFIG
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief ESP Modem DCE Default Configuration
|
||||
*
|
||||
*/
|
||||
#define ESP_MODEM_DCE_DEFAULT_CONFIG(APN) \
|
||||
{ \
|
||||
.apn = APN \
|
||||
}
|
||||
|
||||
typedef struct esp_modem_dce_config esp_modem_dce_config_t;
|
||||
|
||||
/**
|
||||
* @brief DCE configuration structure
|
||||
*/
|
||||
struct esp_modem_dce_config {
|
||||
const char* apn; /*!< APN: Logical name of the Access point */
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif // _ESP_MODEM_DCE_CONFIG_H_
|
@ -0,0 +1,234 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _ESP_MODEM_COMMAND_DECLARE_INC_
|
||||
#define _ESP_MODEM_COMMAND_DECLARE_INC_
|
||||
|
||||
|
||||
// Parameters
|
||||
// * handle different parameters for C++ and C API
|
||||
// * make parameter unique names, so they could be easily referenced and forwarded
|
||||
#define _ARG(param, name) param
|
||||
#define INT_IN(param, name) int _ARG(param, name)
|
||||
#ifdef __cplusplus
|
||||
#include <string>
|
||||
#define STRING_IN(param, name) const std::string& _ARG(param, name)
|
||||
#define STRING_OUT(param, name) std::string& _ARG(param, name)
|
||||
#define BOOL_IN(param, name) const bool _ARG(param, name)
|
||||
#define BOOL_OUT(param, name) bool& _ARG(param, name)
|
||||
#define INT_OUT(param, name) int& _ARG(param, name)
|
||||
|
||||
#define STRUCT_OUT(struct_name, x) struct_name& x
|
||||
#else
|
||||
#define STRING_IN(param, name) const char* _ARG(param, name)
|
||||
#define STRING_OUT(param, name) char* _ARG(param, name)
|
||||
#define BOOL_IN(param, name) const bool _ARG(param, name)
|
||||
#define BOOL_OUT(param, name) bool* _ARG(param, name)
|
||||
#define INT_OUT(param, name) int* _ARG(param, name)
|
||||
#define STRUCT_OUT(struct_name, x) struct struct_name* x
|
||||
#endif
|
||||
|
||||
#define DECLARE_ALL_COMMAND_APIS(...) \
|
||||
/**
|
||||
* @brief Sends the initial AT sequence to sync up with the device
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(sync, command_result, 0) \
|
||||
/**
|
||||
* @brief Reads the operator name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_operator_name, command_result, 1, STRING_OUT(x, name)) \
|
||||
\
|
||||
/**
|
||||
* @brief Stores current user profile
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(store_profile, command_result, 0) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets the supplied PIN code
|
||||
* @param[in] pin Pin
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/\
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_pin, command_result, 1, STRING_IN(x, pin)) \
|
||||
\
|
||||
/**
|
||||
* @brief Checks if the SIM needs a PIN
|
||||
* @param[out] pin_ok true if the SIM card doesn't need a PIN to unlock
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(read_pin, command_result, 1, BOOL_OUT(x, pin_ok)) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets echo mode
|
||||
* @param[in] echo_on true if echo mode on (repeats the commands)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_echo, command_result, 1, BOOL_IN(x, echo_on)) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets the Txt or Pdu mode for SMS (only txt is supported)
|
||||
* @param[in] txt true if txt mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(sms_txt_mode, command_result, 1, BOOL_IN(x, txt)) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets the default (GSM) charater set
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(sms_character_set, command_result, 0) \
|
||||
\
|
||||
/**
|
||||
* @brief Sends SMS message in txt mode
|
||||
* @param[in] number Phone number to send the message to
|
||||
* @param[in] message Text message to be sent
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(send_sms, command_result, 2, STRING_IN(x, number), STRING_IN(y, message)) \
|
||||
\
|
||||
/**
|
||||
* @brief Resumes data mode (Switches back to th data mode, which was temporarily suspended)
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(resume_data_mode, command_result, 0) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets php context
|
||||
* @param[in] x PdP context struct to setup modem cellular connection
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_pdp_context, command_result, 1, STRUCT_OUT(PdpContext, x)) \
|
||||
\
|
||||
/**
|
||||
* @brief Switches to the command mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_command_mode, command_result, 0) \
|
||||
\
|
||||
/**
|
||||
* @brief Switches to the CMUX mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_cmux, command_result, 0) \
|
||||
\
|
||||
/**
|
||||
* @brief Reads the IMSI number
|
||||
* @param[out] imsi Module's IMSI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_imsi, command_result, 1, STRING_OUT(x, imsi)) \
|
||||
\
|
||||
/**
|
||||
* @brief Reads the IMEI number
|
||||
* @param[out] imei Module's IMEI number
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_imei, command_result, 1, STRING_OUT(x, imei)) \
|
||||
\
|
||||
/**
|
||||
* @brief Reads the module name
|
||||
* @param[out] name module name
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_module_name, command_result, 1, STRING_OUT(x, name)) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets the modem to data mode
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_data_mode, command_result, 0) \
|
||||
\
|
||||
/**
|
||||
* @brief Get Signal quality
|
||||
* @param[out] rssi signal strength indication
|
||||
* @param[out] ber channel bit error rate
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_signal_quality, command_result, 2, INT_OUT(x, rssi), INT_OUT(y, ber)) \
|
||||
\
|
||||
/**
|
||||
* @brief Sets HW control flow
|
||||
* @param[in] dce_flow 0=none, 2=RTS hw flow control of DCE
|
||||
* @param[in] dte_flow 0=none, 2=CTS hw flow control of DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_flow_control, command_result, 2, INT_IN(x, dce_flow), INT_IN(y, dte_flow)) \
|
||||
\
|
||||
/**
|
||||
* @brief Hangs up current data call
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(hang_up, command_result, 0) \
|
||||
\
|
||||
/**
|
||||
* @brief Get voltage levels of modem power up circuitry
|
||||
* @param[out] voltage Current status in mV
|
||||
* @param[out] bcs charge status (-1-Not available, 0-Not charging, 1-Charging, 2-Charging done)
|
||||
* @param[out] bcl 1-100% battery capacity, -1-Not available
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(get_battery_status, command_result, 3, INT_OUT(x, voltage), INT_OUT(y, bcs), INT_OUT(z, bcl)) \
|
||||
\
|
||||
/**
|
||||
* @brief Power down the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(power_down, command_result, 0) \
|
||||
\
|
||||
/**
|
||||
* @brief Reset the module
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(reset, command_result, 0)\
|
||||
\
|
||||
/**
|
||||
* @brief Configures the baudrate
|
||||
* @param[in] baud Desired baud rate of the DTE
|
||||
* @return OK, FAIL or TIMEOUT
|
||||
*/ \
|
||||
ESP_MODEM_DECLARE_DCE_COMMAND(set_baud, command_result, 1, INT_IN(x, baud))
|
||||
|
||||
|
||||
#ifdef GENERATE_DOCS
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang++ -E -P -CC -xc++ -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p'
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -CC -xc -I../include -DGENERATE_DOCS - | sed -n '1,/DCE command documentation/!p' > c_api.h
|
||||
// cat ../include/generate/esp_modem_command_declare.inc | clang -E -P -xc -I../include -DGENERATE_DOCS -DGENERATE_RST_LINKS - | sed 's/NL/\n/g' > cxx_api_links.rst
|
||||
|
||||
// call parametrs by names for documentation
|
||||
#undef _ARG
|
||||
#define _ARG(param, name) name
|
||||
// --- DCE command documentation starts here ---
|
||||
#ifdef __cplusplus
|
||||
class esp_modem::DCE: public DCE_T<GenericModule> {
|
||||
public:
|
||||
using DCE_T<GenericModule>::DCE_T;
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, ...) return_type name (__VA_ARGS__);
|
||||
#elif defined(GENERATE_RST_LINKS)
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, ...) NL- :cpp:func:`esp_modem::DCE::name`
|
||||
#else
|
||||
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, ...) return_type esp_modem_ ## name (__VA_ARGS__);
|
||||
#endif
|
||||
|
||||
DECLARE_ALL_COMMAND_APIS()
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _ESP_MODEM_COMMAND_DECLARE_INC_
|
@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS esp_event_mock.c
|
||||
INCLUDE_DIRS include
|
||||
REQUIRES esp_system_protocols_linux)
|
@ -0,0 +1,28 @@
|
||||
//
|
||||
// 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_err.h"
|
||||
#include "esp_event.h"
|
||||
|
||||
const char * WIFI_EVENT = "WIFI_EVENT";
|
||||
const char * IP_EVENT = "IP_EVENT";
|
||||
|
||||
esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, void* event_handler, void* event_handler_arg)
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler)
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef MDNS_HOST_ESP_EVENT_H
|
||||
#define MDNS_HOST_ESP_EVENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_netif.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
|
||||
typedef void * system_event_t;
|
||||
|
||||
extern const char * WIFI_EVENT;
|
||||
extern const char * IP_EVENT;
|
||||
|
||||
#define ESP_EVENT_ANY_BASE NULL /**< register handler for any event base */
|
||||
#define ESP_EVENT_ANY_ID -1 /**< register handler for any event id */
|
||||
|
||||
typedef struct {
|
||||
int if_index; /*!< Interface index for which the event is received (left for legacy compilation) */
|
||||
esp_netif_t *esp_netif; /*!< Pointer to corresponding esp-netif object */
|
||||
esp_netif_ip6_info_t ip6_info; /*!< IPv6 address of the interface */
|
||||
int ip_index; /*!< IPv6 address index */
|
||||
} ip_event_got_ip6_t;
|
||||
|
||||
esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, void* event_handler, void* event_handler_arg);
|
||||
|
||||
esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler);
|
||||
|
||||
#endif //MDNS_HOST_ESP_EVENT_H
|
@ -0,0 +1,28 @@
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef MDNS_HOST_ESP_EVENT_BASE_H
|
||||
#define MDNS_HOST_ESP_EVENT_BASE_H
|
||||
|
||||
typedef enum {
|
||||
WIFI_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */
|
||||
WIFI_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
|
||||
WIFI_EVENT_AP_START, /**< ESP32 soft-AP start */
|
||||
WIFI_EVENT_AP_STOP, /**< ESP32 soft-AP stop */
|
||||
IP_EVENT_STA_GOT_IP,
|
||||
IP_EVENT_GOT_IP6
|
||||
} mdns_used_event_t;
|
||||
|
||||
typedef void * esp_event_base_t;
|
||||
|
||||
#endif //MDNS_HOST_ESP_EVENT_BASE_H
|
@ -0,0 +1,21 @@
|
||||
set(LWIP_DIR "$ENV{LWIP_PATH}")
|
||||
set(LWIP_CONTRIB_DIR "$ENV{LWIP_CONTRIB_PATH}")
|
||||
|
||||
set(lwipcontribportunix_SRCS ${LWIP_CONTRIB_DIR}/ports/unix/port/sys_arch.c)
|
||||
|
||||
include(${LWIP_DIR}/src/Filelists.cmake)
|
||||
|
||||
set (LWIP_INCLUDE_DIRS
|
||||
"${LWIP_DIR}/src/include"
|
||||
"${LWIP_CONTRIB_DIR}/ports/unix/port/include")
|
||||
|
||||
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/netif/slipif.c")
|
||||
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/core/ip4.c")
|
||||
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/core/ipv6/ip6.c")
|
||||
|
||||
|
||||
idf_component_register(SRCS esp_netif_linux.cpp tun_io.c ip6_stub.c ${lwipnoapps_SRCS} ${lwipcontribportunix_SRCS}
|
||||
INCLUDE_DIRS include ${LWIP_INCLUDE_DIRS}
|
||||
PRIV_INCLUDE_DIRS .
|
||||
REQUIRES esp_system_protocols_linux)
|
||||
|
@ -0,0 +1,136 @@
|
||||
//
|
||||
// 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 <thread>
|
||||
#include <atomic>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include "esp_netif.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define BUF_SIZE 1518
|
||||
|
||||
static const char *TAG = "esp_netif_linux";
|
||||
|
||||
extern "C" int ppp_netif_init(esp_netif_t *netif);
|
||||
extern "C" int tun_read(void);
|
||||
|
||||
class NetifStorage;
|
||||
|
||||
void read_task(NetifStorage *netif);
|
||||
|
||||
class NetifStorage: public esp_netif_obj
|
||||
{
|
||||
public:
|
||||
explicit NetifStorage(const esp_netif_config_t *config) : esp_netif_obj(), exit(false)
|
||||
{
|
||||
if ((fd = open(config->dev_name, O_RDWR)) == -1) {
|
||||
ESP_LOGE(TAG, "Cannot open %s", config->dev_name);
|
||||
throw std::runtime_error("Failed to open device");
|
||||
}
|
||||
struct ifreq ifr = { };
|
||||
ifr.ifr_flags = IFF_TUN;
|
||||
strncpy(ifr.ifr_name, config->if_name, IFNAMSIZ);
|
||||
|
||||
if (ioctl(fd, TUNSETIFF, (void *)&ifr) == -1) {
|
||||
ESP_LOGE(TAG, "Cannot set ioctl TUNSETIFF %m");
|
||||
throw std::runtime_error("Failed to set tun device interface name");
|
||||
}
|
||||
ioctl(fd, TUNSETNOCSUM, 1);
|
||||
|
||||
in_buf = new uint8_t[BUF_SIZE];
|
||||
out_buf = new uint8_t[BUF_SIZE];
|
||||
|
||||
if (!ppp_netif_init(this)) {
|
||||
ESP_LOGE(TAG, "Cannot initialize pppos lwip netif %m");
|
||||
throw std::runtime_error("Failed setup ppp interface");
|
||||
}
|
||||
|
||||
task = std::thread(read_task, this);
|
||||
}
|
||||
|
||||
~NetifStorage()
|
||||
{
|
||||
exit = true;
|
||||
task.join();
|
||||
close(fd);
|
||||
delete[] in_buf;
|
||||
delete[] out_buf;
|
||||
}
|
||||
|
||||
std::thread task;
|
||||
std::atomic<bool> exit;
|
||||
|
||||
static void read_task(NetifStorage *netif)
|
||||
{
|
||||
while (!netif->exit.load()) {
|
||||
tun_read();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
extern "C" esp_netif_t *esp_netif_new(const esp_netif_config_t *config)
|
||||
{
|
||||
return new NetifStorage(config);
|
||||
// struct ifreq ifr = { };
|
||||
// esp_netif_t * netif = netif_storage;
|
||||
// if (netif == NULL) {
|
||||
// return NULL;
|
||||
// }
|
||||
// if ((netif->fd = open(config->dev_name, O_RDWR)) == -1) {
|
||||
// ESP_LOGE(TAG, "Cannot open %s", config->dev_name);
|
||||
// goto cleanup;
|
||||
// }
|
||||
// ifr.ifr_flags = IFF_TUN;
|
||||
// strncpy(ifr.ifr_name, config->if_name, IFNAMSIZ);
|
||||
//
|
||||
// if (ioctl(netif->fd, TUNSETIFF, (void *)&ifr) == -1) {
|
||||
// ESP_LOGE(TAG, "Cannot set ioctl TUNSETIFF %m");
|
||||
// goto cleanup;
|
||||
// }
|
||||
// ioctl(netif->fd, TUNSETNOCSUM, 1);
|
||||
//
|
||||
// netif->in_buf = new uint8_t[BUF_SIZE];
|
||||
// netif->out_buf = new uint8_t[BUF_SIZE];
|
||||
// if (netif->in_buf == nullptr || netif->out_buf == nullptr) {
|
||||
// goto cleanup;
|
||||
// }
|
||||
//
|
||||
// if (!ppp_netif_init(netif)) {
|
||||
// ESP_LOGE(TAG, "Cannot initialize pppos lwip netif %m");
|
||||
// goto cleanup;
|
||||
// }
|
||||
//
|
||||
// return netif;
|
||||
//
|
||||
//cleanup:
|
||||
// close(netif->fd);
|
||||
// delete[] netif->in_buf;
|
||||
// delete[] netif->out_buf;
|
||||
// delete netif_storage;
|
||||
// return nullptr;
|
||||
}
|
||||
|
||||
void esp_netif_destroy(esp_netif_t *netif)
|
||||
{
|
||||
delete static_cast<NetifStorage*>(netif);
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef _HOST_ESP_NETIF_H_
|
||||
#define _HOST_ESP_NETIF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_netif_ip_addr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_event_base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct esp_netif_obj esp_netif_t;
|
||||
|
||||
typedef struct esp_netif_driver_base_s {
|
||||
esp_err_t (*post_attach)(esp_netif_t *netif, void *h);
|
||||
esp_netif_t *netif;
|
||||
} esp_netif_driver_base_t;
|
||||
|
||||
struct esp_netif_driver_ifconfig {
|
||||
void *handle;
|
||||
esp_err_t (*transmit)(void *h, void *buffer, size_t len);
|
||||
esp_err_t (*transmit_wrap)(void *h, void *buffer, size_t len, void *netstack_buffer);
|
||||
void (*driver_free_rx_buffer)(void *h, void *buffer);
|
||||
};
|
||||
|
||||
struct esp_netif_config {
|
||||
const char * dev_name; /**< Name of the file device */
|
||||
const char * if_name; /**< Network interface name */
|
||||
};
|
||||
|
||||
struct esp_netif_obj {
|
||||
uint8_t *in_buf;
|
||||
uint8_t *out_buf;
|
||||
int fd;
|
||||
esp_err_t (*transmit)(void *h, void *buffer, size_t len);
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
int esp_netif_receive(esp_netif_t *netif, uint8_t *data, size_t len);
|
||||
|
||||
typedef struct esp_netif_config esp_netif_config_t;
|
||||
|
||||
esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config);
|
||||
|
||||
void esp_netif_destroy(esp_netif_t *esp_netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _HOST_ESP_NETIF_H_
|
@ -0,0 +1,168 @@
|
||||
// Copyright 2015-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.
|
||||
|
||||
#ifndef _ESP_NETIF_IP_ADDR_H_
|
||||
#define _ESP_NETIF_IP_ADDR_H_
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define esp_netif_htonl(x) ((uint32_t)(x))
|
||||
#else
|
||||
#define esp_netif_htonl(x) ((((x) & (uint32_t)0x000000ffUL) << 24) | \
|
||||
(((x) & (uint32_t)0x0000ff00UL) << 8) | \
|
||||
(((x) & (uint32_t)0x00ff0000UL) >> 8) | \
|
||||
(((x) & (uint32_t)0xff000000UL) >> 24))
|
||||
#endif
|
||||
|
||||
#define esp_netif_ip4_makeu32(a,b,c,d) (((uint32_t)((a) & 0xff) << 24) | \
|
||||
((uint32_t)((b) & 0xff) << 16) | \
|
||||
((uint32_t)((c) & 0xff) << 8) | \
|
||||
(uint32_t)((d) & 0xff))
|
||||
|
||||
// Access address in 16-bit block
|
||||
#define ESP_IP6_ADDR_BLOCK1(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[0]) >> 16) & 0xffff))
|
||||
#define ESP_IP6_ADDR_BLOCK2(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[0])) & 0xffff))
|
||||
#define ESP_IP6_ADDR_BLOCK3(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[1]) >> 16) & 0xffff))
|
||||
#define ESP_IP6_ADDR_BLOCK4(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[1])) & 0xffff))
|
||||
#define ESP_IP6_ADDR_BLOCK5(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[2]) >> 16) & 0xffff))
|
||||
#define ESP_IP6_ADDR_BLOCK6(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[2])) & 0xffff))
|
||||
#define ESP_IP6_ADDR_BLOCK7(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[3]) >> 16) & 0xffff))
|
||||
#define ESP_IP6_ADDR_BLOCK8(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[3])) & 0xffff))
|
||||
|
||||
#define IPSTR "%d.%d.%d.%d"
|
||||
#define esp_ip4_addr_get_byte(ipaddr, idx) (((const uint8_t*)(&(ipaddr)->addr))[idx])
|
||||
#define esp_ip4_addr1(ipaddr) esp_ip4_addr_get_byte(ipaddr, 0)
|
||||
#define esp_ip4_addr2(ipaddr) esp_ip4_addr_get_byte(ipaddr, 1)
|
||||
#define esp_ip4_addr3(ipaddr) esp_ip4_addr_get_byte(ipaddr, 2)
|
||||
#define esp_ip4_addr4(ipaddr) esp_ip4_addr_get_byte(ipaddr, 3)
|
||||
|
||||
|
||||
#define esp_ip4_addr1_16(ipaddr) ((uint16_t)esp_ip4_addr1(ipaddr))
|
||||
#define esp_ip4_addr2_16(ipaddr) ((uint16_t)esp_ip4_addr2(ipaddr))
|
||||
#define esp_ip4_addr3_16(ipaddr) ((uint16_t)esp_ip4_addr3(ipaddr))
|
||||
#define esp_ip4_addr4_16(ipaddr) ((uint16_t)esp_ip4_addr4(ipaddr))
|
||||
|
||||
#define IP2STR(ipaddr) esp_ip4_addr1_16(ipaddr), \
|
||||
esp_ip4_addr2_16(ipaddr), \
|
||||
esp_ip4_addr3_16(ipaddr), \
|
||||
esp_ip4_addr4_16(ipaddr)
|
||||
|
||||
#define IPV6STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
|
||||
|
||||
#define IPV62STR(ipaddr) ESP_IP6_ADDR_BLOCK1(&(ipaddr)), \
|
||||
ESP_IP6_ADDR_BLOCK2(&(ipaddr)), \
|
||||
ESP_IP6_ADDR_BLOCK3(&(ipaddr)), \
|
||||
ESP_IP6_ADDR_BLOCK4(&(ipaddr)), \
|
||||
ESP_IP6_ADDR_BLOCK5(&(ipaddr)), \
|
||||
ESP_IP6_ADDR_BLOCK6(&(ipaddr)), \
|
||||
ESP_IP6_ADDR_BLOCK7(&(ipaddr)), \
|
||||
ESP_IP6_ADDR_BLOCK8(&(ipaddr))
|
||||
|
||||
#define ESP_IPADDR_TYPE_V4 0U
|
||||
#define ESP_IPADDR_TYPE_V6 6U
|
||||
#define ESP_IPADDR_TYPE_ANY 46U
|
||||
|
||||
#define ESP_IP4TOUINT32(a,b,c,d) (((uint32_t)((a) & 0xffU) << 24) | \
|
||||
((uint32_t)((b) & 0xffU) << 16) | \
|
||||
((uint32_t)((c) & 0xffU) << 8) | \
|
||||
(uint32_t)((d) & 0xffU))
|
||||
|
||||
#define ESP_IP4TOADDR(a,b,c,d) esp_netif_htonl(ESP_IP4TOUINT32(a, b, c, d))
|
||||
|
||||
// new definitions
|
||||
#define ESP_IPADDR4_INIT(ipaddr, a,b,c,d) (ipaddr)->addr = ESP_IP4TOADDR(a,b,c,d)
|
||||
#define ESP_IP6TOADDR(a, b, c, d) { { { { a, b, c, d } , 0 } }, ESP_IPADDR_TYPE_V6 }
|
||||
|
||||
// TODO: use esp-netif instead of lwip API
|
||||
#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6))
|
||||
#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4))
|
||||
#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0)
|
||||
#define IP_GET_TYPE(ipaddr) ((ipaddr)->type)
|
||||
|
||||
#define IP6_NO_ZONE 0
|
||||
#define ip6_addr_clear_zone(ip6addr) ((ip6addr)->zone = IP6_NO_ZONE)
|
||||
|
||||
#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->s6_addr32[0] = (source_ip6addr)->addr[0]; \
|
||||
(target_in6addr)->s6_addr32[1] = (source_ip6addr)->addr[1]; \
|
||||
(target_in6addr)->s6_addr32[2] = (source_ip6addr)->addr[2]; \
|
||||
(target_in6addr)->s6_addr32[3] = (source_ip6addr)->addr[3];}
|
||||
|
||||
#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->s6_addr32[0]; \
|
||||
(target_ip6addr)->addr[1] = (source_in6addr)->s6_addr32[1]; \
|
||||
(target_ip6addr)->addr[2] = (source_in6addr)->s6_addr32[2]; \
|
||||
(target_ip6addr)->addr[3] = (source_in6addr)->s6_addr32[3]; \
|
||||
ip6_addr_clear_zone(target_ip6addr);}
|
||||
|
||||
|
||||
struct esp_ip6_addr {
|
||||
uint32_t addr[4];
|
||||
uint8_t zone;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct esp_ip4_addr {
|
||||
uint32_t addr;
|
||||
};
|
||||
|
||||
typedef struct esp_ip4_addr esp_ip4_addr_t;
|
||||
|
||||
typedef struct esp_ip6_addr esp_ip6_addr_t;
|
||||
|
||||
typedef struct _ip_addr {
|
||||
union {
|
||||
esp_ip6_addr_t ip6;
|
||||
esp_ip4_addr_t ip4;
|
||||
} u_addr;
|
||||
uint8_t type;
|
||||
} esp_ip_addr_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_IP6_ADDR_IS_UNKNOWN,
|
||||
ESP_IP6_ADDR_IS_GLOBAL,
|
||||
ESP_IP6_ADDR_IS_LINK_LOCAL,
|
||||
ESP_IP6_ADDR_IS_SITE_LOCAL,
|
||||
ESP_IP6_ADDR_IS_UNIQUE_LOCAL,
|
||||
ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6
|
||||
} esp_ip6_addr_type_t;
|
||||
|
||||
typedef struct {
|
||||
esp_ip4_addr_t ip; /**< Interface IPV4 address */
|
||||
esp_ip4_addr_t netmask; /**< Interface IPV4 netmask */
|
||||
esp_ip4_addr_t gw; /**< Interface IPV4 gateway address */
|
||||
} esp_netif_ip_info_t;
|
||||
|
||||
typedef struct {
|
||||
esp_ip6_addr_t ip; /**< Interface IPV6 address */
|
||||
} esp_netif_ip6_info_t;
|
||||
|
||||
/**
|
||||
* @brief Get the IPv6 address type
|
||||
*
|
||||
* @param[in] ip6_addr IPv6 type
|
||||
*
|
||||
* @return IPv6 type in form of enum esp_ip6_addr_type_t
|
||||
*/
|
||||
esp_ip6_addr_type_t esp_netif_ip6_get_addr_type(esp_ip6_addr_t* ip6_addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_ESP_NETIF_IP_ADDR_H_
|
@ -0,0 +1,22 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
|
||||
#ifndef _ESP_NETIF_PPP_H_
|
||||
#define _ESP_NETIF_PPP_H_
|
||||
|
||||
#define NETIF_PP_PHASE_OFFSET 0x100
|
||||
|
||||
|
||||
#endif //_ESP_NETIF_PPP_H_
|
25
components/esp_modem/port/linux/esp_netif_linux/ip6_stub.c
Normal file
25
components/esp_modem/port/linux/esp_netif_linux/ip6_stub.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include "lwip/ip6.h"
|
||||
|
||||
err_t
|
||||
ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
||||
u8_t hl, u8_t tc,
|
||||
u8_t nexth, struct netif *netif)
|
||||
{ return ERR_OK; }
|
||||
|
||||
struct netif *
|
||||
ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
|
||||
{ return NULL; }
|
||||
|
||||
err_t
|
||||
ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
|
||||
u8_t hl, u8_t tc,
|
||||
u8_t nexth, struct netif *netif)
|
||||
{ return ERR_OK; }
|
||||
|
||||
const ip_addr_t *
|
||||
ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
|
||||
{ return NULL; }
|
||||
|
||||
err_t
|
||||
ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value)
|
||||
{ return ERR_OK; }
|
347
components/esp_modem/port/linux/esp_netif_linux/lwipopts.h
Normal file
347
components/esp_modem/port/linux/esp_netif_linux/lwipopts.h
Normal file
@ -0,0 +1,347 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef LWIP_LWIPOPTS_H
|
||||
#define LWIP_LWIPOPTS_H
|
||||
|
||||
#ifdef LWIP_OPTTEST_FILE
|
||||
#include "lwipopts_test.h"
|
||||
#else /* LWIP_OPTTEST_FILE */
|
||||
|
||||
#define LWIP_IPV4 1
|
||||
#define LWIP_IPV6 1
|
||||
|
||||
#define NO_SYS 0
|
||||
#define LWIP_SOCKET (NO_SYS==0)
|
||||
#define LWIP_NETCONN (NO_SYS==0)
|
||||
#define LWIP_NETIF_API (NO_SYS==0)
|
||||
|
||||
#define LWIP_IGMP 0
|
||||
#define LWIP_ICMP 0
|
||||
|
||||
#define LWIP_SNMP 0
|
||||
#define MIB2_STATS 0
|
||||
#ifdef LWIP_HAVE_MBEDTLS
|
||||
#define LWIP_SNMP_V3 (LWIP_SNMP)
|
||||
#endif
|
||||
|
||||
#define LWIP_DNS LWIP_UDP
|
||||
#define LWIP_MDNS_RESPONDER 0
|
||||
|
||||
#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER)
|
||||
|
||||
#define LWIP_HAVE_LOOPIF 0
|
||||
#define LWIP_NETIF_LOOPBACK 1
|
||||
#define LWIP_LOOPBACK_MAX_PBUFS 10
|
||||
|
||||
#define TCP_LISTEN_BACKLOG 1
|
||||
|
||||
#define LWIP_COMPAT_SOCKETS 1
|
||||
#define LWIP_SO_RCVTIMEO 1
|
||||
#define LWIP_SO_RCVBUF 1
|
||||
|
||||
#define LWIP_TCPIP_CORE_LOCKING 0
|
||||
|
||||
#define LWIP_NETIF_LINK_CALLBACK 1
|
||||
#define LWIP_NETIF_STATUS_CALLBACK 1
|
||||
#define LWIP_NETIF_EXT_STATUS_CALLBACK 1
|
||||
|
||||
#define PPP_DEBUG LWIP_DBG_ON
|
||||
#define LWIP_DEBUG LWIP_DBG_ON
|
||||
|
||||
#define PPP_IPV6_SUPPORT 0
|
||||
|
||||
#define PPP_NOTIFY_PHASE 1
|
||||
|
||||
#define PAP_SUPPORT 0
|
||||
|
||||
#define CHAP_SUPPORT 0
|
||||
|
||||
#define MSCHAP_SUPPORT 0
|
||||
|
||||
#define MPPE_SUPPORT 0
|
||||
|
||||
#define PPP_MAXIDLEFLAG 0
|
||||
|
||||
#define PRINTPKT_SUPPORT 1
|
||||
#define PPP_PROTOCOLNAME 1
|
||||
|
||||
|
||||
#define MEM_DEBUG LWIP_DBG_OFF
|
||||
#define MEMP_DEBUG LWIP_DBG_OFF
|
||||
#define PBUF_DEBUG LWIP_DBG_OFF
|
||||
#define API_LIB_DEBUG LWIP_DBG_OFF
|
||||
#define API_MSG_DEBUG LWIP_DBG_OFF
|
||||
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||
#define NETIF_DEBUG LWIP_DBG_OFF
|
||||
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||
#define DNS_DEBUG LWIP_DBG_OFF
|
||||
#define AUTOIP_DEBUG LWIP_DBG_OFF
|
||||
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||
#define IP_DEBUG LWIP_DBG_OFF
|
||||
#define IP_REASS_DEBUG LWIP_DBG_OFF
|
||||
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||
#define IGMP_DEBUG LWIP_DBG_OFF
|
||||
#define UDP_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_RTO_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_CWND_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_WND_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_FR_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_RST_DEBUG LWIP_DBG_OFF
|
||||
|
||||
#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT)
|
||||
|
||||
|
||||
/* ---------- Memory options ---------- */
|
||||
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
|
||||
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
|
||||
byte alignment -> define MEM_ALIGNMENT to 2. */
|
||||
/* MSVC port: intel processors don't need 4-byte alignment,
|
||||
but are faster that way! */
|
||||
#define MEM_ALIGNMENT 4U
|
||||
|
||||
/* MEM_SIZE: the size of the heap memory. If the application will send
|
||||
a lot of data that needs to be copied, this should be set high. */
|
||||
#define MEM_SIZE 10240
|
||||
|
||||
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
|
||||
sends a lot of data out of ROM (or other static memory), this
|
||||
should be set high. */
|
||||
#define MEMP_NUM_PBUF 16
|
||||
/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One
|
||||
per active RAW "connection". */
|
||||
#define MEMP_NUM_RAW_PCB 3
|
||||
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
|
||||
per active UDP "connection". */
|
||||
#define MEMP_NUM_UDP_PCB 4
|
||||
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
|
||||
connections. */
|
||||
#define MEMP_NUM_TCP_PCB 5
|
||||
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
|
||||
connections. */
|
||||
#define MEMP_NUM_TCP_PCB_LISTEN 8
|
||||
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
|
||||
segments. */
|
||||
#define MEMP_NUM_TCP_SEG 16
|
||||
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
|
||||
timeouts. */
|
||||
#define MEMP_NUM_SYS_TIMEOUT 17
|
||||
|
||||
/* The following four are used only with the sequential API and can be
|
||||
set to 0 if the application only will use the raw API. */
|
||||
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
|
||||
#define MEMP_NUM_NETBUF 2
|
||||
/* MEMP_NUM_NETCONN: the number of struct netconns. */
|
||||
#define MEMP_NUM_NETCONN 10
|
||||
/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used
|
||||
for sequential API communication and incoming packets. Used in
|
||||
src/api/tcpip.c. */
|
||||
#define MEMP_NUM_TCPIP_MSG_API 16
|
||||
#define MEMP_NUM_TCPIP_MSG_INPKT 16
|
||||
|
||||
|
||||
/* ---------- Pbuf options ---------- */
|
||||
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
|
||||
#define PBUF_POOL_SIZE 120
|
||||
|
||||
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
|
||||
#define PBUF_POOL_BUFSIZE 256
|
||||
|
||||
/** SYS_LIGHTWEIGHT_PROT
|
||||
* define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
|
||||
* for certain critical regions during buffer allocation, deallocation and memory
|
||||
* allocation and deallocation.
|
||||
*/
|
||||
#define SYS_LIGHTWEIGHT_PROT (NO_SYS==0)
|
||||
|
||||
|
||||
/* ---------- TCP options ---------- */
|
||||
#define LWIP_TCP 0
|
||||
#define TCP_TTL 255
|
||||
|
||||
#define LWIP_ALTCP (LWIP_TCP)
|
||||
#ifdef LWIP_HAVE_MBEDTLS
|
||||
#define LWIP_ALTCP_TLS (LWIP_TCP)
|
||||
#define LWIP_ALTCP_TLS_MBEDTLS (LWIP_TCP)
|
||||
#endif
|
||||
|
||||
|
||||
/* Controls if TCP should queue segments that arrive out of
|
||||
order. Define to 0 if your device is low on memory. */
|
||||
#define TCP_QUEUE_OOSEQ 1
|
||||
|
||||
/* TCP Maximum segment size. */
|
||||
#define TCP_MSS 1024
|
||||
|
||||
/* TCP sender buffer space (bytes). */
|
||||
#define TCP_SND_BUF 2048
|
||||
|
||||
/* TCP sender buffer space (pbufs). This must be at least = 2 *
|
||||
TCP_SND_BUF/TCP_MSS for things to work. */
|
||||
#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS)
|
||||
|
||||
/* TCP writable space (bytes). This must be less than or equal
|
||||
to TCP_SND_BUF. It is the amount of space which must be
|
||||
available in the tcp snd_buf for select to return writable */
|
||||
#define TCP_SNDLOWAT (TCP_SND_BUF/2)
|
||||
|
||||
/* TCP receive window. */
|
||||
#define TCP_WND (20 * 1024)
|
||||
|
||||
/* Maximum number of retransmissions of data segments. */
|
||||
#define TCP_MAXRTX 12
|
||||
|
||||
/* Maximum number of retransmissions of SYN segments. */
|
||||
#define TCP_SYNMAXRTX 4
|
||||
|
||||
|
||||
/* ---------- ARP options ---------- */
|
||||
#define LWIP_ARP 1
|
||||
#define ARP_TABLE_SIZE 10
|
||||
#define ARP_QUEUEING 1
|
||||
|
||||
|
||||
/* ---------- IP options ---------- */
|
||||
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
|
||||
IP packets across network interfaces. If you are going to run lwIP
|
||||
on a device with only one network interface, define this to 0. */
|
||||
#define IP_FORWARD 1
|
||||
|
||||
/* IP reassembly and segmentation.These are orthogonal even
|
||||
* if they both deal with IP fragments */
|
||||
#define IP_REASSEMBLY 1
|
||||
#define IP_REASS_MAX_PBUFS (10 * ((1500 + PBUF_POOL_BUFSIZE - 1) / PBUF_POOL_BUFSIZE))
|
||||
#define MEMP_NUM_REASSDATA IP_REASS_MAX_PBUFS
|
||||
#define IP_FRAG 1
|
||||
#define IPV6_FRAG_COPYHEADER 1
|
||||
|
||||
/* ---------- ICMP options ---------- */
|
||||
#define ICMP_TTL 255
|
||||
|
||||
|
||||
/* ---------- DHCP options ---------- */
|
||||
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
|
||||
interfaces. */
|
||||
#define LWIP_DHCP LWIP_UDP
|
||||
|
||||
/* 1 if you want to do an ARP check on the offered address
|
||||
(recommended). */
|
||||
#define DHCP_DOES_ARP_CHECK (LWIP_DHCP)
|
||||
|
||||
|
||||
/* ---------- AUTOIP options ------- */
|
||||
#define LWIP_AUTOIP (LWIP_DHCP)
|
||||
#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP)
|
||||
|
||||
|
||||
/* ---------- UDP options ---------- */
|
||||
#define LWIP_UDP 1
|
||||
#define LWIP_UDPLITE LWIP_UDP
|
||||
#define UDP_TTL 255
|
||||
|
||||
|
||||
/* ---------- RAW options ---------- */
|
||||
#define LWIP_RAW 1
|
||||
|
||||
|
||||
/* ---------- Statistics options ---------- */
|
||||
|
||||
#define LWIP_STATS 0
|
||||
#define LWIP_STATS_DISPLAY 0
|
||||
|
||||
#if LWIP_STATS
|
||||
#define LINK_STATS 1
|
||||
#define IP_STATS 1
|
||||
#define ICMP_STATS 1
|
||||
#define IGMP_STATS 1
|
||||
#define IPFRAG_STATS 1
|
||||
#define UDP_STATS 1
|
||||
#define TCP_STATS 1
|
||||
#define MEM_STATS 1
|
||||
#define MEMP_STATS 1
|
||||
#define PBUF_STATS 1
|
||||
#define SYS_STATS 1
|
||||
#endif /* LWIP_STATS */
|
||||
|
||||
/* ---------- NETBIOS options ---------- */
|
||||
#define LWIP_NETBIOS_RESPOND_NAME_QUERY 1
|
||||
|
||||
/* ---------- PPP options ---------- */
|
||||
|
||||
#define PPP_SUPPORT 1 /* Set > 0 for PPP */
|
||||
|
||||
#if PPP_SUPPORT
|
||||
|
||||
#define NUM_PPP 1 /* Max PPP sessions. */
|
||||
|
||||
|
||||
/* Select modules to enable. Ideally these would be set in the makefile but
|
||||
* we're limited by the command line length so you need to modify the settings
|
||||
* in this file.
|
||||
*/
|
||||
#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP */
|
||||
#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */
|
||||
#define CCP_SUPPORT 0 /* Set > 0 for CCP */
|
||||
#define VJ_SUPPORT 1 /* Set > 0 for VJ header compression. */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
||||
|
||||
#endif /* LWIP_OPTTEST_FILE */
|
||||
|
||||
/* The following defines must be done even in OPTTEST mode: */
|
||||
|
||||
#if !defined(NO_SYS) || !NO_SYS /* default is 0 */
|
||||
void sys_check_core_locking(void);
|
||||
#define LWIP_ASSERT_CORE_LOCKED() sys_check_core_locking()
|
||||
void sys_mark_tcpip_thread(void);
|
||||
#define LWIP_MARK_TCPIP_THREAD() sys_mark_tcpip_thread()
|
||||
|
||||
#if !defined(LWIP_TCPIP_CORE_LOCKING) || LWIP_TCPIP_CORE_LOCKING /* default is 1 */
|
||||
void sys_lock_tcpip_core(void);
|
||||
#define LOCK_TCPIP_CORE() sys_lock_tcpip_core()
|
||||
void sys_unlock_tcpip_core(void);
|
||||
#define UNLOCK_TCPIP_CORE() sys_unlock_tcpip_core()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LWIP_DHCP_STATE_DEBUG
|
||||
#define ESP_DHCP_DEBUG LWIP_DBG_ON
|
||||
#else
|
||||
#define ESP_DHCP_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
#define ESP_LWIP_SELECT 1
|
||||
|
||||
#endif /* LWIP_LWIPOPTS_H */
|
209
components/esp_modem/port/linux/esp_netif_linux/tun_io.c
Normal file
209
components/esp_modem/port/linux/esp_netif_linux/tun_io.c
Normal file
@ -0,0 +1,209 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "netif/ppp/pppos.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "netif/ppp/pppos.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
#define BUF_SIZE 1518
|
||||
|
||||
void ppp_init(void);
|
||||
|
||||
static const unsigned char ip6_header[4] = { 0, 0, 0x86, 0xdd }; // Ethernet (IPv6)
|
||||
static const unsigned char ip4_header[4] = { 0, 0, 0x08, 0 }; // Ethernet (IPv4)
|
||||
|
||||
static esp_netif_t *esp_netif = NULL;
|
||||
static struct netif pppos_netif;
|
||||
static ppp_pcb *ppp;
|
||||
|
||||
static void ppp_link_status_cb(ppp_pcb *pcb, int err_code, void *ctx)
|
||||
{
|
||||
struct netif *pppif = ppp_netif(pcb);
|
||||
LWIP_UNUSED_ARG(ctx);
|
||||
|
||||
switch(err_code) {
|
||||
case PPPERR_NONE: /* No error. */
|
||||
{
|
||||
#if LWIP_DNS
|
||||
const ip_addr_t *ns;
|
||||
#endif /* LWIP_DNS */
|
||||
fprintf(stderr, "ppp_link_status_cb: PPPERR_NONE\n\r");
|
||||
#if LWIP_IPV4
|
||||
fprintf(stderr, " our_ip4addr = %s\n\r", ip4addr_ntoa(netif_ip4_addr(pppif)));
|
||||
fprintf(stderr, " his_ipaddr = %s\n\r", ip4addr_ntoa(netif_ip4_gw(pppif)));
|
||||
fprintf(stderr, " netmask = %s\n\r", ip4addr_ntoa(netif_ip4_netmask(pppif)));
|
||||
#endif /* LWIP_IPV4 */
|
||||
#if LWIP_IPV6
|
||||
fprintf(stderr, " our_ip6addr = %s\n\r", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if LWIP_DNS
|
||||
ns = dns_getserver(0);
|
||||
fprintf(stderr, " dns1 = %s\n\r", ipaddr_ntoa(ns));
|
||||
ns = dns_getserver(1);
|
||||
fprintf(stderr, " dns2 = %s\n\r", ipaddr_ntoa(ns));
|
||||
#endif /* LWIP_DNS */
|
||||
#if PPP_IPV6_SUPPORT
|
||||
fprintf(stderr, " our6_ipaddr = %s\n\r", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
|
||||
#endif /* PPP_IPV6_SUPPORT */
|
||||
}
|
||||
break;
|
||||
|
||||
case PPPERR_PARAM: /* Invalid parameter. */
|
||||
printf("ppp_link_status_cb: PPPERR_PARAM\n");
|
||||
break;
|
||||
|
||||
case PPPERR_OPEN: /* Unable to open PPP session. */
|
||||
printf("ppp_link_status_cb: PPPERR_OPEN\n");
|
||||
break;
|
||||
|
||||
case PPPERR_DEVICE: /* Invalid I/O device for PPP. */
|
||||
printf("ppp_link_status_cb: PPPERR_DEVICE\n");
|
||||
break;
|
||||
|
||||
case PPPERR_ALLOC: /* Unable to allocate resources. */
|
||||
printf("ppp_link_status_cb: PPPERR_ALLOC\n");
|
||||
break;
|
||||
|
||||
case PPPERR_USER: /* User interrupt. */
|
||||
printf("ppp_link_status_cb: PPPERR_USER\n");
|
||||
break;
|
||||
|
||||
case PPPERR_CONNECT: /* Connection lost. */
|
||||
printf("ppp_link_status_cb: PPPERR_CONNECT\n");
|
||||
break;
|
||||
|
||||
case PPPERR_AUTHFAIL: /* Failed authentication challenge. */
|
||||
printf("ppp_link_status_cb: PPPERR_AUTHFAIL\n");
|
||||
break;
|
||||
|
||||
case PPPERR_PROTOCOL: /* Failed to meet protocol. */
|
||||
printf("ppp_link_status_cb: PPPERR_PROTOCOL\n");
|
||||
break;
|
||||
|
||||
case PPPERR_PEERDEAD: /* Connection timeout. */
|
||||
printf("ppp_link_status_cb: PPPERR_PEERDEAD\n");
|
||||
break;
|
||||
|
||||
case PPPERR_IDLETIMEOUT: /* Idle Timeout. */
|
||||
printf("ppp_link_status_cb: PPPERR_IDLETIMEOUT\n");
|
||||
break;
|
||||
|
||||
case PPPERR_CONNECTTIME: /* PPPERR_CONNECTTIME. */
|
||||
printf("ppp_link_status_cb: PPPERR_CONNECTTIME\n");
|
||||
break;
|
||||
|
||||
case PPPERR_LOOPBACK: /* Connection timeout. */
|
||||
printf("ppp_link_status_cb: PPPERR_LOOPBACK\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ppp_link_status_cb: unknown errCode %d\n", err_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static u32_t ppp_output_cb(struct ppp_pcb_s *pcb, const void *data, u32_t len, void *ctx)
|
||||
{
|
||||
esp_netif_t *netif = (esp_netif_t *)ctx;
|
||||
if (netif->transmit)
|
||||
return netif->transmit(netif->ctx, (uint8_t*)data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int esp_netif_receive(esp_netif_t *netif, uint8_t *data, size_t len)
|
||||
{
|
||||
pppos_input(ppp, data, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ppp_netif_init(esp_netif_t *netif)
|
||||
{
|
||||
// Init necessary units of lwip (no need for the tcpip thread)
|
||||
sys_init();
|
||||
mem_init();
|
||||
memp_init();
|
||||
netif_init();
|
||||
dns_init();
|
||||
ppp_init();
|
||||
sys_timeouts_init();
|
||||
|
||||
// init and start connection attempts on PPP interface
|
||||
ppp = pppos_create(&pppos_netif, ppp_output_cb, ppp_link_status_cb, (void*)netif);
|
||||
if (ppp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
ppp_connect(ppp, 0);
|
||||
ppp_set_usepeerdns(ppp, 1);
|
||||
esp_netif = netif;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static err_t tun_input(struct pbuf *p, const unsigned char tun_header[4])
|
||||
{
|
||||
struct pbuf *n;
|
||||
size_t offset = 4;
|
||||
memcpy(esp_netif->in_buf, tun_header, offset);
|
||||
for (n = p; n; n = n->next) {
|
||||
memcpy(esp_netif->in_buf + offset, n->payload, n->len);
|
||||
offset += n->len;
|
||||
}
|
||||
if (write(esp_netif->fd, esp_netif->in_buf, offset) != offset) {
|
||||
pbuf_free(p);
|
||||
return ERR_ABRT;
|
||||
}
|
||||
pbuf_free(p);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t ip6_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
return tun_input(p, ip6_header);
|
||||
}
|
||||
|
||||
err_t ip4_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
return tun_input(p, ip4_header);
|
||||
}
|
||||
|
||||
int tun_read(void)
|
||||
{
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(esp_netif->fd, &fds);
|
||||
struct timeval tv = { .tv_usec = 0, .tv_sec = 1 };
|
||||
|
||||
if (select(esp_netif->fd +1, &fds, NULL, NULL, &tv) <= 0) {
|
||||
sys_check_timeouts();
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pbuf *p;
|
||||
ssize_t len = read(esp_netif->fd, esp_netif->out_buf, BUF_SIZE);
|
||||
if (len < 0) {
|
||||
perror("read returned -1");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len <= 4) {
|
||||
return -1;
|
||||
}
|
||||
len -= 4;
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
if (p == NULL) {
|
||||
perror("Cannot allocate pbuf");
|
||||
return -1;
|
||||
}
|
||||
pbuf_take(p, esp_netif->out_buf + 4, len);
|
||||
if (memcmp(esp_netif->out_buf, ip6_header, 4) == 0) {
|
||||
pppos_netif.output_ip6(&pppos_netif, p, NULL);
|
||||
} else if (memcmp(esp_netif->out_buf, ip4_header, 4) == 0) {
|
||||
pppos_netif.output(&pppos_netif, p, NULL);
|
||||
} else {
|
||||
printf("Unknown protocol %x %x\n", esp_netif->out_buf[2], esp_netif->out_buf[3]);
|
||||
}
|
||||
pbuf_free(p);
|
||||
return 1;
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
idf_component_register(INCLUDE_DIRS include
|
||||
REQUIRES esp_netif_linux esp_event_mock)
|
@ -0,0 +1,19 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
typedef int uart_port_t;
|
||||
typedef int uart_word_length_t;
|
||||
typedef int uart_stop_bits_t;
|
||||
typedef int uart_parity_t;
|
@ -0,0 +1,25 @@
|
||||
//
|
||||
// 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.
|
||||
|
||||
typedef int esp_err_t;
|
||||
|
||||
#define ESP_FAIL -1
|
||||
#define ESP_OK 0
|
||||
|
||||
#define ESP_ERR_NO_MEM 0x101
|
||||
#define ESP_ERR_INVALID_ARG 0x102
|
||||
#define ESP_ERR_INVALID_STATE 0x103
|
||||
#define ESP_ERR_INVALID_SIZE 0x104
|
||||
#define ESP_ERR_NOT_FOUND 0x105
|
||||
#define ESP_ERR_NOT_SUPPORTED 0x106
|
||||
#define ESP_ERR_TIMEOUT 0x107
|
@ -0,0 +1,49 @@
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef MDNS_HOST_ESP_LOG_H
|
||||
#define MDNS_HOST_ESP_LOG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define ESP_LOG_INFO 1
|
||||
#define ESP_LOG_BUFFER_HEXDUMP(...)
|
||||
|
||||
#define LOG_COLOR_BLACK "30"
|
||||
#define LOG_COLOR_RED "31"
|
||||
#define LOG_COLOR_GREEN "32"
|
||||
#define LOG_COLOR_BROWN "33"
|
||||
#define LOG_COLOR_BLUE "34"
|
||||
#define LOG_COLOR_PURPLE "35"
|
||||
#define LOG_COLOR_CYAN "36"
|
||||
#define LOG_COLOR(COLOR) "\033[0;" COLOR "m"
|
||||
#define LOG_BOLD(COLOR) "\033[1;" COLOR "m"
|
||||
#define LOG_RESET_COLOR "\033[0m"
|
||||
#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED) "E"
|
||||
#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN) "W"
|
||||
#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN) "I"
|
||||
#define LOG_COLOR_D LOG_COLOR(LOG_COLOR_CYAN) "D"
|
||||
#define LOG_COLOR_V "V"
|
||||
|
||||
#define ESP_LOGE(TAG, ...) do { \
|
||||
printf(LOG_COLOR_E); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
|
||||
#define ESP_LOGW(TAG, ...) do { \
|
||||
printf(LOG_COLOR_W); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
|
||||
#define ESP_LOGI(TAG, ...) do { \
|
||||
printf(LOG_COLOR_I); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
|
||||
#define ESP_LOGD(TAG, ...) do { \
|
||||
printf(LOG_COLOR_D); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
|
||||
#define ESP_LOGV(TAG, ...) do { \
|
||||
printf(LOG_COLOR_V); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
|
||||
|
||||
#endif //MDNS_HOST_ESP_LOG_H
|
@ -0,0 +1,19 @@
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef MDNS_HOST_ENDIAN_H
|
||||
#define MDNS_HOST_ENDIAN_H
|
||||
|
||||
#include_next "endian.h"
|
||||
|
||||
#endif //MDNS_HOST_ENDIAN_H
|
36
components/esp_modem/private_include/exception_stub.hpp
Normal file
36
components/esp_modem/private_include/exception_stub.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _EXCEPTION_STUB_HPP_
|
||||
#define _EXCEPTION_STUB_HPP_
|
||||
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
#define TRY_CATCH_RET_NULL(block) \
|
||||
try { block \
|
||||
} catch (std::bad_alloc& e) { \
|
||||
ESP_LOGE(TAG, "Out of memory"); \
|
||||
return nullptr; \
|
||||
} catch (esp_err_exception& e) { \
|
||||
esp_err_t err = e.get_err_t(); \
|
||||
ESP_LOGE(TAG, "%s: Exception caught with ESP err_code=%d", __func__, err); \
|
||||
ESP_LOGE(TAG, "%s", e.what()); \
|
||||
return nullptr; \
|
||||
}
|
||||
#else
|
||||
#define TRY_CATCH_RET_NULL(block) \
|
||||
block
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _EXCEPTION_STUB_HPP_
|
38
components/esp_modem/private_include/uart_resource.hpp
Normal file
38
components/esp_modem/private_include/uart_resource.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _UART_RESOURCE_HPP_
|
||||
#define _UART_RESOURCE_HPP_
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_modem_config.h"
|
||||
|
||||
struct esp_modem_dte_config;
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
/**
|
||||
* @brief Uart Resource is a platform specific struct which is implemented separately for ESP_PLATFORM and linux target
|
||||
*/
|
||||
struct uart_resource {
|
||||
explicit uart_resource(const esp_modem_dte_config *config, struct QueueDefinition** event_queue, int fd);
|
||||
~uart_resource();
|
||||
uart_port_t port{};
|
||||
};
|
||||
|
||||
std::unique_ptr<Terminal> create_vfs_terminal(const esp_modem_dte_config *config);
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _UART_RESOURCE_HPP_
|
28
components/esp_modem/private_include/uart_terminal.hpp
Normal file
28
components/esp_modem/private_include/uart_terminal.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
#ifndef _UART_TERMINAL_HPP_
|
||||
#define _UART_TERMINAL_HPP_
|
||||
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
|
||||
struct esp_modem_dte_config;
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
std::unique_ptr<Terminal> create_uart_terminal(const esp_modem_dte_config *config);
|
||||
|
||||
} // namespace esp_modem
|
||||
|
||||
#endif // _UART_TERMINAL_HPP_
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user