【ESP32】利用 sscanf() 字符串参数 %n 解析AT+CNUM指令

2023-05-16

    这两天在调试即将完成的Hands Free Profile的AG部分代码,在调试与HF Client设备收发AT指令部分时遇到了AT+CNUM指令HF Client端 “解析AT指令错误”的提示。由于HFP中,AT指令参数都是存放在字符串中进行收发的,字符串的解析就至关重要,而在解掉bug的同时,我也在不断地学习。本文便介绍一个在HF Client端利用sscanf()按格式读取字符串时的一个小技巧%n。
    首先,我们来看一眼HFP 1.7.1协议关于CNUM指令的介绍。

HFP CNUM
 

    其中字符串的格式如图所示," [,,<service>] " 为option选项。在我的AG模块中并不选择发送service,所以从AG发送到HF Client端的字符内容应该为 "\r\n +CNUM: ,<number>,<type>\r\n"。 AG和HF Client的字符串解析代码如下:

/* AG 端字符串内容*/

if (is_connected(bd_addr) && (idx != BTC_HF_INVALID_IDX)) {
    tBTA_AG_RES_DATA    ag_res;
    memset(&ag_res, 0, sizeof (ag_res));
    BTC_TRACE_EVENT("cnum_response: number = %s, type = %d", number, type);
    if (number) {
        sprintf(ag_res.str, ",\"%s\",%d",number, type);
    } else {
        sprintf(ag_res.str, ",\"\",%d",type);
    }
    ag_res.ok_flag = BTA_AG_OK_DONE;
    BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_CNUM_RES, &ag_res);

    这里顺便解释一下,%32[^\"]的意思是:忽略掉所有的 “ 字符并最多读取32字节的数据。 

/* HF Client端字符串解析*/
AT_CHECK_EVENT(buffer, "+CNUM:");

res = sscanf(buffer, ",\"%32[^\"]\",%hu,,%hu%n", numstr, &type, &service, &offset);
if (res < 0) {
    return NULL;
}

if (res == 0) {
    res = sscanf(buffer, ",\"\",%hu,,%hu%n", &type, &service, &offset);
    if (res < 0) {
        return NULL;
    }

    /* numstr is not matched in second attempt, correct this */
    res++;
    numstr[0] = '\0';
}

if (res < 2) {
    return NULL;
}

buffer += offset;
printf("buffer :%s, offset %d\n",buffer,offset);
AT_CHECK_RN(buffer);

当使用上述代码进行测试时,HF Client端的错误信息如图:



 

    上图打印中,buffer内为HF Client端已经去除掉 “+CNUM: ”部分剩余的打印,可以看出并不符合协议要求的CNUM指令字符串,故出现报错。经过分析,原因处在offset的数值上。offset是HF Client端在解析字符串时进行赋值的,而HF Client端代码的offset仅仅出现在了option选项(service)的后面,这就导致在并不发送service的情况下offset是一个随机值,此处为2,也就是说,HF Client方面并不认为service是一个option选项,这与协议相违背。故,应该予以修改。
 

/* 原 HF Client 代码*/
res = sscanf(buffer, ",\"%32[^\"]\",%hu,,%hu%n", numstr, &type, &service, &offset);
/* 修改后 HF Client 代码*/
res = sscanf(buffer, ",\"%32[^\"]\",%hu%n,,%hu%n", numstr, &type, &offset, &service, &offset);

    从上端代码可以看出,我在type对应的%hu后面加上了一个%n来更新offset的值,并且保持了service对应%hu后面%n和offset不便,这样就可以利用一句代码适配协议中service选项的option要求。由于sscanf()在读取数据时遵循从左至右的方向性进行,所以只需要在type后对offset进行更新(更新后为16),便可以正确地进行解析。修改后效果如下:

=====================THE END=========================

如果觉得有用,请点赞、收藏、关注、或转发给你觉得有用的人。
本帐号会不定期记录与ESP-IDF调试小技巧,或者其他功能模块介绍。

LOVE AND SHARE.  PEACE.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【ESP32】利用 sscanf() 字符串参数 %n 解析AT+CNUM指令 的相关文章

  • [INFOCOM 2019] NeuralWalk:使用神经网络的在线社交网络中的信任评估

    NeuralWalk Trust Assessment in Online Social Networks with Neural Networks IEEE Conference Publication IEEE Xplore 摘要 xf
  • [CDC 2018] 理解压缩对抗隐私

    Understanding Compressive Adversarial Privacy IEEE Conference Publication IEEE Xplore 摘要 本文提出了一种新的隐私保护方法 xff0c 称为 压缩对抗隐私
  • 弱实体集

    弱实体 weak entity 1 定义 xff1a 有些实体集的所有属性都不足以形成主码 xff0c 这样的实体集称为弱实体集 与此相对 xff0c 其属性可以形成主码的实体集称为强实体集 通俗的说 xff1a 有些实体集的所有属性都不足
  • 理解“生成高斯随机测量矩阵”段代码;奇异值分解(SVD)的理解

    生成高斯随机测量矩阵 sampleRate 61 0 7 采样率 Phi 61 np random randn 256 256 u s vh 61 np linalg svd Phi Phi 61 u 256 sampleRate 将测量矩
  • 云服务器cvm & 云服务器ecs区别

    1 全称 cvm的英文全拼是 Cloud Virtual Machine xff08 云虚拟机 xff09 ecs的英文全拼是 Elastic Compute Service xff08 弹性计算服务 xff09 2 对比 云服务器cvm是
  • 远程连接腾讯云上的数据库

    一 准备工作 1 云服务器配置为windows server 2012 r2 2 远程连接云主机 下载rdp xff0c 输入win账号密码运行即可 2 在云主机上安装mysql xff08 1 xff09 下载mysql安装包 xff0c
  • 基于ubuntu18.04 VNC开机自启动

    本博客内容实现了RK3399 NanoPi NEO4的VNC的开机自启动 xff0c 以及原版桌面的显示 系统 xff1a FriendlyDesktop 最新版本 xff0d 基于Ubuntu 18 04 64位系统构建 易于开发 xff
  • Latex部分斜体变直体

    Latex斜体变为直体 rm即可 未使用之前的效果 xff08 x n 43 1 61 mathop arg min limits x alpha x D n xff09 为了将所有的小写x变为直体 xff0c 将所有的x替换为 rm x
  • Latex打花体

    Latex提供了三种花体 xff0c 注意使用时候提前导入包 xff0c 否则会报错 usepackage amsthm amsmath amssymb usepackage mathrsfs 使用的时候直接掉包即可 下面演示部分效果 xf
  • 遗传算法代码

    全局搜索最优算法 xff08 1 xff09 遗传算法 这里以github上的遗传算法开源库为例子 xff1a 首先我们安装GA xff08 官方说依赖库好像只支持Python 3 xff0c 但是我好像python2也安装成功了 xff0
  • ubuntu安装KVM

    ubuntu安装KVM 现在官网下载ubuntu镜像 xff0c 桌面版或者服务端都可 xff0c 这里以桌面端为例 安装之前确保磁盘有足够大的空间 xff08 这很重要 xff09 安装KVM span class token funct
  • Error: GPG check FAILED

    Error GPG check FAILED 这由于源key错误导致的dnf或者yum xff08 软件包管理器 xff09 安装软件失败 解决的方法很简单 xff0c 有些傻逼博客在那边坑人 xff0c 写的一长串解决办法都不能用 xff
  • Ubuntu彻底卸载Python

    1 查看要卸载的Python版本 若要卸载python2 xff0c 则查看命令为 python2 version 若要卸载python3 xff0c 则查看命令为 python3 version 这里我卸载python3 6 2 卸载Py
  • Ubuntu Python链接指向python3

    1 安装python3 7 sudo apt get install python3 7 2 查看python目前的指向 ls l usr bin grep python 3 删除原有的python链接 sudo rm usr bin py
  • ubuntu安装pip3

    1 安装命令 sudo apt get install python3 pip 2 查看pip3的版本以及对应的python版本 pip3 V pip 21 1 1 from usr local lib python3 7 dist pac
  • latex打双引号“ “

    latex中如果用英文输入模式的双引号键入 xff0c 则输出的结果与我们预期的不符合 xff0c 这并不是LaTeX的正确输入方式 34 test 34 输出为 xff1a 正确的输入方式为 xff1a 引号左边输入两个反引号 96 xf
  • 过拟合的原因以及解决办法(深度学习)

    过拟合 xff1a 模型在训练集上表现的非常好 xff0c 但在测试集的数据下表现很差 具体观察loss函数就是 xff0c train loss一直降低 xff0c 而test loss先降低 xff0c 而后随着epoach的增加 xf
  • Linux与MAC共享以及TimeMachine服务器的搭建

    自从添置了MBPR之后 xff0c 就发现使用Samba协议的话 xff0c Linux与MacOS之间传输速度相当不稳定 xff0c 我还一度以为是MBP的无线网卡问题 随后便尝试了一下AFP协议 xff0c 果然效果立现 xff0c 因
  • Python字符串转数字

    默认转换方式 xff1a num 61 int string 把二进制 xff0c 八进制 xff0c 十六进制转化为数字 xff0c python也提供了内置函数 xff0c 非常方便 xff0c 用法分别如下 xff1a num1 61
  • Linux根据进程名字彻底删除所有相关的子进程

    Linux有些时候kill 9进程pid xff0c 进程名字还会出现 xff0c 比如spark提交应用时的SparkSubmit 这是因为当前进程有其它子进程依赖 此时可以根据进程名字彻底删除 xff0c 这里我提供了一份模板 xff1

随机推荐