mirror of
https://gitee.com/moluo-tech/AT-Command
synced 2025-06-17 16:07:52 +00:00
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:
parent
8866cdf7f9
commit
a1cf6f2672
@ -1,6 +1,6 @@
|
|||||||
<!-- navbar.md -->
|
<!-- navbar.md -->
|
||||||
|
|
||||||
* [介绍](readme#简介)
|
* [介绍](README#简介)
|
||||||
* [快速上手](quickStart#基础应用)
|
* [快速上手](quickStart#基础应用)
|
||||||
* [高级教程](Expert#高级教程)
|
* [高级教程](Expert#高级教程)
|
||||||
* [平台移植](Porting#平台移植)
|
* [平台移植](Porting#平台移植)
|
@ -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);
|
||||||
|
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user