数据提取方案设计

1. 方案简介

1.1 背景

嵌入式行业的通信协议,一般是由十六进制的数据流组成,而该数据流具有多框架、多分支、常变动的特点,通常在编写完一种工具后,由于协议变更,经常需要变更工具,这就造成了工具运维困难的问题。

为了解决该问题,本方案将采用脚本的形式,将不同十六进制协议进行格式化表示,格式化表示后,在协议变更时,就可以通过更改脚本来实现,从而省去了需要频繁搭建环境进行维护的烦恼。

1.2 展望

本方案后期可扩展到所有以十六进制流协议的显示,可实现场景上位机工具加载、网页加载、设备界面加载等多种方式,将大大减少协议维护的难度。

本方案还可与《脚本工具设计方案》实现互动,可以做到工具设计、协议解析等工作的全脚本化维护,这将极大程度上减轻嵌入式行业的上位机设计负担,并为广大嵌入式行业从业人员,提供快速、高效、灵活的指令发送与协议展示的服务。

2. 方案剖析

2.1 需求分析

本章节将结合多种协议的特性,以及用户的实际需求,对协议解析方案进行简要分析,详细分析见下文。

综合编辑、解析、显示和维护等多个角度,整理用户需求如下:

  • 脚本语言:描述协议的语言,需要具有树状结构特性,便于理解,如xml语言、jeson格式,不过xml适合描述庞大的树状结构。

  • 多文件编辑:由于协议经常由多种子协议构成,因此对不同协议进行分文件编辑就显得格外重要。多文件编辑,需要嵌套编辑规则。

  • 多语言切换:工具需要支持中文、英文等多语言显示,并且多个语言之间可以快速切换。

  • 重点标注:需要支持多颜色显示方案,每个字段不同颜色显示,可以应用在重点字段重要值的标注,如操作错误的标注。

  • 字段联动:需要支持不同字段间协同关联,共同进行决策。如,检测到操作结果为成功时,则进行成功相关的解析;检测到操作结果为失败时,则进行操作失败的相关解析。

  • 协议跳转:系统跳转是针对协议中包含不同协议的场景,如系统检测到数据帧为cmd包,则自动流转到cmd包进行二次解析。

  • 协议分段:支持对数据帧进行分段处理,可以引出不同的分段操作,一旦进入该段,下面对字段的操作的位置坐标将自动切换到分段解析的坐标系。

  • 界面关联:字段可以与界面进行关联,关联后,界面组件可以快速提取有效字段进行显示。界面显示需要支持并列显示、分组显示、聊表显示和梯度显示等多种格式,这就意味着字段中需要引入深度的概念。

2.2 场景分析

2.2.1 字段提取

字段提取是指从数据帧或数据段中提取预期字段的过程,字段提取时,需要考虑到如下需求:

  • 跨段提取:跨段提取主要是考虑到某一个完整的字段分布在不同的区段的场景。如,命令包中流水号,一部分在消息帧的帧头,另一部分在消息包的包头,在解析消息包的时候,已经对数据帧进行分段,则此时就需要进行跨段提取,然后将提取的数据,进行合并处理。

  • 数组提取:数组提取需要考虑固定长度数组的提取和可变长度数组的提取。固定长度数组,就是在定义的时候就可以制定长度的数组;可变长度数组,是指其长度是跟随数据帧中某个字段变化的数组。相对于整形提取来说,数组提取相对简单,需要考虑的元素不多。

  • 文本提取:文本提取不同于数组提取,其包含多种情况,主要有固定长度文本、可变长度文本、自校验长度(特殊结尾字符),同时还需要考虑文本的编码等元素,因此文本提取和显示将会是比数组显示更复杂的逻辑。

  • 数值提取:数值提取包含按字节提取和按位域提取两种方式,但是按位域提取需要考虑因素很多,流程复杂,因此将按位域提取单独进行分类。按字节提取,是指字段在段落中,偏移位置和字段长度都是按照字节来计算。

  • 位域提取:位域提取包含单字节单位域提取、单字节多位域提取、多字节多位域提取等多种场景。单字节单位域提取,是指偏移量的单位是字节,且提取的长度是,偏移字节中的一个位域片段;单字节多位域提取,是指偏移量的单位是字节,但是提取的长度是,偏移字节中的多个段的位域片段;多字节多位域提取,是指待提取的字段,是由”单字节单位域“或”多字节多位域”中,多个场景组合的复杂的提取方式。

2.2.2 协议分段

协议分段是指对协议进行分段解析的策略,是为了方便用户变更坐标原点,重新规划解析方案而设计的处理方法。协议分段需要考虑以下需求:

  • 分段名称,是为了方便用户进行跨段处理,而设置的数据段标识。通常情况下,消息帧是最大的分段数据。

  • 协议名称,是为了指示当前子协议的类型,如“cmd数据包”。协议名称也可以不设置。

  • 段落深度,需要记录段略的深度(不指定的情况,默认比分配段落深一级),指定之后,该段落下的所有字段的深度的偏移都将基于此深度。

  • 末尾长度,段略内部需要记录段落的数据长度,以防越界。

  • 循环段落,循环段落是指多组相同的子协议共存于一个父段落的场景,但是每个段落的解析方式都是一样的,需要有循环算法和次数判断等。

2.2.3 界面显示

界面显示,是该方案系统,为用户提供的集中参考显示demo,用户可基于此demo,快速将协议解析方案合入所设计的工具。界面显示系统,需要考虑如下场景:

  • 并列显示:并列显示是指在一行中显示所有字段,这种显示方式通常会考虑一般格式和jeson格式。一般格式相对简单,即依次打印所有字符;jeson格式相对复杂,要求对不同深度的字段使用括号区分。

  • 树状显示:按照字段深度进行显示,显示过程中,可能会选择性屏蔽某些字段。

  • 分列显示:与树状显示不同的是,该模式下,所有字段都是在一列中,但是可以根据字段深度,进行快速折叠。另外,这种情况下,需要将字段与原始数据进行绑定,即点击字段相应的原始数据就会被高亮。

  • 表格显示:该模式下,会加载多种解析协议,并根据解析协议进行解析显示。当然,也可通过给不同字段命名的方式,通过检索进行过滤显示。如,查询包名称,并在某一列中显示。也会有,在某一列中,并列显示指定的字段。

  • 显示深度:所有的显示庚哥,都可能只要求显示一个区段深度的字段,其他字段不进行显示。

  • 显示色彩:所有的显示风格,都可能会要求不同字段显示不同颜色,也可能要求所有的显示都按照系统颜色进行显示。

  • 搜索过滤:方案设计需要达到可以快速进行搜索定位的目的;方案设计需要考虑到可以快速进行过滤,屏蔽不关心的字段,以方便分析。

2.3 方案框架

2.3.1 方案定位

下图为脚本协议析构方案在整个方案中的位置,图中所示,由两条主线:

  • 数据拆解:该主线的目的是将输入的数据帧拆解成数个数据段,并输出界面显示。前后经过数据接收、数据输入、协议解析、字段输出和界面输出五个阶段。数据接收,是将二进制数据流转化为数据帧的过程;数据输入,是将接收到的完整数据帧输入到本方案,进行解析的过程;字段输出,是本方案对输入数据进行解析后,输出一系列字段的过程;界面输出,是将字段按照指定样式,展现在图形界面上的过程。

  • 数据组合:该主线的目的是将界面触发的动作,转换成与设备交互的数据帧,并将数据帧发送给设备。请后经过界面输入、字段输入、协议构造、数据输出和数据发送五个阶段。界面输入,是捕获用户界面操作的过程,如点击按键;字段输入,是将界面交互后生成的字段列表,输入到本方案,进行匹配确定的过程;数据输出,是本方案对输入的字段进行匹配和组合,输出一个完整的数据帧的过程;数据发送,是将方案输出的完整数据帧进行处理,并发送给设备端的过程。

2.3.2 方案组成

下图为方案的加载运行流程图,从图中可以看出,方案设计到运行需要经历四个重要阶段:

  • 组件定义:组件定义是对协议进行的抽象化和具体化,形成一个个可被表述的对象的过程。组件定义是方案的核心,也是方案的基础,其确立了方案的可行性。组件定义主要是对组件的属性元素、显示元素和构造元素进行详细的进行描述,并且指明解析和应用的方法以及注意事项等。

  • 脚本解析:脚本解析是对用户编写的脚本进行解析,提取定义的组件和组件间关系的过程。脚本解析与应用实现紧密关联,是必不可少的环节,其承担将脚本语言转化为程序语言的角色。本方案采用通用型较强的XML语言作为脚本语言,支持多文件编写,大大简化了操作复杂度和运维的难度。

  • 格式转化:格式转化是将XML脚本语言转变为便于程序解析和执行的二进制文件的过程,转化后的文件主要有文件信息区块、组件信息区块和组件关系区块。文件信息区块,主要记录用户编辑过程中,使用到的文件,可以用于文件反转解析;组件信息区块,主要记录组件的信息,程序运行过程中,需要首先加载所有的组件信息;组件关系区块,主要记录组件之关系的区域,只有确定了组件间的关系之后,方案才能有效运转。

  • 加载应用:加载应用是将程序可执行语言文件加入系统,并明确组件引用规则的过程。方案主要有三个应用方向,将数据帧解析成一系列字段、以图形界面的形式展示协议和将用户输入的字段打包成数据帧。解析成字段后,对接jeson解析器,快速开发应用;解析出来的字段,可以以多种图形形式展示给用户,如表格列表等;用户也可输入字段,系统快速匹配,并生成数据帧。

2.3.3 组件结构

为了满足各种协议场景,方案引入了枚举组件、段落组件、字段组件、切换组件、循环组件和文件组件,组件的定义和关系如下图:

  • 枚举组件,负责常量的应用和命名,可供全局引用。

  • 段落组件,执行位置界定的组件,。

  • 字段组件,

  • 切换组件,

  • 循环组件,

  • 文件组件,

3. 架构设计

3.1 设计概论

3.1.1 组件简介

为了满足各种协议解析场景,设计引入了枚举组件、段落组件、字段组件、切换组件、循环组件和文件组件,每种组件的功能和使用说明可以参考本章后续章节的描述。各种组件的基础定义如下:
  • 枚举组件,节点名称<enum>,赋予给常量的别名,使得常量更加直观,便于理解和维护。
  • 段落组件,节点名称<seg>,对原有数据帧进行分片解析,有序的分片操作可以简化脚本的编写与维护。
  • 字段组件,节点名称<field>,将数据帧中,具有相同属性的数据进行打包,形成可被描述和解析的字段。
  • 条件组件,节点名称<conf>,用于段落之间的切换操作,使得系统分片解析成为了可能。
  • 循环组件,节点名称<loop>,针对协议中包含相同属性的段落进行循环解析,可以满足更复杂的应用场景。
  • 文件组件,节点名称<file>,用于多个文件之间的相互引用。
在使用各个组件,进行协同操作时,需要注意以下情况:
  • 除第一次解析外,脚本解析遇段落则结束,段落之间切换需要使用切换组件来描述。
  • 段落解析过程中,如遇到跳转,则在跳转段落解析完成之后,还需要回归到原段落再次进行解析。
  • 每个段落执行结束后,都需要返回段落的执行长度,以备其他组件解析使用。
  • 每个组件均需要在本文件中有完整描述,不能跨文件进行描述。

3.1.2 显示元素

显示组件的节点名称为<show>,用来定义界面主体或界面内部使用字体以及字节的样式。字体组件的元素及标签如下:
  • 字体组件,节点名称<font>,这里定义字体的完整路径。字体组件全局不能超过256个,保存时,作为全局变量进行保存,遇到重复的将会被合并。
  • 字体大小,节点名称<size>,定义字体的大小。
  • 字体加粗,节点名称<bold>,定义字体是否加粗。
  • 字体倾斜,节点名称<iatlic>,定义字体是否倾斜。
  • 显示偏移,节点名称<offset>,定制显示时,需要附加的偏移量。
  • 对齐方式,节点名称<align>,定义主题在控制间显示的对齐方式,目前支持left/right/center。
  • 显示颜色,节点名称<color>,定义字体的显示或填充颜色。颜色可以是,Red/Blue/Black/Yellow/Green等,但是再解析的节后会被解析成ARGB样式。
<show> 
    <font> </font> 
    <size> </size> 
    <bold> </bold> 
    <iatlic> </iatlic> 
    <!-- 显示偏移 --> 
    <offset> </offset> 
    <align> </align> 
    <color type="font"> </color> 
    <color type="fill"> </color> 
</show>

3.1.3 标题元素

标题元素的节点名称为<title>,用来定义组件对外展示的标题元素。标题组件的元素及标签如下:
  • 显示属性,节点名称<show>,参照“3.1.2 显示元素”。
  • 显示文本,节点名称<text>,标题的文本元素。显示文本支持多语言显示,其中"en"代表英文模式所显示的名称,"cn"代表中文模式下所显示的名称。注意,多种语言可同时标写,代表,如"en/cn"-代表中英文模式均显示该字段。
<title> 
    <show> </show> 
    <text type="cn"> 中文显示 </text> 
    <text type="en"> EnglishShow </text> 
</title>

3.2 组件设计

3.2.1 文件组件

3.2.2 字体组件

3.2.3 枚举组件

枚举组件是用来定义一组具有离散值的常量的组件,不仅可以提高数据的可读性,也可以提高脚本的可维护性。方案中枚举组件主要有两个用途:定义常量,给一组常量赋予别名,方便引用,应用主体式别名;别名替代,对常量进行定义,并在出现该常量的场景中,使用该名称进行替代显示。枚举组件的脚本描述元素如下:
属性元素
  • 组件名称,节点名称<name>,定义枚举组件的名称。对于枚举组件来说,组件名称不能与其他枚举组件命名重复。在做枚举替换的时候,需要指明替换自哪个枚举组件。
标签元素
  • 常量定义,节点名称<value>,定义一条枚举变量名称以及对应的数值。注意:条目的名称必须要有,且枚举内部所有的条目名称不能重复;枚举条目的作用域是全局,会首先进行解析,可以在其他地方进行定义;枚举条目中的数值可以进行简单的数值计算。
  • 常量命名,节点名称<alias>,对常量数值进行命名,便于展示和理解。常量命名字段中有一个数值属性,数值属性可以是数值变量,也可以是常量定义里面的别名。注意:如果枚举组件中没有组件名称属性,则常量命名标签将会被或略。
脚本示例
<enum name="EnumName">
    <value name="Item0"> DigitValue or Formula </value>
    <value name="Item1"> DigitValue or Formula </value>
    <alias name="Alias0" type="en/cn"> EnumValue </alias> 
</enum>

3.2.4 段落组件

段落组件是用来对数据进行分段命名的标签组件,数据分段后,便于直观解析与维护。段落组件的脚本描述元素如下:
属性元素
  • 组件名称,节点名称<name>,段落组件的唯一标识。注意:组件名称需要符合c语言变量命名规则;组件名称可以不做设置,意味着任何其他组件都将无法引用该组件。
标签元素
  • 段落深度,节点名称<deep>,指示字段在整个协议中深度,用于界面显示控制。默认情况下,新生段落深度将沿用该段落所在的已有段落的深度。
  • 标题元素,节点名称<title>,详见“3.1.3 标题组件”。无标题组件,意味着该切换时继承式切换,显示时可根据情况处理。
  • 字节长度,节点长度<length>,待提取的目标字段在源段落中的总体长度,可以输入固定数值数据,或者简单的数学四则运算,支持在四则运算中引用其他数值字段的值。注意,如果不设置长度标签,则默认从偏移位置到段落的末尾;此值为负值时,意味着将从末尾计数,偏移设定值选取。
脚本示例
<seg name="SegName"> 
    <deep> DigitValue </deep> 
    <title> </title> 
    <offset> DigitValue or FieldName or Formula </offset> 
    <length> DigitValue or FieldName or Formula </length> 
</seg>

3.2.5 字段组件

字段组件是用来描述段落组件中,各个字段的提取方式的组件。字段组件将在"3.3 字段提取"章节进行详细描述。

3.2.6 切换组件

切换组件的节点名称为<switch>,是用来描述分段切换解析方式的组件,其内部定义比较组件和跳转组件,可以在满足一定条件下,进行跳转解析操作。切换组件的脚本描述元素如下:
标签元素
  • 比较标签,节点名称<compare>,比较标签是用来进行一系列数学比较算法,并且在条件满足的情况下,进行相应跳转操作的标签。比较流程是数据分片处理的核心流程。
  • 跳转标签,节点名称<jump>,用于描述跳转的目标组件名称的标签。注意:跳转的目标组件只能是段落组件或文件组件;切换组件直属的跳转标签是在所有的compare条件都不满足的情况下,才会进行跳转的组件;如果切换组件中没有直属的跳转标签,则在所有条件都不满足时,解析结束,并提示解析不完整。
  • 主题元素,节点名称<title>,定义循环组件在显示时,所需要显示的主题,参照“3.1.3 标题元素”。循环组件的主题元素可以没有。
比较元素
  • 比较类型,节点名称<type>,比较组件的属性元素,用来确定比较类型,如Equal, Include, Sequence, Unequal, Less, Great, Between, LessEqual, GreatEqual。
  • 目标数值,节点名称<src>,参与比较的目标数值、字段数据或数学表达式,具体可根据比较类型来确认。
  • 参考数值,节点名称<ref>,参与比较的参考数值、字段数据或数学表达式,具体可根据比较类型来确认。
  • 跳转标签,节点名称<jump>,用于描述跳转的目标组件名称的标签。注意:跳转的目标组件只能是段落组件;条件组件中若无跳转组件,则满足该条件时,解析结束。
脚本示例
<switch> 
    <title> </title> 
    <compare type="equal"> 
        <src> DigitName or FieldName or Formula </src> 
        <ref> DigitName or FieldName or Formula </ref> 
        <ref> DigitName or FieldName or Formula </ref> 
        <jump> SegName </jump> 
    </compare> <!-- 缺省跳转的段落 --> 
    <jump> SegName </jump> 
</switch>

3.2.7 循环组件

循环组件是用来描述对段落进行循环解析的组件,循环组件适用于对某一重复段落进行解析。循环组件的脚本描述元素如下:
属性元素
  • 组件名称,节点名称<name>,段落组件的唯一标识。对于循环组件来说,该属性可以忽略。
标签元素
  • 段落标识,节点名称<seg>,指示字段解析的源字段名称,用于跨段操作,一般不设置。默认情况下,段落将沿用最后一次跳转的字段。
  • 段落深度,节点名称<deep>,指示字段在整个协议中深度,用于界面显示控制。默认情况下,新生段落深度将沿用该段落所在的已有段落的深度。
  • 主题元素,节点名称<title>,定义循环组件在显示时,所需要显示的主题,参照“3.1.3 标题元素”。循环组件的主题元素可以没有。
  • 跳转标签,节点名称<jump>,用于描述跳转的目标组件名称。注意:跳转的目标组件只能是段落组件或文件组件。
  • 执行次数,节点名称<count>,用于描述循环体需要执行的次数。如果无该项,则会一直运行,直至所有数据均已解析或解析错误。
  • 偏移位置,节点名称<offset>,待提取的目标段落在源段落中的偏移位置,可以输入固定数值数据,或者简单的数学四则运算,支持在四则运算中引用其他数值字段的值。注意:如果不设置位置标签,则默认从段落的开始位置提取;该位置为所操作的段落的偏移位置,并不一定是数据帧的偏移位置。
  • 字节长度,节点长度<length>,待提取的目标字段在源段落中的总体长度,可以输入固定数值数据,或者简单的数学四则运算,支持在四则运算中引用其他数值字段的值。注意,如果不设置长度标签,则默认从偏移位置到段落的末尾。
脚本示例
<loop name="LoopName"> 
    <deep> DigitValue </deep> 
    <jump> SegName </jump> 
    <title> </title> 
    <count> DigitValue or FieldName or Formula </count> 
    <offset> DigitValue or FieldName or Formula </offset> 
    <length> DigitValue or FieldName or Formula </length> 
</loop>

3.3 字段组件

3.3.1 数组字段

数组提取是指从协议段落中提取数组字段的过程,数组提取中的脚本描述元素如下:
属性元素
  • 字段类型,节点名称<type>,用来指示该字段所属类别,此处恒为“array"(数组类型)。
  • 组件名称,节点名称<name>,字段的唯一标识,可以用来参与字段间的数值引用,文中提到的"FieldName"就是该字段。注意:组件名称需要符合c语言变量命名规则;如果标签元素中无"text"标签,则该名称将用作显示;组件名称可以不做设置,意味着任何其他组件都将无法引用该组件。
标签元素
  • 段落标识,节点名称<seg>,指示字段解析的源字段名称,用于跨段操作,一般不设置。默认情况下,段落将沿用最后一次跳转的字段。
  • 字段深度,节点名称<deep>,指示字段在整个协议中深度,用于界面显示控制。默认情况下,字段深度将沿用字段所在的段落深度。
  • 显示元素,节点名称<show>,指示字段数值显示的方式。
  • 主题元素,节点名称<title>,定义组件在显示时,所需要显示的主题,参照“3.1.3 标题元素”。
  • 偏移位置,节点名称<offset>,待提取的字段在段落中的偏移位置,可以输入固定数值数据,或者简单的数学四则运算,支持在四则运算中引用其他数值字段的值。注意:如果不设置位置标签,则默认从段落的开始位置提取;该位置为所操作的段落的偏移位置,并不一定是数据帧的偏移位置;此值为负值时,意味着将从末尾计数,偏移设定值选取。
  • 字节长度,节点长度<length>,待提取的字段在段落中的总体长度,可以输入固定数值数据,或者简单的数学四则运算,支持在四则运算中引用其他数值字段的值。注意,如果不设置长度标签,则默认从偏移位置到段落的末尾;字节长度为负值时,意味着将从末尾计数,偏移设定值选取。
脚本示例
<field type="array" name="ArrayName"> 
    <deep> DigitValue </deep> 
    <show> </show> 
    <title> </title> 
    <offset> DigitValue or FieldName </offset> 
    <length> DigitValue or FieldName </length> 
</field>

3.3.2 文本字段

文本提取是指从协议段落中提取文本字段的过程,文本提取中的脚本描述元素如下:
属性元素
  • 字段类型,节点名称<type>,用来指示该字段所属类别,此处恒为“text"(数组类型)。
  • 组件名称,节点名称<name>,参考"数组提取->属性元素->组件名称"。
标签元素
  • 段落标识,节点名称<seg>,参考"数组提取->标签元素->段落标识"。
  • 字段深度,节点名称<deep>,参考"数组提取->标签元素->字段深度"。
  • 显示元素,节点名称<show>,指示字段数值显示的方式。
  • 主题元素,节点名称<title>,定义组件在显示时,所需要显示的主题,参照“3.1.3 标题元素”。
  • 偏移位置,节点名称<offset>,参考"数组提取->标签元素->偏移位置"。
  • 字节长度,节点长度<length>,参考"数组提取->标签元素->字节长度"。
  • 文本编码,节点名称<encode>,指示字段数值的编码类型,用在界面显示中,界定字段数值的显示文本。目前,支持utf8和unicode编码。
脚本示例
<field type="text" name="TextName">
    <deep> DigitValue </deep> 
    <show> </show> 
    <title> </title> 
    <encode> utf8/unicode </encode> 
    <offset> DigitValue or FieldName </offset> 
    <length> DigitValue or FieldName </length> 
</field>

3.3.3 数值字段

数值提取是指从协议段落中提取数值字段的过程,数值提取中的脚本描述元素如下:
属性元素
  • 字段类型,节点名称<type>,用来指示该字段所属类别,此处恒为“digit"(数组类型)。
  • 组件名称,节点名称<name>,参考"数组提取->属性元素->组件名称"。
标签元素
  • 字段深度,节点名称<deep>,参考"数组提取->标签元素->字段深度"。
  • 显示元素,节点名称<show>,指示字段数值显示的方式。
  • 主题元素,节点名称<title>,定义组件在显示时,所需要显示的主题,参照“3.1.3 标题元素”。
  • 数值别名,节点名称<alias>,用来对数值数据进行重命名,可以让字段更容易理解。
  • 数值前缀,节点名称<prefix>,用来控制数值显示的前缀属性。
  • 数值后缀,节点名称<suffix>,用来数值在界面显示的后面名称,通常是数值所使用的单位类型,如kg/mm。
  • 偏移位置,节点名称<offset>,参考"数组提取->标签元素->偏移位置"。
  • 字节长度,节点长度<length>,参考"数组提取->标签元素->字节长度"。
  • 编码方式,节点名称<endian>,指示字段数值的编码类型,用于字段的解析时,确定字段的数据流编码传输格式。数值的传输格式有两种,即大端模式(big-endian)和小端模式(little-endian),缺省情况下,默认为大端模式。
  • 数值转化,节点名称<convert>,用来对数值进行二次转化,支持简单得数学计算。如,解析数值的长度为实际长度的一半时,既可以通过数学公式接得,实际得长度为DigitName/2。
脚本示例
<field type="digit" name="DigitName"> 
    <deep> DigitValue </deep> 
    <show> </show> 
    <title> </title> 
    <alias> EnumName </alias> 
    <prefix> Text </prefix> 
    <suffix> Text </suffix> 
    <endian> big/little </endian> 
    <offset> DigitValue or FieldName </offset> 
    <length> DigitValue or FieldName </length> 
    <convert> </convert> 
</field>

3.3.4 位域字段

位域提取是指从协议段落中提取位域字段的过程,位域提取需要考虑到的因素颇多,因此其流程和标签也会比其他类型的字段多很多。位域提取中的脚本描述元素如下:

属性元素

  • 字段类型,节点名称<type>,用来指示该字段所属类别,此处恒为“bit"(数组类型)。

  • 组件名称,节点名称<name>,参考"数组提取->属性元素->组件名称"。

标签元素

  • 段落标识,节点名称<seg>,参考"数组提取->标签元素->段落标识"。

  • 字段深度,节点名称<deep>,参考"数组提取->标签元素->字段深度"。

  • 显示元素,节点名称<show>,指示字段数值显示的方式。

  • 主题元素,节点名称<title>,定义组件在显示时,所需要显示的主题,参照“3.1.3 标题元素”。

  • 数值别名,节点名称<alias>,参考"数值提取->标签元素->数值别名"。

  • 数值前缀,节点名称<prefix>,用来控制数值显示的前缀属性。

  • 数值后缀,节点名称<suffix>,参考"数值提取->标签元素->数值后缀"。

  • 偏移位置,节点名称<offset>,参考"数组提取->标签元素->偏移位置"。注意,此处是用来设置字段在当前段落的整体偏移位置,偏移单位为字节,后面的"value"的偏移单位在在此基础上,按位域进行累加。

  • 数值转化,节点名称<convert>,参考"数值提取->标签元素->数值转化"。

  • 位域数值,节点名称<value>,指示位域字段中,各个数值得构成部分,后面可以通过"数值转化"进行计算,得到实际得数值。位域字段得计息方式,参考"数值标签"

数值标签

  • 组件名称,节点名称<name>,参考"数组提取->属性元素->组件名称"。注意,这里的组件名称,只作用于操作字段内部,只需要保证待操作字段内部所有的数值标签名字唯一即可。

  • 段落标识,节点名称<seg>,参考"数组提取->标签元素->段落标识"。注意,如果没有该标签,则意味着从当前段落中取值。

  • 位域偏移,节点名称<offset>,参考"数组提取->标签元素->偏移位置"。注意,此处的偏移单位是bit(位)。

  • 位域长度,节点长度<length>,参考"数组提取->标签元素->数组长度"。注意,此处的偏移单位是bit(位)。

  • 数值转化,节点名称<convert>,参考"数值提取->标签元素->数值转化"。

脚本示例

<field type="bit" name="BitName"> 
    <deep> DigitValue </deep> 
    <show> </show> 
    <title> </title> 
    <alias> EnumName </alias> 
    <prefix> Text </prefix> 
    <suffix> Text </suffix> 
    <offset> DigitValue or FieldName </offset> 
    <value name="ValueName0"> 
        <seg> SegName </seg> 
        <offset> DigitValue or FieldName </offset> 
        <length> DigitValue or FieldName </length> 
        <convert> </convert> 
    </value> 
    <value name="ValueName1"> 
        <seg> SegName </seg> 
        <offset> DigitValue or FieldName </offset> 
        <length> DigitValue or FieldName </length> 
        <convert> </convert> 
    </value> 
    <convert> </convert> 
</field>

3.4. 应用示例

3.4.1 数据格式

本章节将以下图数据帧格式,来阐述界面设计规则及注意事项:

3.4.2 组件说明

字段命名如下:

  • 数据帧,组件类型<seg>,组件深度<0>,组件名称<Frame>,显示文本<Frame/帧数据>。

  • 包长度,组件类型<field>,组件名称<PktLen>,字节长度(WORD),显示文本<PacketLength/包长度>。

  • 包类型,组件类型<field>,组件名称<PktType>,字节长度(WORD),显示文本<PacketType/包类型>。

  • 包数据,组件类型<seg>,组件深度<1>,组件名称<Packet>,显示文本<Packet/包数据>。

  • 段长度,组件类型<field>,组件名称<SegLen>,字节长度(WORD),显示文本<SegmentLength/段长度>。

  • 段类型,组件类型<field>,组件名称<SegType>,字节长度(WORD),显示文本<SegmentType/段类型>。

  • 段数据,组件类型<seg>,组件深度<1>,组件名称<Segment>,显示文本<Segment/段数据>。

  • 数据长度,组件类型<field>,组件名称<DataLen>,字节长度(WORD),显示文本<DataLen/数据长度>。

  • 数据类型,组件类型<field>,组件名称<DataType>,字节长度(WORD),显示文本<DataType/数据类型>。

  • 数据数值,组件类型<field>,组件名称<DataValue>,字节长度(WORD),显示文本<DataValue/数据数值>。

  • 帧校验码,组件类型<field>,组件名称<FrmCRC>,字节长度(WORD),显示文本<FrameCRC/帧校验码>。

3.4.3 脚本示例

索引文件《index.xml》:

<file> alias/alias.xml </file> 
<file> frame.xml </file>

别名文件《alias.xml》:

<enum name="PacketTypeEnum"> 
    <value name="PacketTypeCmd"> 0 </value> 
    <value name="PacketTypeEvt"> 1 </value> 
    <alias name="CMD " type="en"> PacketTypeCmd </alias>
    <alias name="命令包" type="cn"> PacketTypeCmd </alias> 
    <alias name="EVT " type="en"> PacketTypeEvt </alias> 
    <alias name="事件包" type="cn"> PacketTypeEvt </alias> 
</enum> 
    <enum name="SegmentTypeEnum"> 
    <value name="SegmentTypeSys"> 0 </value> 
    <value name="SegmentTypeDev"> 1 </value> 
    <alias name="SYS"> SegmentTypeSys </alias> 
    <alias name="DEV"> SegmentTypeDev </alias> 
</enum> 
<enum name="SegMentCmdID"> 
    <value name="GetSysVersion"> 0 </value> 
    <value name="GetSysInfo"> 1 </value> 
    <alias name="GetSysVersion"> GetSystemVersion </alias> 
    <alias name="GetSysInfo"> GetSystemInfo </alias> 
</enum>

数据帧文件《frame.xml》:

<seg name="Frame"> 
    <deep> 0 </deep> 
    <text type="en"> Frame </text> 
    <text type="cn"> 帧数据 </text> 
    <offset> 2 </offset> 
    <length> -2 </length> 
</seg> 
<field type="digit" name="PktLen"> 
    <title> 
        <text type="en"> PacketLength </text> 
        <text type="cn"> 包长度 </text> 
    </title> 
    <offset> 0 </offset> 
    <length> 2 </length> 
    <convert> PktLen-6 </convert> 
</field> 
<field type="digit" name="PktType"> 
    <text type="en"> PacketType </text> 
    <text type="cn"> 包类型 </text> 
    <alias> PacketTypeEnum </alias> 
    <offset> 2 </offset> 
    <length> 2 </length> 
</field> 
<switch> 
    <compare type="equal"> 
        <src> PktType </src> 
        <ref> PacketTypeCmd </ref> 
        <jump type="file"> CmdPkt.xml </jump> 
    </compare> 
    <compare type="equal"> 
        <src> PktType </src> 
        <ref> PacketTypeEvt </ref> 
        <jump type="file"> EvtPkt.xml </jump> 
    </compare> 
</switch> 
<field type="digit" name="FrmCRC"> 
    <text type="en"> FrameCRC </text> 
    <text type="cn"> 帧校验码 </text> 
    <offset> -2 </offset> 
    <length> 2 </length> 
</field>

命令包文件《CmdPkt.xml》:

<seg name="CmdPkt"> 
    <deep> 1 </deep> 
    <text type="en"> CmdPacket </text> 
    <text type="en/cn"> 命令包 </text> 
    <offset> 4 </offset> 
    <length> PktLen </length> 
</seg> 
<field type="digit" name="SegLen"> 
    <text type="en"> SegmentLength </text> 
    <text type="cn"> 段长度 </text> 
    <offset> 0 </offset> 
    <length> 2 </length> 
</field> 
<field type="digit" name="SegType"> 
    <text type="en"> SegmentType </text> 
    <text type="cn"> 段类型 </text> 
    <alias> SegmentTypeEnum </alias> 
    <offset> 2 </offset> 
    <length> 2 </length>
</field> 
<switch> 
    <compare type="equal"> 
        <src> SegType </src> 
        <ref> SegmentTypeSys </ref> 
        <jump type="file"> SysPkt.xml </jump> 
    </compare> 
    <compare type="equal"> 
        <src> SegType </src> 
        <ref> SegmentTypeDev </ref> 
        <jump type="file"> DevPkt.xml </jump> 
    </compare> 
</switch>

事件包文件《EvtPkt.xml》:

<!-- 参考CmdPkt.xml的描述 -->

系统段文件《SysSeg.xml》:

<seg name="CmdPkt"> 
    <deep> 2 </deep> 
    <text type="en"> CmdPacket </text> 
    <text type="cn"> 命令包 </text> 
    <offset> 4 </offset> 
    <length> SegLen </length> 
</seg> 
<field type="digit" name="CmdID"> 
    <text type="en"> MsgID </text> 
    <text type="cn"> 消息编号 </text> 
    <alias> SegMentCmdID </alias> 
    <offset> 0 </offset> 
    <length> 2 </length> 
</field> 
    <field type="digit" name="CmdSerial"> 
    <text type="en"> CmdSerial </text> 
    <text type="cn"> 命令流水号 </text> 
    <offset> 2 </offset> 
    <length> 2 </length> 
</field> 
<switch> 
    <compare type="equal"> 
        <src> CmdID </src> 
        <ref> GetSysVersion </ref> 
        <jump type="file"> GetSysVers.xml </jump> 
    </compare> 
    <compare type="equal"> 
        <src> CmdID </src> 
        <ref> GetSysInfo </ref> 
        <jump type="file"> GetSysInfo.xml </jump> 
    </compare> 
</switch>

设备段文件《DevSeg.xml》:

<!-- 参考SysSeg.xml的描述 -->

获取系统版本文件《GetSysVers.xml》:

<seg name="GetSysVers"> 
    <deep> 3 </deep> 
    <text type="en"> SystemVersion </text> 
    <text type="cn"> 系统版本 </text> 
    <offset> 4 </offset> 
    <length> SegLen-4 </length> 
</seg> 
<loop name="LoopName"> 
    <jump type="seg"> SysVersion </jump> 
    <offset> 0 </offset> 
</loop> 
<seg name="SysVersion"> </seg> 
<field type="digit" name="SysVersionDataLen"> 
    <text type="en"> DataLength </text> 
    <text type="cn"> 数据长度 </text> 
    <offset> 0 </offset> 
    <length> 2 </length> 
</field> 
<field type="digit"> 
    <text type="en"> DataType </text> 
    <text type="cn"> 数据类型 </text> 
    <offset> 2 </offset> 
    <length> 2 </length> 
</field> 
<field type="digit"> 
    <text type="en"> DataValue </text> 
    <text type="cn"> 数据数值 </text> 
    <offset> 4 </offset> 
    <length> SysVersionDataLen </length> 
</field>

获取系统信息文件《GetSysInfo.xml》:

<!-- 参考GetSysVers.xml的描述 -->

3.5 流程说明

3.5.1 基础解析

3.5.2 段落切换

3.5.3 循环执行

暂时无法在飞书文档外展示此内容

3.5.4 段落执行

3.6 界面设计

3.6.1 并列显示

并列显示:并列显示是指在一行中显示所有字段,这种显示方式通常会考虑一般格式和jeson格式。一般格式相对简单,即依次打印所有字符;jeson格式相对复杂,要求对不同深度的字段使用括号区分。

CommonFormat: Field1:Value1; Field2:Value2; Field3:Value3; JesonFormat: Field1:Value1; {Field2:Value2; Field3:Value3;}

3.6.2 树状显示

树状显示:按照字段深度进行显示,显示过程中,可能会选择性屏蔽某些字段。

Field1 Value1 
    Field2 Value2 
        Field3 Value3

3.6.3 分列显示

分列显示:与树状显示不同的是,该模式下,所有字段都是在一列中,但是可以根据字段深度,进行快速折叠。

另外,这种情况下,需要将字段与原始数据进行绑定,即点击字段相应的原始数据就会被高亮。

3.6.4 表格显示

表格显示:该模式下,会加载多种解析协议,并根据解析协议进行解析显示。当然,也可通过给不同字段命名的方式,通过检索进行过滤显示。如,查询包名称,并在某一列中显示。也会有,在某一列中,并列显示指定的字段。

3.6.5 查询过滤

负责协议过滤显示的管理,如包含、排他等算法处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值