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 -->
* [介绍](readme#简介)
* [介绍](README#简介)
* [快速上手](quickStart#基础应用)
* [高级教程](Expert#高级教程)
* [平台移植](Porting#平台移植)

View File

@ -8,11 +8,16 @@
* Change Logs:
* Date Author Notes
* 2020-01-02 roger.luo Initial version
* 2021-01-20 roger.luo Add debugging interface, and at the same time solve
* the problem of uninitialized linked list 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-01-20 roger.luo Add debugging interface, and at the same time
* solve the problem of uninitialized linked list
* leading to segment fault.
* 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.
* 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_
#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_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);

View File

@ -8,11 +8,16 @@
* Change Logs:
* Date Author Notes
* 2020-01-02 roger.luo Initial version
* 2021-01-20 roger.luo Add debugging interface, and at the same time solve
* the problem of uninitialized linked list 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-01-20 roger.luo Add debugging interface, and at the same time
* solve the problem of uninitialized linked list
* leading to segment fault.
* 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.
* 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_port.h"
@ -155,13 +160,7 @@ static inline at_info_t *obj_map(at_obj_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)
{
@ -196,7 +195,7 @@ static void send_cmdline(at_info_t *at, const char *cmd)
len = strlen(cmd);
__get_adapter(at)->write(cmd, len);
__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)
{
at_context_t *ctx = wi->attr.ctx;
wi->state = state;
wi->code = code;
#if AT_WORK_CONTEXT_EN
at_context_t *ctx = wi->attr.ctx;
if (ctx != NULL) {
ctx->code = (at_resp_code)wi->code;
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)
{
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
if ((code == AT_RESP_ERROR || code == AT_RESP_TIMEOUT) && __get_adapter(ai)->error != NULL) {
__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;
}
#if AT_WORK_CONTEXT_EN
ctx = wi->attr.ctx;
at_context_t *ctx = wi->attr.ctx;
if (ctx != NULL ) {
if (ctx->respbuf != NULL/* && ctx->bufsize */) {
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->type = type;
it->state = AT_WORK_STAT_READY;
#if AT_WORK_CONTEXT_EN
if (attr->ctx) {
attr->ctx->code = AT_RESP_OK;
attr->ctx->work_state = AT_WORK_STAT_READY;
}
#endif
return it;
}
@ -518,7 +518,7 @@ static int do_cmd_handler(at_info_t *ai)
do_at_callback(ai, wi, AT_RESP_ERROR);
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->reset_timer(env);
}
@ -558,7 +558,7 @@ static int send_multiline_handler(at_info_t *ai)
{
case AT_STAT_SEND:
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;
}
send_cmdline(ai, cmds[env->i]);
@ -572,23 +572,27 @@ static int send_multiline_handler(at_info_t *ai)
env->state = 0;
env->i++;
env->j = 0;
env->params = (void *)true; /*Mark execution status*/
AT_DEBUG(ai, "<-\r\n%s\r\n", ai->recvbuf);
} else if (find_substr(env, AT_DEF_RESP_ERR)) {
AT_DEBUG(ai, "<-\r\n%s\r\n", ai->recvbuf);
if (env->j++ >= attr->retry) {
do_at_callback(ai, wi, AT_RESP_ERROR);
return true;
env->j++;
AT_DEBUG(ai, "CMD:'%s' failed to executed, retry:%d\r\n", cmds[env->i], env->j);
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)) {
do_at_callback(ai, wi, AT_RESP_TIMEOUT);
return true;
}
break;
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.*/
break;
default:
@ -663,11 +667,13 @@ static void urc_handler_entry(at_info_t *ai, urc_recv_status status, char *urc,
{
int remain;
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. */
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);
} else {
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;
urc_buf[ai->urc_cnt] = '\0';
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)) == NULL) {
ai->urc_item = find_urc_item(ai, urc_buf, ai->urc_cnt);
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);
continue;
}
}
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.
* @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;
attr.cb = cb;
attr.timeout = timeout;
attr.retry = retry;
return add_work_item(obj_map(at), WORK_TYPE_SINGLLINE, &attr, singlline, 0) != NULL;
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
/**
* @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.
*/