mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-21 10:36:04 +08:00
[net][at] update AT component V1.3.0, change as follows:
- AT Socket feature supports multi-client connections; - Fix `send data error, current socket (0) state (0) is error` issue when the socket is closed; - Improve dirty data processing when AT device hard reset; - Improve `at_obj_set_urc_table()` fucntion, Support for setting multiple URC tables; - Improve RAW data print format;
This commit is contained in:
@@ -83,7 +83,7 @@ if RT_USING_AT
|
||||
|
||||
config AT_SW_VERSION_NUM
|
||||
hex
|
||||
default 0x10200
|
||||
default 0x10300
|
||||
help
|
||||
sfotware module version number
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,7 @@ extern "C" {
|
||||
enum at_socket_state
|
||||
{
|
||||
AT_SOCKET_NONE,
|
||||
AT_SOCKET_OPEN,
|
||||
AT_SOCKET_LISTEN,
|
||||
AT_SOCKET_CONNECT,
|
||||
AT_SOCKET_CLOSED
|
||||
@@ -54,18 +55,19 @@ typedef enum
|
||||
AT_SOCKET_EVT_CLOSED,
|
||||
} at_socket_evt_t;
|
||||
|
||||
typedef void (*at_evt_cb_t)(int socket, at_socket_evt_t event, const char *buff, size_t bfsz);
|
||||
|
||||
struct at_socket;
|
||||
|
||||
typedef void (*at_evt_cb_t)(struct at_socket *socket, at_socket_evt_t event, const char *buff, size_t bfsz);
|
||||
|
||||
/* A callback prototype to inform about events for AT socket */
|
||||
typedef void (* at_socket_callback)(struct at_socket *conn, int event, uint16_t len);
|
||||
|
||||
/* AT device socket options function */
|
||||
struct at_device_ops
|
||||
/* AT socket operations function */
|
||||
struct at_socket_ops
|
||||
{
|
||||
int (*at_connect)(int socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client);
|
||||
int (*at_closesocket)(int socket);
|
||||
int (*at_send)(int socket, const char *buff, size_t bfsz, enum at_socket_type type);
|
||||
int (*at_connect)(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client);
|
||||
int (*at_closesocket)(struct at_socket *socket);
|
||||
int (*at_send)(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type);
|
||||
int (*at_domain_resolve)(const char *name, char ip[16]);
|
||||
void (*at_set_event_cb)(at_socket_evt_t event, at_evt_cb_t cb);
|
||||
};
|
||||
@@ -86,10 +88,14 @@ struct at_socket
|
||||
uint32_t magic;
|
||||
|
||||
int socket;
|
||||
/* device releated information for the socket */
|
||||
void *device;
|
||||
/* type of the AT socket (TCP, UDP or RAW) */
|
||||
enum at_socket_type type;
|
||||
/* current state of the AT socket */
|
||||
enum at_socket_state state;
|
||||
/* sockets operations */
|
||||
const struct at_socket_ops *ops;
|
||||
/* receive semaphore, received data release semaphore */
|
||||
rt_sem_t recv_notice;
|
||||
rt_mutex_t recv_lock;
|
||||
@@ -111,6 +117,10 @@ struct at_socket
|
||||
#ifdef SAL_USING_POSIX
|
||||
rt_wqueue_t wait_head;
|
||||
#endif
|
||||
rt_slist_t list;
|
||||
|
||||
/* user-specific data */
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
int at_socket(int domain, int type, int protocol);
|
||||
@@ -129,7 +139,6 @@ int at_getaddrinfo(const char *nodename, const char *servname, const struct addr
|
||||
void at_freeaddrinfo(struct addrinfo *ai);
|
||||
|
||||
struct at_socket *at_get_socket(int socket);
|
||||
void at_socket_device_register(const struct at_device_ops *ops);
|
||||
|
||||
#ifndef RT_USING_SAL
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AT_SW_VERSION "1.2.0"
|
||||
#define AT_SW_VERSION "1.3.0"
|
||||
|
||||
#define AT_CMD_NAME_LEN 16
|
||||
#define AT_END_MARK_LEN 4
|
||||
@@ -124,9 +124,11 @@ struct at_response
|
||||
{
|
||||
/* response buffer */
|
||||
char *buf;
|
||||
/* the maximum response buffer size */
|
||||
/* the maximum response buffer size, it set by `at_create_resp()` function */
|
||||
rt_size_t buf_size;
|
||||
/* the number of setting response lines
|
||||
/* the length of current response buffer */
|
||||
rt_size_t buf_len;
|
||||
/* the number of setting response lines, it set by `at_create_resp()` function
|
||||
* == 0: the response data will auto return when received 'OK' or 'ERROR'
|
||||
* != 0: the response data will return when received setting lines number data */
|
||||
rt_size_t line_num;
|
||||
@@ -138,15 +140,24 @@ struct at_response
|
||||
|
||||
typedef struct at_response *at_response_t;
|
||||
|
||||
struct at_client;
|
||||
|
||||
/* URC(Unsolicited Result Code) object, such as: 'RING', 'READY' request by AT server */
|
||||
struct at_urc
|
||||
{
|
||||
const char *cmd_prefix;
|
||||
const char *cmd_suffix;
|
||||
void (*func)(const char *data, rt_size_t size);
|
||||
void (*func)(struct at_client *client, const char *data, rt_size_t size);
|
||||
};
|
||||
typedef struct at_urc *at_urc_t;
|
||||
|
||||
struct at_urc_table
|
||||
{
|
||||
size_t urc_size;
|
||||
const struct at_urc *urc;
|
||||
};
|
||||
typedef struct at_urc *at_urc_table_t;
|
||||
|
||||
struct at_client
|
||||
{
|
||||
rt_device_t device;
|
||||
@@ -154,9 +165,12 @@ struct at_client
|
||||
at_status_t status;
|
||||
char end_sign;
|
||||
|
||||
char *recv_buffer;
|
||||
/* the current received one line data buffer */
|
||||
char *recv_line_buf;
|
||||
/* The length of the currently received one line data */
|
||||
rt_size_t recv_line_len;
|
||||
/* The maximum supported receive data length */
|
||||
rt_size_t recv_bufsz;
|
||||
rt_size_t cur_recv_len;
|
||||
rt_sem_t rx_notice;
|
||||
rt_mutex_t lock;
|
||||
|
||||
@@ -164,7 +178,7 @@ struct at_client
|
||||
rt_sem_t resp_notice;
|
||||
at_resp_status_t resp_status;
|
||||
|
||||
const struct at_urc *urc_table;
|
||||
struct at_urc_table *urc_table;
|
||||
rt_size_t urc_table_size;
|
||||
|
||||
rt_thread_t parser;
|
||||
@@ -207,7 +221,7 @@ rt_size_t at_client_obj_recv(at_client_t client, char *buf, rt_size_t size, rt_i
|
||||
void at_obj_set_end_sign(at_client_t client, char ch);
|
||||
|
||||
/* Set URC(Unsolicited Result Code) table */
|
||||
void at_obj_set_urc_table(at_client_t client, const struct at_urc * table, rt_size_t size);
|
||||
int at_obj_set_urc_table(at_client_t client, const struct at_urc * table, rt_size_t size);
|
||||
|
||||
/* AT client send commands to AT server and waiter response */
|
||||
int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr, ...);
|
||||
|
||||
@@ -301,13 +301,18 @@ int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr
|
||||
client->resp_status = AT_RESP_OK;
|
||||
client->resp = resp;
|
||||
|
||||
if (resp != RT_NULL)
|
||||
{
|
||||
resp->buf_len = 0;
|
||||
resp->line_counts = 0;
|
||||
}
|
||||
|
||||
va_start(args, cmd_expr);
|
||||
at_vprintfln(client->device, cmd_expr, args);
|
||||
va_end(args);
|
||||
|
||||
if (resp != RT_NULL)
|
||||
{
|
||||
resp->line_counts = 0;
|
||||
if (rt_sem_take(client->resp_notice, resp->timeout) != RT_EOK)
|
||||
{
|
||||
cmd = at_get_last_cmd(&cmd_size);
|
||||
@@ -348,17 +353,18 @@ int at_client_obj_wait_connect(at_client_t client, rt_uint32_t timeout)
|
||||
rt_err_t result = RT_EOK;
|
||||
at_response_t resp = RT_NULL;
|
||||
rt_tick_t start_time = 0;
|
||||
char *client_name = client->device->parent.name;
|
||||
|
||||
if (client == RT_NULL)
|
||||
{
|
||||
LOG_E("input AT Client object is NULL, please create or get AT Client object!");
|
||||
LOG_E("input AT client object is NULL, please create or get AT Client object!");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
resp = at_create_resp(16, 0, rt_tick_from_millisecond(500));
|
||||
resp = at_create_resp(64, 0, rt_tick_from_millisecond(300));
|
||||
if (resp == RT_NULL)
|
||||
{
|
||||
LOG_E("No memory for response object!");
|
||||
LOG_E("no memory for AT client(%s) response object.", client_name);
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
@@ -372,12 +378,13 @@ int at_client_obj_wait_connect(at_client_t client, rt_uint32_t timeout)
|
||||
/* Check whether it is timeout */
|
||||
if (rt_tick_get() - start_time > rt_tick_from_millisecond(timeout))
|
||||
{
|
||||
LOG_E("wait connect timeout (%d millisecond)!", timeout);
|
||||
LOG_E("wait AT client(%s) connect timeout(%d tick).", client_name, timeout);
|
||||
result = -RT_ETIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check whether it is already connected */
|
||||
resp->buf_len = 0;
|
||||
resp->line_counts = 0;
|
||||
rt_device_write(client->device, 0, "AT\r\n", 4);
|
||||
|
||||
@@ -417,7 +424,7 @@ rt_size_t at_client_obj_send(at_client_t client, const char *buf, rt_size_t size
|
||||
}
|
||||
|
||||
#ifdef AT_PRINT_RAW_CMD
|
||||
at_print_raw_cmd("send", buf, size);
|
||||
at_print_raw_cmd("sendline", buf, size);
|
||||
#endif
|
||||
|
||||
return rt_device_write(client->device, 0, buf, size);
|
||||
@@ -518,14 +525,14 @@ void at_obj_set_end_sign(at_client_t client, char ch)
|
||||
* @param table URC table
|
||||
* @param size table size
|
||||
*/
|
||||
void at_obj_set_urc_table(at_client_t client, const struct at_urc *urc_table, rt_size_t table_sz)
|
||||
int at_obj_set_urc_table(at_client_t client, const struct at_urc *urc_table, rt_size_t table_sz)
|
||||
{
|
||||
rt_size_t idx;
|
||||
|
||||
if (client == RT_NULL)
|
||||
{
|
||||
LOG_E("input AT Client object is NULL, please create or get AT Client object!");
|
||||
return;
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < table_sz; idx++)
|
||||
@@ -534,8 +541,47 @@ void at_obj_set_urc_table(at_client_t client, const struct at_urc *urc_table, rt
|
||||
RT_ASSERT(urc_table[idx].cmd_suffix);
|
||||
}
|
||||
|
||||
client->urc_table = urc_table;
|
||||
client->urc_table_size = table_sz;
|
||||
if (client->urc_table_size == 0)
|
||||
{
|
||||
client->urc_table = (struct at_urc_table *) rt_calloc(1, sizeof(struct at_urc_table));
|
||||
if (client->urc_table == RT_NULL)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
client->urc_table[0].urc = urc_table;
|
||||
client->urc_table[0].urc_size = table_sz;
|
||||
client->urc_table_size++;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct at_urc_table *old_urc_table = RT_NULL;
|
||||
size_t old_table_size = client->urc_table_size * sizeof(struct at_urc_table);
|
||||
|
||||
old_urc_table = (struct at_urc_table *) rt_malloc(old_table_size);
|
||||
if (old_urc_table == RT_NULL)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
rt_memcpy(old_urc_table, client->urc_table, old_table_size);
|
||||
|
||||
/* realloc urc table space */
|
||||
client->urc_table = (struct at_urc_table *) rt_realloc(client->urc_table,
|
||||
old_table_size + sizeof(struct at_urc_table));
|
||||
if (client->urc_table == RT_NULL)
|
||||
{
|
||||
rt_free(old_urc_table);
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
rt_memcpy(client->urc_table, old_urc_table, old_table_size);
|
||||
client->urc_table[client->urc_table_size].urc = urc_table;
|
||||
client->urc_table[client->urc_table_size].urc_size = table_sz;
|
||||
client->urc_table_size++;
|
||||
|
||||
rt_free(old_urc_table);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -579,30 +625,38 @@ at_client_t at_client_get_first(void)
|
||||
|
||||
static const struct at_urc *get_urc_obj(at_client_t client)
|
||||
{
|
||||
rt_size_t i, prefix_len, suffix_len;
|
||||
rt_size_t buf_sz;
|
||||
rt_size_t i, j, prefix_len, suffix_len;
|
||||
rt_size_t bufsz;
|
||||
char *buffer = RT_NULL;
|
||||
const struct at_urc *urc = RT_NULL;
|
||||
struct at_urc_table *urc_table = RT_NULL;
|
||||
|
||||
if (client->urc_table == RT_NULL)
|
||||
{
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
buffer = client->recv_buffer;
|
||||
buf_sz = client->cur_recv_len;
|
||||
buffer = client->recv_line_buf;
|
||||
bufsz = client->recv_line_len;
|
||||
|
||||
for (i = 0; i < client->urc_table_size; i++)
|
||||
{
|
||||
prefix_len = strlen(client->urc_table[i].cmd_prefix);
|
||||
suffix_len = strlen(client->urc_table[i].cmd_suffix);
|
||||
if (buf_sz < prefix_len + suffix_len)
|
||||
for (j = 0; j < client->urc_table[i].urc_size; j++)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((prefix_len ? !strncmp(buffer, client->urc_table[i].cmd_prefix, prefix_len) : 1)
|
||||
&& (suffix_len ? !strncmp(buffer + buf_sz - suffix_len, client->urc_table[i].cmd_suffix, suffix_len) : 1))
|
||||
{
|
||||
return &client->urc_table[i];
|
||||
urc_table = client->urc_table + i;
|
||||
urc = urc_table->urc + j;
|
||||
|
||||
prefix_len = rt_strlen(urc->cmd_prefix);
|
||||
suffix_len = rt_strlen(urc->cmd_suffix);
|
||||
if (bufsz < prefix_len + suffix_len)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((prefix_len ? !rt_strncmp(buffer, urc->cmd_prefix, prefix_len) : 1)
|
||||
&& (suffix_len ? !rt_strncmp(buffer + bufsz - suffix_len, urc->cmd_suffix, suffix_len) : 1))
|
||||
{
|
||||
return urc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,8 +669,8 @@ static int at_recv_readline(at_client_t client)
|
||||
char ch = 0, last_ch = 0;
|
||||
rt_bool_t is_full = RT_FALSE;
|
||||
|
||||
memset(client->recv_buffer, 0x00, client->recv_bufsz);
|
||||
client->cur_recv_len = 0;
|
||||
rt_memset(client->recv_line_buf, 0x00, client->recv_bufsz);
|
||||
client->recv_line_len = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -624,8 +678,8 @@ static int at_recv_readline(at_client_t client)
|
||||
|
||||
if (read_len < client->recv_bufsz)
|
||||
{
|
||||
client->recv_buffer[read_len++] = ch;
|
||||
client->cur_recv_len = read_len;
|
||||
client->recv_line_buf[read_len++] = ch;
|
||||
client->recv_line_len = read_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -639,8 +693,8 @@ static int at_recv_readline(at_client_t client)
|
||||
if (is_full)
|
||||
{
|
||||
LOG_E("read line failed. The line data length is out of buffer size(%d)!", client->recv_bufsz);
|
||||
memset(client->recv_buffer, 0x00, client->recv_bufsz);
|
||||
client->cur_recv_len = 0;
|
||||
rt_memset(client->recv_line_buf, 0x00, client->recv_bufsz);
|
||||
client->recv_line_len = 0;
|
||||
return -RT_EFULL;
|
||||
}
|
||||
break;
|
||||
@@ -649,7 +703,7 @@ static int at_recv_readline(at_client_t client)
|
||||
}
|
||||
|
||||
#ifdef AT_PRINT_RAW_CMD
|
||||
at_print_raw_cmd("recvline", client->recv_buffer, read_len);
|
||||
at_print_raw_cmd("recvline", client->recv_line_buf, read_len);
|
||||
#endif
|
||||
|
||||
return read_len;
|
||||
@@ -657,9 +711,7 @@ static int at_recv_readline(at_client_t client)
|
||||
|
||||
static void client_parser(at_client_t client)
|
||||
{
|
||||
int resp_buf_len = 0;
|
||||
const struct at_urc *urc;
|
||||
rt_size_t line_counts = 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
@@ -670,39 +722,42 @@ static void client_parser(at_client_t client)
|
||||
/* current receive is request, try to execute related operations */
|
||||
if (urc->func != RT_NULL)
|
||||
{
|
||||
urc->func(client->recv_buffer, client->cur_recv_len);
|
||||
urc->func(client, client->recv_line_buf, client->recv_line_len);
|
||||
}
|
||||
}
|
||||
else if (client->resp != RT_NULL)
|
||||
{
|
||||
at_response_t resp = client->resp;
|
||||
|
||||
/* current receive is response */
|
||||
client->recv_buffer[client->cur_recv_len - 1] = '\0';
|
||||
if (resp_buf_len + client->cur_recv_len < client->resp->buf_size)
|
||||
client->recv_line_buf[client->recv_line_len - 1] = '\0';
|
||||
if (resp->buf_len + client->recv_line_len < resp->buf_size)
|
||||
{
|
||||
/* copy response lines, separated by '\0' */
|
||||
memcpy(client->resp->buf + resp_buf_len, client->recv_buffer, client->cur_recv_len);
|
||||
resp_buf_len += client->cur_recv_len;
|
||||
rt_memcpy(resp->buf + resp->buf_len, client->recv_line_buf, client->recv_line_len);
|
||||
|
||||
line_counts++;
|
||||
/* update the current response information */
|
||||
resp->buf_len += client->recv_line_len;
|
||||
resp->line_counts++;
|
||||
}
|
||||
else
|
||||
{
|
||||
client->resp_status = AT_RESP_BUFF_FULL;
|
||||
LOG_E("Read response buffer failed. The Response buffer size is out of buffer size(%d)!", client->resp->buf_size);
|
||||
LOG_E("Read response buffer failed. The Response buffer size is out of buffer size(%d)!", resp->buf_size);
|
||||
}
|
||||
/* check response result */
|
||||
if (memcmp(client->recv_buffer, AT_RESP_END_OK, strlen(AT_RESP_END_OK)) == 0
|
||||
&& client->resp->line_num == 0)
|
||||
if (rt_memcmp(client->recv_line_buf, AT_RESP_END_OK, rt_strlen(AT_RESP_END_OK)) == 0
|
||||
&& resp->line_num == 0)
|
||||
{
|
||||
/* get the end data by response result, return response state END_OK. */
|
||||
client->resp_status = AT_RESP_OK;
|
||||
}
|
||||
else if (strstr(client->recv_buffer, AT_RESP_END_ERROR)
|
||||
|| (memcmp(client->recv_buffer, AT_RESP_END_FAIL, strlen(AT_RESP_END_FAIL)) == 0))
|
||||
else if (rt_strstr(client->recv_line_buf, AT_RESP_END_ERROR)
|
||||
|| (rt_memcmp(client->recv_line_buf, AT_RESP_END_FAIL, rt_strlen(AT_RESP_END_FAIL)) == 0))
|
||||
{
|
||||
client->resp_status = AT_RESP_ERROR;
|
||||
}
|
||||
else if (line_counts == client->resp->line_num && client->resp->line_num)
|
||||
else if (resp->line_counts == resp->line_num && resp->line_num)
|
||||
{
|
||||
/* get the end data by response line, return response state END_OK.*/
|
||||
client->resp_status = AT_RESP_OK;
|
||||
@@ -711,15 +766,13 @@ static void client_parser(at_client_t client)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
client->resp->line_counts = line_counts;
|
||||
|
||||
client->resp = RT_NULL;
|
||||
rt_sem_release(client->resp_notice);
|
||||
resp_buf_len = 0, line_counts = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// log_d("unrecognized line: %.*s", client->cur_recv_len, client->recv_buffer);
|
||||
// log_d("unrecognized line: %.*s", client->recv_line_len, client->recv_line_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -754,9 +807,9 @@ static int at_client_para_init(at_client_t client)
|
||||
|
||||
client->status = AT_STATUS_UNINITIALIZED;
|
||||
|
||||
client->cur_recv_len = 0;
|
||||
client->recv_buffer = (char *) rt_calloc(1, client->recv_bufsz);
|
||||
if (client->recv_buffer == RT_NULL)
|
||||
client->recv_line_len = 0;
|
||||
client->recv_line_buf = (char *) rt_calloc(1, client->recv_bufsz);
|
||||
if (client->recv_line_buf == RT_NULL)
|
||||
{
|
||||
LOG_E("AT client initialize failed! No memory for receive buffer.");
|
||||
result = -RT_ENOMEM;
|
||||
@@ -829,9 +882,9 @@ __exit:
|
||||
rt_device_close(client->device);
|
||||
}
|
||||
|
||||
if (client->recv_buffer)
|
||||
if (client->recv_line_buf)
|
||||
{
|
||||
rt_free(client->recv_buffer);
|
||||
rt_free(client->recv_line_buf);
|
||||
}
|
||||
|
||||
rt_memset(client, 0x00, sizeof(struct at_client));
|
||||
|
||||
@@ -70,7 +70,7 @@ rt_size_t at_vprintf(rt_device_t device, const char *format, va_list args)
|
||||
last_cmd_len = vsnprintf(send_buf, sizeof(send_buf), format, args);
|
||||
|
||||
#ifdef AT_PRINT_RAW_CMD
|
||||
at_print_raw_cmd("send", send_buf, last_cmd_len);
|
||||
at_print_raw_cmd("sendline", send_buf, last_cmd_len);
|
||||
#endif
|
||||
|
||||
return rt_device_write(device, 0, send_buf, last_cmd_len);
|
||||
|
||||
Reference in New Issue
Block a user