c - 从完整的响应字符串中解析 AT 命令的有效负载
问题描述
我想从 AT 命令的输出中解析实际的有效载荷。
例如:在下面的示例中,我只想阅读"2021/11/16,11:12:14-32,0"
AT+QLTS=1 // command
+QLTS: "2021/11/16,11:12:14-32,0" // response
OK
在以下情况下,我只需要阅读12345678
.
AT+CIMI // command
12345678 // example response
所以重点是:并非所有命令的输出格式都相同。我们可以假设响应存储在一个字符串数组中。
我GetAtCmdRsp()
已经实现了将响应存储在 char 数组中。
void GetPayload()
{
char rsp[100] = {0};
GetAtCmdRsp("AT+QLTS=1", rsp);
// rsp now contains +QLTS: "2021/11/16,11:12:14-32,0"
// now, I need to parse "2021/11/16,11:12:14-32,0" out of the response
memset(rsp, 0, sizeof(rsp));
GetAtCmdRsp("AT+CIMI", rsp);
// rsp now contains 12345678
// no need to do additional parsing since the output already contains the value I need
}
我正在考虑如何char *start = strstr(rsp, ":") + 1;
启动有效负载,但某些响应可能只包含有效负载,因为情况就是这样AT+CIMI
也许正则表达式是确定+<COMMAND>:
字符串中模式的好主意?
解决方案
为了解析 AT 命令响应,一个好的起点是了解它们可以具有的所有可能格式。因此,我不会通过“响应类型”
来区分命令,而不是实现特定于命令的例程:
例如,答案中没有有效负载的命令
AT OK
答案中没有标题的命令,例如
AT+CIMI 12345678 OK
答案中只有一个标题的命令
AT+QLTS=1 +QLTS: "2021/11/16,11:12:14-32,0" OK
具有多行响应的命令。
每行都可以是“单标题”类型,例如+CGDCONT
:AT+CDGCONT? +CGDCONT: 1,"IP","epc.tmobile.com","0.0.0.0",0,0 +CGDCONT: 2,"IP","isp.cingular","0.0.0.0",0,0 +CGDCONT: 3,"IP","","0.0.0.0",0,0 OK
或者我们甚至可以有混合类型,例如
+CGML
:AT+CMGL="ALL" +CMGL: 1,"REC READ","+XXXXXXXXXX","","21/11/25,10:20:00+00" Good morning! How are you? +CMGL: 2,"REC READ","+XXXXXXXXXX","","21/11/25,10:33:33+00" I'll come a little late. See you. Bruce Wayne OK
(请注意它如何也有“空”行,即
\r\n
)。
目前我无法考虑任何其他情况。
通过这种方式,您将能够定义一个枚举,例如
typedef enum
{
AT_RESPONSE_TYPE_NO_RESPONSE,
AT_RESPONSE_TYPE_NO_HEADER,
AT_RESPONSE_TYPE_SINGLE_HEADER,
AT_RESPONSE_TYPE_MULTILINE,
AT_RESPONSE_TYPE_MAX
}
并将其传递给您的GetAtCmdRsp( )
函数,以便相应地解析响应。如果在该函数中实现微分,或者在它之后(或在外部函数中是你的选择。
没有明确分类的解决方案
一旦你清楚了所有可能发生的场景,你就可以考虑一个适用于所有场景的通用算法:
resp
在命令 echo 之后和关闭OK
or之前获取完整响应ERROR
。确保\r\n\r\nOK
删除尾随(或\r\nERROR
. 或\r\nNO CARRIER
. 或响应的终止消息可能是什么)。
还要确保删除命令 echo如果
strlen( resp ) == 0
我们属于该NO_RESPONSE
类别,并且工作完成如果响应中包含
\r\n
s,我们就有了MULTILINE
答案。因此,对其进行标记并将每一行放入一个数组元素resp_arr[i]
中。确保删除尾随\r\n
对于响应中的每一行(对于每个
resp_arr[i]
元素),搜索<CMD> :
模式(不仅:
,它也可能包含在有效负载中!)。像这样的东西:size_t len = strlen( resp_cur_line ); char *payload; if( strstr( "+YOURCMD: ", resp_cur_line) == NULL ) { // We are in "NO_HEADER" case payload = resp_cur_line; } else { // We are in "HEADER" case payload = resp_cur_line + strlen( "+YOURCMD: " ); }
现在
payload
指针指向实际的有效载荷。请注意,在
MULTILINE
回答的情况下,在将行拆分为数组元素后,每个循环将如何正确处理混合场景,例如 in 中的场景+CMGL
,因为您将能够区分包含标题的行和包含数据的行(以及当然是空行)。有关+CMGL
响应解析的更深入分析,请查看此答案。
推荐阅读
- css - 如何调整/恢复 WooCommerce 中的单个产品页面?
- c - 每 5 秒停止一次 SSL 连接失败
- dart - 如何将卡片放入 sliver 应用栏
- angular - 服务工作者在 chrome 中无法在离线模式下工作
- javascript - 如何在 Netlify Serverless 功能中设置 CORS
- html - 带有嵌套 td 的 HTML 表格
- javascript - 有没有办法为 Javascript / Typescript 模块自动声明外部导出?
- java - 硒 getWindowHandles() 处理?
- php - 使用 PHP 显示 docx 文件的内容
- grails - Grails 动态休息端点映射