Skip to content

Latest commit

 

History

History
89 lines (47 loc) · 4.58 KB

README.md

File metadata and controls

89 lines (47 loc) · 4.58 KB

StreamParser

背景

在嵌入式软件开发中,我们几乎一定会涉及到协议和数据相关的解析,这些协议往往有两种解析方式:流式解析块式解析

块式解析是指将整个协议接收下来,然后对整个接收缓冲区内的所有数据进行解析处理。这种解析方式的典型使用场景是:使用DMA进行定长协议的接受。在解析的过程中可以使用标准库函数进行字符串的解析,代码的编写上一般不会十分复杂,但是对于协议的设计有一定的要求。

流式解析是指在接收的过程中,每接收到一个字符就进行一部分处理,进而从字符串流中完成数据解析的方式。典型的使用场景是:使用接收中断进行接收和解析。解析过程相对而言比较复杂,没有现成的函数可用,不过这种方式对于协议设计的要求比较宽松,并且不限制协议的长度。

本模块旨在简化流式数据解析的流程,开发者仅需提供协议头、数据分隔标志符以及协议尾即可完成整个协议的解析。

PS:该模块的开发思路源自GPS中NMEA协议的解析。

模块功能

该模块的功能是依据格式字符串将字符流中的字符串数据解析为代码中可用的数据。比如:

  • "d":将字符串“123”解析为整型123;

  • "f":将字符串“123.456”解析为浮点型(双精度型)123.456;

  • "s":将数据流中的字符串转化为存在于用户缓冲区中的字符串;

  • " ":忽略部分开发者不关心的数据;

一个StreamParser可以处理的典型的协议如下:

$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F

其中,我们将$GP称为头字符串(也可以使用$),它标志着一个协议包解析的开始;将,称为分隔字符串,它标志着一个解析部分的结束。在整个协议的解析过程中,格式字符串中的每个字符都对应着一个解析部分;可以将*1F作为一个尾字符串,它标志着一个协议包解析的结束。

使用*1F进行解析的方式在GPS解析中是错误的操作,因为最后两位是校验位,并不是固定的,此处只是简单举个例子。

使用说明

要在你的工程中使用StreamParser,仅需将一对头文件与源文件添加进入你的工程路径,解决包含与连接问题后做出如下处理:

  • 为你的解析器定义一个sParser_t句柄(不同解析器之间相互独立);

  • 使用metaData_t类型为你的协议数据定义一个缓冲区;

  • 为每个解析器调用SParser_Init函数进行初始化;

    • 初始化参数如下:

      parser:解析器句柄

      headStr:协议头字符串

      tailStr:协议尾字符串

      divStr:协议分隔字符串

      typeList:格式字符串

  • 将你接收到的数据流逐个字符传入SParser_Parsech参数;

    • 解析器参数如下:

      parser:解析器句柄

      dataArray:协议数据缓冲区指针

      ch:数据流中的字符

  • 监视SParser_Parse函数的返回值,一旦该函数返回1,则说明一个协议包的解析已经完成。

  • 从缓冲区中取出数据使用。

关于dataArray的使用的注意事项:

当你使用字符串解析时,你可以将dataArray中对应格式字符串中s的位置设置为预先创建的字符串缓冲区地址,解析器会自动使用这个地址。否则,请务必确保对应位置为NULL,解析器会为解析出的字符串自动创建长度为STRING_BUFFER_SIZE的缓冲区。

此外,如果你使用预先创建缓冲区的方式,请确保缓冲区的大小大于等于STRING_BUFFER_SIZE(如果你能确保你的缓冲区可以装下协议字符串的话也可以忽略),因为解析器内部只对STRING_BUFFER_SIZE的长度进行了边界检查。

你还有一些配置宏可以用于配置解析器:

  • 考虑到float可能精度不足,所以还可以通过将USE_DOUBLE置1来配置解析器使用双精度;

  • 如果你用不到字符串解析的功能,可以通过将USE_STRING_PARSE置0的方式来节省部分代码空间(省,但不多);

  • 你可以使用STRING_BUFFER_SIZE来配置字符串解析默认的缓冲区边界检查范围和默认创建的缓冲区大小

示例

函数的使用示例位于./test中,也是一个简单的测试文件。

解析器在一些头、分隔、尾字符串较复杂的情况下可能会匹配失败,请自行简化协议设计,当然也欢迎提出PR完善Bug。