esp_modem: Moved to component folder

This commit is contained in:
David Čermák
2021-05-19 23:00:28 +08:00
committed by David Cermak
parent 61f264f97a
commit 90641c89eb
133 changed files with 21 additions and 21 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

File diff suppressed because it is too large Load Diff

View 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.

View 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.

View 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:

View 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', }

View 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.

View 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`

View 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);

View 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);
};

View 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

View 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>

View 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
![DCE_architecture](DCE_DTE_collaboration.png)
## 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.
![CMUX Terminal](CMux_collaboration.png)

View 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: