1.Optimized the processing logic when multi-line command execution fails.

2. Resolve URC message containing ':' character causing parsing failure.
This commit is contained in:
roger.luo 2023-01-09 23:28:04 +08:00
parent 8866cdf7f9
commit a1cf6f2672
3 changed files with 64 additions and 46 deletions

View File

@ -1,6 +1,6 @@
<!-- navbar.md --> <!-- navbar.md -->
* [介绍](readme#简介) * [介绍](README#简介)
* [快速上手](quickStart#基础应用) * [快速上手](quickStart#基础应用)
* [高级教程](Expert#高级教程) * [高级教程](Expert#高级教程)
* [平台移植](Porting#平台移植) * [平台移植](Porting#平台移植)

View File

@ -8,11 +8,16 @@
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2020-01-02 roger.luo Initial version * 2020-01-02 roger.luo Initial version
* 2021-01-20 roger.luo Add debugging interface, and at the same time solve * 2021-01-20 roger.luo Add debugging interface, and at the same time
* the problem of uninitialized linked list leading to * solve the problem of uninitialized linked list
* segment fault. * leading to segment fault.
* 2021-03-03 roger.luo Fix the problem of frequent print receive timeout caused by not clearing the URC counter. * 2021-03-03 roger.luo Fix the problem of frequent print receive timeout
* caused by not clearing the URC counter.
* 2022-10-01 roger.luo Redesign the entire AT framework and release V2.0. * 2022-10-01 roger.luo Redesign the entire AT framework and release V2.0.
* 2023-01-09 roger.luo Optimized the processing logic when multi-line
* command execution fails.
* 2023-01-10 roger.luo Resolve URC message containing ':' character
* causing parsing failure.
******************************************************************************/ ******************************************************************************/
#ifndef _AT_CHAT_H_ #ifndef _AT_CHAT_H_
#define _AT_CHAT_H_ #define _AT_CHAT_H_
@ -243,7 +248,7 @@ bool at_exec_cmd(at_obj_t *at, const at_attr_t *attr, const char *cmd, ...);
bool at_exec_vcmd(at_obj_t *at, const at_attr_t *attr, const char *cmd, va_list va); bool at_exec_vcmd(at_obj_t *at, const at_attr_t *attr, const char *cmd, va_list va);
bool at_send_singlline(at_obj_t *at, at_callback_t cb, int timeout, int retry, const char *singlline); bool at_send_singlline(at_obj_t *at, const at_attr_t *attr, const char *singlline);
bool at_send_multiline(at_obj_t *at, const at_attr_t *attr, const char **multiline); bool at_send_multiline(at_obj_t *at, const at_attr_t *attr, const char **multiline);

View File

@ -8,11 +8,16 @@
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2020-01-02 roger.luo Initial version * 2020-01-02 roger.luo Initial version
* 2021-01-20 roger.luo Add debugging interface, and at the same time solve * 2021-01-20 roger.luo Add debugging interface, and at the same time
* the problem of uninitialized linked list leading to * solve the problem of uninitialized linked list
* segment fault. * leading to segment fault.
* 2021-03-03 roger.luo Fix the problem of frequent print receive timeout caused by not clearing the URC counter. * 2021-03-03 roger.luo Fix the problem of frequent print receive timeout
* caused by not clearing the URC counter.
* 2022-10-01 roger.luo Redesign the entire AT framework and release V2.0. * 2022-10-01 roger.luo Redesign the entire AT framework and release V2.0.
* 2023-01-09 roger.luo Optimized the processing logic when multi-line
* command execution fails.
* 2023-01-10 roger.luo Resolve URC message containing ':' character
* causing parsing failure.
******************************************************************************/ ******************************************************************************/
#include "at_chat.h" #include "at_chat.h"
#include "at_port.h" #include "at_port.h"
@ -155,13 +160,7 @@ static inline at_info_t *obj_map(at_obj_t *at)
{ {
return (at_info_t *)at; return (at_info_t *)at;
} }
/**
* @brief void * -> work_item_t *
*/
static inline work_item_t *work_item_map(void *work_obj)
{
return (work_item_t *)work_obj;
}
static inline const at_adapter_t *__get_adapter(at_info_t *ai) static inline const at_adapter_t *__get_adapter(at_info_t *ai)
{ {
@ -196,7 +195,7 @@ static void send_cmdline(at_info_t *at, const char *cmd)
len = strlen(cmd); len = strlen(cmd);
__get_adapter(at)->write(cmd, len); __get_adapter(at)->write(cmd, len);
__get_adapter(at)->write("\r\n", 2); __get_adapter(at)->write("\r\n", 2);
AT_DEBUG(at,"=>:\r\n%s\r\n", cmd); AT_DEBUG(at,"->\r\n%s\r\n", cmd);
} }
/** /**
@ -268,10 +267,10 @@ static void at_next_wait(struct at_env *env, unsigned int ms)
static void update_work_state(work_item_t *wi, at_work_state state, at_resp_code code) static void update_work_state(work_item_t *wi, at_work_state state, at_resp_code code)
{ {
at_context_t *ctx = wi->attr.ctx;
wi->state = state; wi->state = state;
wi->code = code; wi->code = code;
#if AT_WORK_CONTEXT_EN #if AT_WORK_CONTEXT_EN
at_context_t *ctx = wi->attr.ctx;
if (ctx != NULL) { if (ctx != NULL) {
ctx->code = (at_resp_code)wi->code; ctx->code = (at_resp_code)wi->code;
ctx->work_state = (at_work_state)wi->state; ctx->work_state = (at_work_state)wi->state;
@ -294,8 +293,7 @@ static void at_finish(struct at_env *env, at_resp_code code)
static void do_at_callback(at_info_t *ai, work_item_t *wi, at_resp_code code) static void do_at_callback(at_info_t *ai, work_item_t *wi, at_resp_code code)
{ {
at_response_t r; at_response_t r;
at_context_t *ctx; AT_DEBUG(ai, "<-\r\n%s\r\n", ai->recvbuf);
AT_DEBUG(ai, "<=:\r\n%s\r\n", ai->recvbuf);
//Exception notification //Exception notification
if ((code == AT_RESP_ERROR || code == AT_RESP_TIMEOUT) && __get_adapter(ai)->error != NULL) { if ((code == AT_RESP_ERROR || code == AT_RESP_TIMEOUT) && __get_adapter(ai)->error != NULL) {
__get_adapter(ai)->error(&r); __get_adapter(ai)->error(&r);
@ -305,7 +303,7 @@ static void do_at_callback(at_info_t *ai, work_item_t *wi, at_resp_code code)
ai->err_occur = 0; ai->err_occur = 0;
} }
#if AT_WORK_CONTEXT_EN #if AT_WORK_CONTEXT_EN
ctx = wi->attr.ctx; at_context_t *ctx = wi->attr.ctx;
if (ctx != NULL ) { if (ctx != NULL ) {
if (ctx->respbuf != NULL/* && ctx->bufsize */) { if (ctx->respbuf != NULL/* && ctx->bufsize */) {
ctx->resplen = ai->recv_cnt >= ctx->bufsize ? ctx->bufsize - 1 : ai->recv_cnt; ctx->resplen = ai->recv_cnt >= ctx->bufsize ? ctx->bufsize - 1 : ai->recv_cnt;
@ -412,10 +410,12 @@ static work_item_t *create_work_item(at_info_t *ai, int type, const at_attr_t *a
it->attr = *attr; it->attr = *attr;
it->type = type; it->type = type;
it->state = AT_WORK_STAT_READY; it->state = AT_WORK_STAT_READY;
#if AT_WORK_CONTEXT_EN
if (attr->ctx) { if (attr->ctx) {
attr->ctx->code = AT_RESP_OK; attr->ctx->code = AT_RESP_OK;
attr->ctx->work_state = AT_WORK_STAT_READY; attr->ctx->work_state = AT_WORK_STAT_READY;
} }
#endif
return it; return it;
} }
@ -518,7 +518,7 @@ static int do_cmd_handler(at_info_t *ai)
do_at_callback(ai, wi, AT_RESP_ERROR); do_at_callback(ai, wi, AT_RESP_ERROR);
return true; return true;
} }
AT_DEBUG(ai, "<=\r\n%s\r\n", ai->recvbuf); AT_DEBUG(ai, "<-\r\n%s\r\n", ai->recvbuf);
env->state = AT_STAT_RETRY; //If the command responds incorrectly, it will wait for a while and try again. env->state = AT_STAT_RETRY; //If the command responds incorrectly, it will wait for a while and try again.
env->reset_timer(env); env->reset_timer(env);
} }
@ -558,7 +558,7 @@ static int send_multiline_handler(at_info_t *ai)
{ {
case AT_STAT_SEND: case AT_STAT_SEND:
if (cmds[env->i] == NULL) { /* All commands are sent.*/ if (cmds[env->i] == NULL) { /* All commands are sent.*/
do_at_callback(ai, wi, AT_RESP_OK); do_at_callback(ai, wi, env->params ? AT_RESP_OK : AT_RESP_ERROR);
return true; return true;
} }
send_cmdline(ai, cmds[env->i]); send_cmdline(ai, cmds[env->i]);
@ -572,23 +572,27 @@ static int send_multiline_handler(at_info_t *ai)
env->state = 0; env->state = 0;
env->i++; env->i++;
env->j = 0; env->j = 0;
env->params = (void *)true; /*Mark execution status*/
AT_DEBUG(ai, "<-\r\n%s\r\n", ai->recvbuf); AT_DEBUG(ai, "<-\r\n%s\r\n", ai->recvbuf);
} else if (find_substr(env, AT_DEF_RESP_ERR)) { } else if (find_substr(env, AT_DEF_RESP_ERR)) {
AT_DEBUG(ai, "<-\r\n%s\r\n", ai->recvbuf); AT_DEBUG(ai, "<-\r\n%s\r\n", ai->recvbuf);
if (env->j++ >= attr->retry) { env->j++;
do_at_callback(ai, wi, AT_RESP_ERROR); AT_DEBUG(ai, "CMD:'%s' failed to executed, retry:%d\r\n", cmds[env->i], env->j);
return true; if (env->j >= attr->retry) {
env->state = 0;
env->j = 0;
env->i++;
} else {
env->state = AT_STAT_RETRY; //After the command responds incorrect, try again after a period of time.
env->reset_timer(env);
} }
AT_DEBUG(ai, "<=\r\n%s\r\n", ai->recvbuf);
env->state = AT_STAT_RETRY; //After the command responds incorrect, try again after a period of time.
env->reset_timer(env);
} else if (env->is_timeout(env, AT_DEF_TIMEOUT)) { } else if (env->is_timeout(env, AT_DEF_TIMEOUT)) {
do_at_callback(ai, wi, AT_RESP_TIMEOUT); do_at_callback(ai, wi, AT_RESP_TIMEOUT);
return true; return true;
} }
break; break;
case AT_STAT_RETRY: case AT_STAT_RETRY:
if (env->is_timeout(env, 200)) if (env->is_timeout(env, 100))
env->state = AT_STAT_SEND;/*Go back to the send state and resend.*/ env->state = AT_STAT_SEND;/*Go back to the send state and resend.*/
break; break;
default: default:
@ -663,11 +667,13 @@ static void urc_handler_entry(at_info_t *ai, urc_recv_status status, char *urc,
{ {
int remain; int remain;
at_urc_info_t ctx = {status, urc, size}; at_urc_info_t ctx = {status, urc, size};
if (ai->cursor == NULL && ai->urc_target == 0)
AT_DEBUG(ai, "<=\r\n%s ...\r\n", urc);
/* Send URC event notification. */ /* Send URC event notification. */
remain = ai->urc_item ? ai->urc_item->handler(&ctx) : 0; remain = ai->urc_item ? ai->urc_item->handler(&ctx) : 0;
if (remain == 0) { if (remain == 0 && (ai->urc_item || ai->cursor == NULL)) {
if (ai->urc_target > 0)
AT_DEBUG(ai, "<=\r\n%.5s..\r\n", urc);
else
AT_DEBUG(ai, "<=\r\n%s\r\n", urc);
urc_reset(ai); urc_reset(ai);
} else { } else {
AT_DEBUG(ai,"URC receives %d bytes remaining.\r\n", remain); AT_DEBUG(ai,"URC receives %d bytes remaining.\r\n", remain);
@ -723,9 +729,12 @@ static void urc_recv_process(at_info_t *ai, char *buf, unsigned int size)
continue; continue;
urc_buf[ai->urc_cnt] = '\0'; urc_buf[ai->urc_cnt] = '\0';
if (ai->urc_item == NULL) { //Find the corresponding URC handler if (ai->urc_item == NULL) { //Find the corresponding URC handler
if (ai->urc_cnt < 3 || ai->urc_item = find_urc_item(ai, urc_buf, ai->urc_cnt);
(ai->urc_item = find_urc_item(ai, urc_buf, ai->urc_cnt)) == NULL) { if (ai->urc_item == NULL && ch == '\n') {
if (ai->urc_cnt > 2 && ai->cursor == NULL) //Unrecognized URC message
AT_DEBUG(ai, "%s\r\n", urc_buf);
urc_reset(ai); urc_reset(ai);
continue;
} }
} }
if (ai->urc_item != NULL && ch == ai->urc_item->endmark) if (ai->urc_item != NULL && ch == ai->urc_item->endmark)
@ -985,13 +994,9 @@ bool at_send_data(at_obj_t *at, const at_attr_t *attr, const void *databuf, unsi
* @retval Indicates whether the asynchronous work was enqueued successfully. * @retval Indicates whether the asynchronous work was enqueued successfully.
* @note Only the address is saved, so the 'singlline' can not be a local variable which will be destroyed. * @note Only the address is saved, so the 'singlline' can not be a local variable which will be destroyed.
*/ */
bool at_send_singlline(at_obj_t *at, at_callback_t cb, int timeout, int retry, const char *singlline) bool at_send_singlline(at_obj_t *at, const at_attr_t *attr, const char *singlline)
{ {
at_attr_t attr = at_def_attr; return add_work_item(obj_map(at), WORK_TYPE_SINGLLINE, attr, singlline, 0) != NULL;
attr.cb = cb;
attr.timeout = timeout;
attr.retry = retry;
return add_work_item(obj_map(at), WORK_TYPE_SINGLLINE, &attr, singlline, 0) != NULL;
} }
/** /**
@ -1107,6 +1112,14 @@ static void at_core_free(void *ptr)
#if AT_WORK_CONTEXT_EN #if AT_WORK_CONTEXT_EN
/**
* @brief void * -> work_item_t *
*/
static inline work_item_t *work_item_map(void *work_obj)
{
return (work_item_t *)work_obj;
}
/** /**
* @brief Indicates whether the AT work is valid. * @brief Indicates whether the AT work is valid.
*/ */