11/*
2- * Copyright (c) 2006-2024 RT-Thread Development Team
2+ * Copyright (c) 2006-2025 RT-Thread Development Team
33 *
44 * SPDX-License-Identifier: Apache-2.0
55 *
1010 * 2018-08-17 chenyong multiple client support
1111 * 2021-03-17 Meco Man fix a buf of leaking memory
1212 * 2021-07-14 Sszl fix a buf of leaking memory
13+ * 2025-01-02 dongly support SERIAL_V2
14+ * 2025-04-18 RyanCw support New SERIAL_V2
1315 */
1416
1517#include <at.h>
1921
2022#define LOG_TAG "at.clnt"
2123#include <at_log.h>
22-
2324#ifdef AT_USING_CLIENT
2425
2526#define AT_RESP_END_OK "OK"
2627#define AT_RESP_END_ERROR "ERROR"
2728#define AT_RESP_END_FAIL "FAIL"
2829#define AT_END_CR_LF "\r\n"
30+ #define AT_END_CR "\r"
31+ #define AT_END_LF "\n"
32+ #define AT_END_RAW ""
2933
3034static struct at_client at_client_table [AT_CLIENT_NUM_MAX ] = { 0 };
3135
@@ -34,6 +38,9 @@ extern rt_size_t at_utils_send(rt_device_t dev,
3438 const void * buffer ,
3539 rt_size_t size );
3640extern rt_size_t at_vprintfln (rt_device_t device , char * send_buf , rt_size_t buf_size , const char * format , va_list args );
41+ extern rt_size_t at_vprintf (rt_device_t device , char * send_buf , rt_size_t buf_size , const char * format , va_list args );
42+ extern rt_size_t at_vprintfcr (rt_device_t device , char * send_buf , rt_size_t buf_size , const char * format , va_list args );
43+ extern rt_size_t at_vprintflf (rt_device_t device , char * send_buf , rt_size_t buf_size , const char * format , va_list args );
3744extern void at_print_raw_cmd (const char * type , const char * cmd , rt_size_t size );
3845
3946/**
@@ -219,7 +226,8 @@ int at_resp_parse_line_args(at_response_t resp, rt_size_t resp_line, const char
219226 RT_ASSERT (resp );
220227 RT_ASSERT (resp_expr );
221228
222- if ((resp_line_buf = at_resp_get_line (resp , resp_line )) == RT_NULL )
229+ resp_line_buf = at_resp_get_line (resp , resp_line );
230+ if (resp_line_buf == RT_NULL )
223231 {
224232 return -1 ;
225233 }
@@ -253,7 +261,8 @@ int at_resp_parse_line_args_by_kw(at_response_t resp, const char *keyword, const
253261 RT_ASSERT (resp );
254262 RT_ASSERT (resp_expr );
255263
256- if ((resp_line_buf = at_resp_get_line_by_kw (resp , keyword )) == RT_NULL )
264+ resp_line_buf = at_resp_get_line_by_kw (resp , keyword );
265+ if (resp_line_buf == RT_NULL )
257266 {
258267 return -1 ;
259268 }
@@ -341,6 +350,97 @@ int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr
341350 return result ;
342351}
343352
353+ /**
354+ * Send commands through custom formatting to AT server and wait response.
355+ *
356+ * @param client current AT client object
357+ * @param resp AT response object, using RT_NULL when you don't care response
358+ * @param format formatting macro, it can be one of these values: AT_END_CR_LF, AT_END_RAW, AT_END_CR, AT_END_LF.
359+ * Behavior of AT_END_CR_LF is same as at_obj_exec_cmd, and it will add \r\n symnbol behind message.
360+ * AT_END_RAW means frame work won't modify anything of message. AT_END_CR will add \r for Carriage
361+ * Return. AT_END_LF means add \\n for Line Feed.
362+ * @param cmd_expr AT commands expression
363+ *
364+ * @return 0 : success
365+ * -1 : response status error
366+ * -2 : wait timeout
367+ * -7 : enter AT CLI mode
368+ */
369+ int at_obj_exec_cmd_format (at_client_t client , at_response_t resp , const char * format , const char * cmd_expr , ...)
370+ {
371+ va_list args ;
372+ rt_err_t result = RT_EOK ;
373+
374+ RT_ASSERT (cmd_expr );
375+
376+ if (client == RT_NULL )
377+ {
378+ LOG_E ("input AT Client object is NULL, please create or get AT Client object!" );
379+ return - RT_ERROR ;
380+ }
381+
382+ /* check AT CLI mode */
383+ if (client -> status == AT_STATUS_CLI && resp )
384+ {
385+ return - RT_EBUSY ;
386+ }
387+
388+ rt_mutex_take (client -> lock , RT_WAITING_FOREVER );
389+
390+ client -> resp_status = AT_RESP_OK ;
391+
392+ if (resp != RT_NULL )
393+ {
394+ resp -> buf_len = 0 ;
395+ resp -> line_counts = 0 ;
396+ }
397+
398+ client -> resp = resp ;
399+ rt_sem_control (client -> resp_notice , RT_IPC_CMD_RESET , RT_NULL );
400+
401+ va_start (args , cmd_expr );
402+
403+ if (strcmp (format , AT_END_CR_LF ) == 0 )
404+ {
405+ client -> last_cmd_len = at_vprintfln (client -> device , client -> send_buf , client -> send_bufsz , cmd_expr , args );
406+ }
407+ else if (strcmp (format , AT_END_RAW ) == 0 )
408+ {
409+ client -> last_cmd_len = at_vprintf (client -> device , client -> send_buf , client -> send_bufsz , cmd_expr , args );
410+ }
411+ else if (strcmp (format , AT_END_CR ) == 0 )
412+ {
413+ client -> last_cmd_len = at_vprintfcr (client -> device , client -> send_buf , client -> send_bufsz , cmd_expr , args );
414+ }
415+ else if (strcmp (format , AT_END_LF ) == 0 )
416+ {
417+ client -> last_cmd_len = at_vprintflf (client -> device , client -> send_buf , client -> send_bufsz , cmd_expr , args );
418+ }
419+
420+ va_end (args );
421+
422+ if (resp != RT_NULL )
423+ {
424+ if (rt_sem_take (client -> resp_notice , resp -> timeout ) != RT_EOK )
425+ {
426+ LOG_W ("execute command (%.*s) timeout (%d ticks)!" , client -> last_cmd_len , client -> send_buf , resp -> timeout );
427+ client -> resp_status = AT_RESP_TIMEOUT ;
428+ result = - RT_ETIMEOUT ;
429+ }
430+ else if (client -> resp_status != AT_RESP_OK )
431+ {
432+ LOG_E ("execute command (%.*s) failed!" , client -> last_cmd_len , client -> send_buf );
433+ result = - RT_ERROR ;
434+ }
435+ }
436+
437+ client -> resp = RT_NULL ;
438+
439+ rt_mutex_release (client -> lock );
440+
441+ return result ;
442+ }
443+
344444/**
345445 * Waiting for connection to external devices.
346446 *
@@ -444,7 +544,7 @@ static rt_err_t at_client_getchar(at_client_t client, char *ch, rt_int32_t timeo
444544{
445545 rt_err_t result = RT_EOK ;
446546
447- #if (!defined(RT_USING_SERIAL_V2 ) || RT_VER_NUM < 0x50200 )
547+ #if (!defined(RT_USING_SERIAL_V2 ))
448548 while (rt_device_read (client -> device , 0 , ch , 1 ) == 0 )
449549 {
450550 result = rt_sem_take (client -> rx_notice , rt_tick_from_millisecond (timeout ));
@@ -495,7 +595,7 @@ rt_size_t at_client_obj_recv(at_client_t client, char *buf, rt_size_t size, rt_i
495595 return 0 ;
496596 }
497597
498- #if (!defined(RT_USING_SERIAL_V2 ) || RT_VER_NUM < 0x50200 )
598+ #if (!defined(RT_USING_SERIAL_V2 ))
499599 while (size )
500600 {
501601 rt_size_t read_len ;
@@ -703,7 +803,8 @@ static int at_recv_readline(at_client_t client)
703803 }
704804
705805 /* is newline or URC data */
706- if ((client -> urc = get_urc_obj (client )) != RT_NULL || (ch == '\n' && last_ch == '\r' )
806+ client -> urc = get_urc_obj (client );
807+ if (client -> urc != RT_NULL || (ch == '\n' && last_ch == '\r' )
707808 || (client -> end_sign != 0 && ch == client -> end_sign ))
708809 {
709810 if (is_full )
@@ -800,7 +901,7 @@ static void client_parser(at_client_t client)
800901 }
801902}
802903
803- #if (!defined(RT_USING_SERIAL_V2 ) || RT_VER_NUM < 0x50200 )
904+ #if (!defined(RT_USING_SERIAL_V2 ))
804905static rt_err_t at_client_rx_ind (rt_device_t dev , rt_size_t size )
805906{
806907 int idx = 0 ;
@@ -858,7 +959,7 @@ static int at_client_para_init(at_client_t client)
858959 goto __exit ;
859960 }
860961
861- #if (!defined(RT_USING_SERIAL_V2 ) || RT_VER_NUM < 0x50200 )
962+ #if (!defined(RT_USING_SERIAL_V2 ))
862963 rt_snprintf (name , RT_NAME_MAX , "%s%d" , AT_CLIENT_SEM_NAME , at_client_num );
863964 client -> rx_notice = rt_sem_create (name , 0 , RT_IPC_FLAG_FIFO );
864965 if (client -> rx_notice == RT_NULL )
@@ -886,7 +987,8 @@ static int at_client_para_init(at_client_t client)
886987 (void (* )(void * parameter ))client_parser ,
887988 client ,
888989 1024 + 512 ,
889- RT_THREAD_PRIORITY_MAX / 3 - 1 ,
990+ 6 ,
991+ /* RT_THREAD_PRIORITY_MAX / 3 - 1,*/
890992 5 );
891993 if (client -> parser == RT_NULL )
892994 {
@@ -901,7 +1003,7 @@ static int at_client_para_init(at_client_t client)
9011003 rt_mutex_delete (client -> lock );
9021004 }
9031005
904- #if (!defined(RT_USING_SERIAL_V2 ) || RT_VER_NUM < 0x50200 )
1006+ #if (!defined(RT_USING_SERIAL_V2 ))
9051007 if (client -> rx_notice )
9061008 {
9071009 rt_sem_delete (client -> rx_notice );
@@ -984,7 +1086,7 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz, rt_size_t send_bu
9841086 if (client -> device )
9851087 {
9861088 RT_ASSERT (client -> device -> type == RT_Device_Class_Char );
987- #if (!defined(RT_USING_SERIAL_V2 ) || RT_VER_NUM < 0x50200 )
1089+ #if (!defined(RT_USING_SERIAL_V2 ))
9881090 rt_device_set_rx_indicate (client -> device , at_client_rx_ind );
9891091 /* using DMA mode first */
9901092 open_result = rt_device_open (client -> device , RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX );
@@ -1021,4 +1123,4 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz, rt_size_t send_bu
10211123
10221124 return result ;
10231125}
1024- #endif /* AT_USING_CLIENT */
1126+ #endif /* AT_USING_CLIENT */
0 commit comments