Skip to content

Commit b7d46d8

Browse files
committed
fix(modem): Fix URC callback + add test
1 parent 3c1624a commit b7d46d8

File tree

7 files changed

+362
-3
lines changed

7 files changed

+362
-3
lines changed

common_components/modem_sim/pppd_cmd/custom/at_custom_cmd.c

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "esp_netif.h"
1717
#include "esp_netif_ppp.h"
1818
#include "esp_check.h"
19+
#include "esp_http_server.h"
20+
#include "esp_timer.h"
1921

2022
extern uint8_t g_at_cmd_port;
2123

@@ -73,6 +75,7 @@ static uint8_t at_setup_cmd_test(uint8_t para_num)
7375

7476
#define TAG "at_custom_cmd"
7577
static esp_netif_t *s_netif = NULL;
78+
static httpd_handle_t http_server = NULL;
7679

7780
static void on_ppp_event(void *arg, esp_event_base_t base, int32_t event_id, void *data)
7881
{
@@ -206,10 +209,202 @@ static uint8_t at_exe_cereg(uint8_t *cmd_name)
206209
return ESP_AT_RESULT_CODE_OK;
207210
}
208211

212+
/* HTTP Server handlers */
213+
static esp_err_t hello_get_handler(httpd_req_t *req)
214+
{
215+
const char* resp_str = "Hello from ESP-AT HTTP Server!";
216+
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
217+
return ESP_OK;
218+
}
219+
220+
static esp_err_t root_get_handler(httpd_req_t *req)
221+
{
222+
const char* resp_str = "ESP-AT HTTP Server is running";
223+
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
224+
return ESP_OK;
225+
}
226+
227+
static esp_err_t test_get_handler(httpd_req_t *req)
228+
{
229+
const char* resp_str = "{\"status\":\"success\",\"message\":\"Test endpoint working\",\"timestamp\":12345}";
230+
httpd_resp_set_type(req, "application/json");
231+
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
232+
return ESP_OK;
233+
}
234+
235+
static esp_err_t async_get_handler(httpd_req_t *req)
236+
{
237+
printf("Starting async chunked response handler\r\n");
238+
239+
// Set content type for plain text response
240+
httpd_resp_set_type(req, "text/plain");
241+
242+
// Static counter to track requests
243+
static uint8_t req_count = 0;
244+
req_count++;
245+
246+
// Send initial response with request count
247+
char buffer[256];
248+
snprintf(buffer, sizeof(buffer), "=== Async Response #%d ===\r\n", req_count);
249+
httpd_resp_sendstr_chunk(req, buffer);
250+
251+
// Long message broken into chunks
252+
const char* chunks[] = {
253+
"This is a simulated slow server response.\r\n",
254+
"Chunk 1: The ESP-AT HTTP server is demonstrating...\r\n",
255+
"Chunk 2: ...asynchronous chunked transfer encoding...\r\n",
256+
"Chunk 3: ...with artificial delays between chunks...\r\n",
257+
"Chunk 4: ...to simulate real-world network conditions.\r\n",
258+
"Chunk 5: Processing data... please wait...\r\n",
259+
"Chunk 6: Still processing... almost done...\r\n",
260+
"Chunk 7: Final chunk - transfer complete!\r\n",
261+
"=== END OF RESPONSE ===\r\n"
262+
};
263+
264+
int num_chunks = sizeof(chunks) / sizeof(chunks[0]);
265+
266+
// Send each chunk with delays
267+
for (int i = 0; i < num_chunks; i++) {
268+
// Add a delay to simulate slow processing
269+
vTaskDelay(pdMS_TO_TICKS(1500)); // 1.5 second delay between chunks
270+
271+
// Add chunk number and timestamp
272+
snprintf(buffer, sizeof(buffer), "[%d/%d] [%d ms] %s",
273+
i + 1, num_chunks, (int)(esp_timer_get_time() / 1000), chunks[i]);
274+
275+
printf("Sending chunk %d: %s", i + 1, chunks[i]);
276+
httpd_resp_sendstr_chunk(req, buffer);
277+
}
278+
279+
// Add final summary
280+
vTaskDelay(pdMS_TO_TICKS(500));
281+
snprintf(buffer, sizeof(buffer), "\r\nTransfer completed in %d chunks with delays.\r\n", num_chunks);
282+
httpd_resp_sendstr_chunk(req, buffer);
283+
284+
// Send NULL to signal end of chunked transfer
285+
httpd_resp_sendstr_chunk(req, NULL);
286+
287+
printf("Async chunked response completed\r\n");
288+
return ESP_OK;
289+
}
290+
291+
static const httpd_uri_t hello = {
292+
.uri = "/hello",
293+
.method = HTTP_GET,
294+
.handler = hello_get_handler,
295+
.user_ctx = NULL
296+
};
297+
298+
static const httpd_uri_t root = {
299+
.uri = "/",
300+
.method = HTTP_GET,
301+
.handler = root_get_handler,
302+
.user_ctx = NULL
303+
};
304+
305+
static const httpd_uri_t test = {
306+
.uri = "/test",
307+
.method = HTTP_GET,
308+
.handler = test_get_handler,
309+
.user_ctx = NULL
310+
};
311+
312+
static const httpd_uri_t async_uri = {
313+
.uri = "/async",
314+
.method = HTTP_GET,
315+
.handler = async_get_handler,
316+
.user_ctx = NULL
317+
};
318+
319+
static esp_err_t start_http_server(void)
320+
{
321+
if (http_server != NULL) {
322+
printf("HTTP server already running\r\n");
323+
return ESP_OK;
324+
}
325+
326+
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
327+
config.server_port = 8080;
328+
config.lru_purge_enable = true;
329+
330+
printf("Starting HTTP server on port: %d\r\n", config.server_port);
331+
if (httpd_start(&http_server, &config) == ESP_OK) {
332+
printf("Registering URI handlers\r\n");
333+
httpd_register_uri_handler(http_server, &hello);
334+
httpd_register_uri_handler(http_server, &root);
335+
httpd_register_uri_handler(http_server, &test);
336+
httpd_register_uri_handler(http_server, &async_uri);
337+
return ESP_OK;
338+
}
339+
340+
printf("Error starting HTTP server!\r\n");
341+
return ESP_FAIL;
342+
}
343+
344+
static esp_err_t stop_http_server(void)
345+
{
346+
if (http_server != NULL) {
347+
httpd_stop(http_server);
348+
http_server = NULL;
349+
printf("HTTP server stopped\r\n");
350+
return ESP_OK;
351+
}
352+
return ESP_OK;
353+
}
354+
355+
/* HTTP Server AT Commands */
356+
static uint8_t at_test_httpd(uint8_t *cmd_name)
357+
{
358+
uint8_t buffer[64] = {0};
359+
snprintf((char *)buffer, 64, "AT%s=<0/1> - Start/Stop HTTP server\r\n", cmd_name);
360+
esp_at_port_write_data(buffer, strlen((char *)buffer));
361+
return ESP_AT_RESULT_CODE_OK;
362+
}
363+
364+
static uint8_t at_query_httpd(uint8_t *cmd_name)
365+
{
366+
uint8_t buffer[64] = {0};
367+
snprintf((char *)buffer, 64, "+HTTPD:%d\r\n", http_server != NULL ? 1 : 0);
368+
esp_at_port_write_data(buffer, strlen((char *)buffer));
369+
return ESP_AT_RESULT_CODE_OK;
370+
}
371+
372+
static uint8_t at_setup_httpd(uint8_t para_num)
373+
{
374+
int32_t action = 0;
375+
if (esp_at_get_para_as_digit(0, &action) != ESP_AT_PARA_PARSE_RESULT_OK) {
376+
return ESP_AT_RESULT_CODE_ERROR;
377+
}
378+
379+
if (action == 1) {
380+
if (start_http_server() == ESP_OK) {
381+
printf("HTTP server started successfully\r\n");
382+
return ESP_AT_RESULT_CODE_OK;
383+
}
384+
} else if (action == 0) {
385+
if (stop_http_server() == ESP_OK) {
386+
return ESP_AT_RESULT_CODE_OK;
387+
}
388+
}
389+
390+
return ESP_AT_RESULT_CODE_ERROR;
391+
}
392+
393+
static uint8_t at_exe_httpd(uint8_t *cmd_name)
394+
{
395+
// Default action: start server
396+
if (start_http_server() == ESP_OK) {
397+
printf("HTTP server started via execute command\r\n");
398+
return ESP_AT_RESULT_CODE_OK;
399+
}
400+
return ESP_AT_RESULT_CODE_ERROR;
401+
}
402+
209403

210404
static const esp_at_cmd_struct at_custom_cmd[] = {
211405
{"+PPPD", at_test_cmd_test, at_query_cmd_test, at_setup_cmd_test, at_exe_cmd_test},
212406
{"+CEREG", at_test_cereg, at_query_cereg, at_setup_cereg, at_exe_cereg},
407+
{"+HTTPD", at_test_httpd, at_query_httpd, at_setup_httpd, at_exe_httpd},
213408
/**
214409
* @brief You can define your own AT commands here.
215410
*/

components/esp_modem/src/esp_modem_dte.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ bool DTE::command_cb::process_line(uint8_t *data, size_t consumed, size_t len)
372372
if (urc_handler) {
373373
commandResult = urc_handler(data, consumed + len);
374374
}
375-
if (result != command_result::TIMEOUT && got_line == nullptr) {
375+
if (result != command_result::TIMEOUT || got_line == nullptr) {
376376
return false; // this line has been processed already (got OK or FAIL previously)
377377
}
378378
#endif

components/esp_modem/src/esp_modem_uart.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ int UartTerminal::read(uint8_t *data, size_t len)
178178
if (length > 0) {
179179
int read_len = uart_read_bytes(uart.port, data, length, portMAX_DELAY);
180180
#if CONFIG_ESP_MODEM_ADD_DEBUG_LOGS
181-
ESP_LOG_BUFFER_HEXDUMP("uart-rx", data, read_len, ESP_LOG_DEBUG);
181+
ESP_LOG_BUFFER_HEXDUMP("uart-rx", data, read_len, ESP_LOG_WARN);
182182
#endif
183183
return read_len;
184184
}
@@ -188,7 +188,7 @@ int UartTerminal::read(uint8_t *data, size_t len)
188188
int UartTerminal::write(uint8_t *data, size_t len)
189189
{
190190
#if CONFIG_ESP_MODEM_ADD_DEBUG_LOGS
191-
ESP_LOG_BUFFER_HEXDUMP("uart-tx", data, len, ESP_LOG_DEBUG);
191+
ESP_LOG_BUFFER_HEXDUMP("uart-tx", data, len, ESP_LOG_INFO);
192192
#endif
193193
return uart_write_bytes_compat(uart.port, data, len);
194194
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# The following lines of boilerplate have to be in your project's CMakeLists
2+
# in this exact order for cmake to work correctly
3+
cmake_minimum_required(VERSION 3.5)
4+
5+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6+
set(COMPONENTS main)
7+
project(urc_test)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
idf_component_register(SRCS "urc_test.cpp"
2+
INCLUDE_DIRS ".")
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## IDF Component Manager Manifest File
2+
dependencies:
3+
## Required IDF version
4+
idf: ">=4.1.0"
5+
espressif/esp_modem:
6+
version: "^1.0.0"
7+
override_path: "../../../"

0 commit comments

Comments
 (0)