Skip to content

Commit 11a8567

Browse files
authored
Merge pull request #884 from david-cermak/feat/modem_prepare_v2.0
[modem]: Prepare for v2.0 release
2 parents 2681b9b + 68e299a commit 11a8567

File tree

5 files changed

+507
-0
lines changed

5 files changed

+507
-0
lines changed

docs/esp_modem/en/README.rst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,41 @@ Component Kconfig
176176
Compile-time configuration is provided using menuconfig. Please check
177177
the description for the CMUX mode configuration options.
178178

179+
Development Mode
180+
~~~~~~~~~~~~~~~~
181+
182+
ESP-MODEM supports two different modes for handling AT command definitions:
183+
184+
**Production Mode (Default)**
185+
Uses pre-generated headers and sources with common AT commands from the ``command/`` directory.
186+
This mode provides better IDE navigation and code completion, making it ideal for:
187+
188+
- Application development using existing AT commands
189+
- Better code navigation and IntelliSense support
190+
- Faster compilation times
191+
- Stable, tested command implementations
192+
193+
**Development Mode**
194+
Uses in-place macro expansion with AT commands from the ``generate/`` directory.
195+
This mode is designed for ESP-MODEM library developers who need to:
196+
197+
- Modify or add new AT command definitions in ``esp_modem_command_declare.inc``
198+
- Work directly with the source definitions of AT commands
199+
- Debug command implementations
200+
- Contribute to the core ESP-MODEM library development
201+
202+
.. note::
203+
For adding support for new modem modules, you typically don't need development mode.
204+
Instead, create a custom module class inheriting from ``GenericModule`` and add your
205+
commands directly in your project's headers/sources. See the ``pppos_client`` example
206+
for a demonstration of this approach.
207+
208+
To enable development mode, set ``CONFIG_ESP_MODEM_ENABLE_DEVELOPMENT_MODE=y`` in your project configuration.
209+
210+
.. note::
211+
Development mode requires the C preprocessor to expand command definitions at compile time,
212+
which may result in longer compilation times and larger binary sizes compared to production mode.
213+
179214
Runtime configuration
180215
~~~~~~~~~~~~~~~~~~~~~
181216

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
Customization
2+
=============
3+
4+
This chapter covers how to customize ESP-MODEM for your specific requirements by creating custom modules and adding new commands.
5+
6+
Custom Module Development
7+
-------------------------
8+
9+
For most customization needs, you don't need development mode. Instead, you can create custom modules that inherit from existing ESP-MODEM classes.
10+
11+
Creating Custom Modules
12+
~~~~~~~~~~~~~~~~~~~~~~~
13+
14+
The recommended approach for adding support for new modem modules or custom commands is to create a custom module class. This approach:
15+
16+
- **Doesn't require development mode**
17+
- **Keeps your changes separate** from the core library
18+
- **Allows easy updates** of the ESP-MODEM library
19+
- **Provides full flexibility** for custom commands
20+
21+
Basic Custom Module Example
22+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
23+
24+
Here's a simple example of creating a custom module:
25+
26+
.. code-block:: cpp
27+
28+
#include "cxx_include/esp_modem_api.hpp"
29+
#include "cxx_include/esp_modem_command_library_utils.hpp"
30+
31+
class MyCustomModule: public GenericModule {
32+
using GenericModule::GenericModule;
33+
34+
public:
35+
// Add a new command
36+
command_result get_custom_info(std::string &info) {
37+
return esp_modem::dce_commands::generic_get_string(
38+
dte.get(), "AT+CUSTOM?\r", info);
39+
}
40+
41+
// Override an existing command
42+
command_result get_signal_quality(int &rssi, int &ber) override {
43+
// Custom implementation
44+
return esp_modem::dce_commands::generic_get_string(
45+
dte.get(), "AT+CSQ\r", rssi, ber);
46+
}
47+
};
48+
49+
Using Custom Modules with C++ API
50+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
51+
52+
With the C++ API, you can use your custom module directly:
53+
54+
.. code-block:: cpp
55+
56+
// Create DCE with custom module
57+
auto dce = dce_factory::Factory::create_unique_dce_from<MyCustomModule>(
58+
dce_config, std::move(dte), netif);
59+
60+
// Use custom commands
61+
std::string info;
62+
auto result = dce->get_custom_info(info);
63+
64+
Using Custom Modules with C API
65+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
66+
67+
To use custom modules with the C API, you need to:
68+
69+
1. **Enable custom module support** in Kconfig:
70+
71+
.. code-block:: bash
72+
73+
idf.py menuconfig
74+
# Navigate to: Component config → ESP-MODEM
75+
# Enable: "Add support for custom module in C-API"
76+
77+
2. **Create a custom module header** (e.g., ``custom_module.hpp``) in your main component
78+
79+
3. **Implement the required functions**:
80+
81+
.. code-block:: cpp
82+
83+
// Create custom DCE function
84+
DCE *esp_modem_create_custom_dce(
85+
const esp_modem_dce_config_t *dce_config,
86+
std::shared_ptr<DTE> dte,
87+
esp_netif_t *netif) {
88+
return dce_factory::Factory::create_unique_dce_from<MyCustomModule, DCE *>(
89+
dce_config, std::move(dte), netif);
90+
}
91+
92+
// Add C API wrappers for custom commands
93+
extern "C" esp_err_t esp_modem_get_custom_info(esp_modem_dce_t *dce_wrap, char *info) {
94+
if (dce_wrap == nullptr || dce_wrap->dce == nullptr) {
95+
return ESP_ERR_INVALID_ARG;
96+
}
97+
std::string info_str{CONFIG_ESP_MODEM_C_API_STR_MAX};
98+
auto ret = command_response_to_esp_err(
99+
static_cast<MyCustomModule *>(dce_wrap->dce->get_module())->get_custom_info(info_str));
100+
if (ret == ESP_OK && !info_str.empty()) {
101+
strlcpy(info, info_str.c_str(), CONFIG_ESP_MODEM_C_API_STR_MAX);
102+
}
103+
return ret;
104+
}
105+
106+
4. **Use the custom commands** in your C code:
107+
108+
.. code-block:: c
109+
110+
char info[128];
111+
esp_err_t ret = esp_modem_get_custom_info(dce, info);
112+
113+
Complete Example
114+
~~~~~~~~~~~~~~~~
115+
116+
See the ``examples/pppos_client`` example for a complete demonstration of custom module development. This example shows:
117+
118+
- Creating a custom module that inherits from ``GenericModule``
119+
- Adding new commands (``get_time()``)
120+
- Overriding existing commands (``get_signal_quality()``)
121+
- Integration with both C++ and C APIs
122+
123+
Available Base Classes
124+
----------------------
125+
126+
You can inherit from several base classes depending on your needs:
127+
128+
**GenericModule**
129+
The most general implementation of a common modem. Use this when:
130+
- Your modem supports most standard AT commands
131+
- You need to add a few custom commands
132+
- You want to override some existing commands
133+
134+
**Specific Module Classes**
135+
Inherit from existing module classes (e.g., ``SIM800``, ``BG96``, ``SIM7600``) when:
136+
- Your modem is very similar to an existing one
137+
- You only need minor modifications
138+
- You want to leverage existing device-specific optimizations
139+
140+
**ModuleIf**
141+
Use this minimal interface when:
142+
- You only need basic AT command functionality
143+
- You don't need network interface features
144+
- You want to implement a custom DTE without DCE
145+
146+
Command Utilities
147+
-----------------
148+
149+
ESP-MODEM provides utility functions to help implement custom commands:
150+
151+
**Generic Command Helpers**
152+
- ``generic_get_string()`` - Parse string responses
153+
- ``generic_get_int()`` - Parse integer responses
154+
- ``generic_set_string()`` - Send string commands
155+
- ``generic_set_int()`` - Send integer commands
156+
157+
**Response Parsing**
158+
- ``get_number_from_string()`` - Extract numbers from responses
159+
- ``get_string_from_response()`` - Extract strings from responses
160+
- ``get_urc()`` - Handle unsolicited result codes
161+
162+
Example Usage:
163+
.. code-block:: cpp
164+
165+
// Get a string value
166+
command_result get_imei(std::string &imei) {
167+
return esp_modem::dce_commands::generic_get_string(
168+
dte.get(), "AT+CGSN\r", imei);
169+
}
170+
171+
// Get an integer value
172+
command_result get_signal_strength(int &rssi) {
173+
return esp_modem::dce_commands::generic_get_int(
174+
dte.get(), "AT+CSQ\r", rssi);
175+
}
176+
177+
Best Practices
178+
--------------
179+
180+
**For Application Developers:**
181+
- Use production mode for better IDE support and faster builds
182+
- Create custom modules for new modem support
183+
- Inherit from ``GenericModule`` or other existing modules
184+
- Keep customizations in your project, not in the ESP-MODEM library
185+
186+
**Module Design:**
187+
- Choose the most appropriate base class for your needs
188+
- Override only the commands you need to modify
189+
- Use the provided utility functions for common operations
190+
- Follow the existing command naming conventions
191+
192+
**Testing:**
193+
- Test your custom module with real hardware
194+
- Verify compatibility with existing ESP-MODEM features
195+
- Test both C++ and C API usage if applicable
196+
- Consider edge cases and error handling
197+
198+
**Documentation:**
199+
- Document your custom commands clearly
200+
- Provide usage examples
201+
- Explain any device-specific requirements
202+
- Note any limitations or known issues

0 commit comments

Comments
 (0)