feat(AT): LINK 对外接口改为 S1/S2/C1/C2

- LINK 首参数由数字索引改为角色名(S1/S2/C1/C2),内部映射对用户隐藏

- LINK 查询与摘要回包统一输出角色名

- LINK 配置成功后返回当前记录,格式与查询一致

- 同步更新 AT 使用手册中的命令示例与字段说明
This commit is contained in:
2026-04-04 15:44:18 +08:00
parent d5b2506269
commit c5b2bdd2d2
2 changed files with 82 additions and 39 deletions
+57 -12
View File
@@ -158,6 +158,48 @@ static const char *link_uart_to_str(uint8_t uart)
return (uart == LINK_UART_U1) ? "U1" : "U0";
}
static const char *link_index_to_name(uint32_t index)
{
switch (index) {
case CONFIG_LINK_S1:
return "S1";
case CONFIG_LINK_S2:
return "S2";
case CONFIG_LINK_C1:
return "C1";
case CONFIG_LINK_C2:
return "C2";
default:
return "?";
}
}
static int parse_link_name(const char *value, uint32_t *index)
{
if (value == NULL || index == NULL) {
return -1;
}
if (equals_ignore_case(value, "S1")) {
*index = CONFIG_LINK_S1;
return 0;
}
if (equals_ignore_case(value, "S2")) {
*index = CONFIG_LINK_S2;
return 0;
}
if (equals_ignore_case(value, "C1")) {
*index = CONFIG_LINK_C1;
return 0;
}
if (equals_ignore_case(value, "C2")) {
*index = CONFIG_LINK_C2;
return 0;
}
return -1;
}
static bool parse_command_with_value(const char *cmd, const char *name, const char **value)
{
size_t name_len;
@@ -309,10 +351,10 @@ static at_result_t handle_summary_query(char *response, uint16_t max_len)
snprintf(response, max_len,
"+NET:IP=%s,MASK=%s,GW=%s,MAC=%s\r\n"
"+LINK:0,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:1,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:2,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:3,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:S1,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:S2,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:C1,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:C2,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+MUX:%u\r\n"
"+MAP:UART2=0x04,UART3=0x08,C1=0x01,C2=0x02,S1=0x10,S2=0x20\r\n"
"+BAUD:U0=%lu,U1=%lu\r\n"
@@ -356,8 +398,8 @@ static at_result_t handle_link_query(uint32_t index, char *response, uint16_t ma
config_ip_to_str(g_config.links[index].remote_ip, rip_str);
snprintf(response,
max_len,
"+LINK:%lu,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\nOK\r\n",
index,
"+LINK:%s,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\nOK\r\n",
link_index_to_name(index),
g_config.links[index].enabled,
g_config.links[index].local_port,
rip_str,
@@ -376,10 +418,10 @@ static at_result_t handle_all_link_query(char *response, uint16_t max_len)
snprintf(response,
max_len,
"+LINK:0,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:1,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:2,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:3,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:S1,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:S2,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:C1,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"+LINK:C2,EN=%u,LPORT=%u,RIP=%s,RPORT=%u,UART=%s\r\n"
"OK\r\n",
g_config.links[0].enabled, g_config.links[0].local_port, rip_str[0], g_config.links[0].remote_port, link_uart_to_str(g_config.links[0].uart),
g_config.links[1].enabled, g_config.links[1].local_port, rip_str[1], g_config.links[1].remote_port, link_uart_to_str(g_config.links[1].uart),
@@ -581,7 +623,7 @@ at_result_t config_process_at_cmd(const char *cmd, char *response, uint16_t max_
cursor = value_copy;
token = config_next_token(&cursor);
if (token == NULL || parse_u32_value(token, 0u, CONFIG_LINK_COUNT - 1u, &index) != 0) {
if (token == NULL || parse_link_name(token, &index) != 0) {
snprintf(response, max_len, "ERROR: Invalid route field\r\n");
return AT_INVALID_PARAM;
}
@@ -623,7 +665,10 @@ at_result_t config_process_at_cmd(const char *cmd, char *response, uint16_t max_
memcpy(g_config.links[index].remote_ip, rip, sizeof(rip));
g_config.links[index].remote_port = (uint16_t)remote_port;
g_config.links[index].uart = uart;
snprintf(response, max_len, "OK\r\n");
if (handle_link_query(index, response, max_len) != AT_OK) {
snprintf(response, max_len, "ERROR: Invalid route field\r\n");
return AT_INVALID_PARAM;
}
return AT_NEED_REBOOT;
}