每个协议文件都可包含import, items, protocols三项,但并非必须,解析时也按照前面顺序依次解析。
import|导入其他协议文件
json数组,填写需要引入的其他json协议文件,示例:
{
"import": [
"example_utils.json",
"example_setting.json"
]
}
items
items当中每一项由名称-内容构成,经过解析,将注入当前协议集合的公共项库中,可在解析protocols时通过import关键字调用,用于在同一个item存在于多个协议时提高重用性。
name
表示该项名称,对应自定义脚本函数scripts
中args
的from_frame_data
参数项,同时,如需要生成波形,波形名称中也会含有name,因此需要保持唯一。
data_type
支持多种数值类型,用 data_type 表示,基础类型包括
uint8_t uint16_t uint24_t uint32_t uint64_t
int8_t int16_t int24_t int32_t int64_t
float double
而为了节省字节占用,通常会将浮点型乘以倍数后以整形传输,例如 float 类型数据 ,需要以单字节int8_t传输,可根据实际情况乘以一定倍率,这里假设100,则有对应关系如下
- 用户端:int8_t=[float,double]*100
- 上位机:double=int8_t/100
协议定义中上位机端表示,也即int8_t/100
如果是数组,则可在末尾直接添加数组标识,如int8_t/100[3]
bytes
用于表示当前项占用的字节数,用于无法确定长度的item类型,如frame_tail
,reserved
等
type
frame_header
协议固定帧头,用以协议数据检测,必须作为block
中首项存在,示例:
{
"use": "frame_header",
"hex": "55 04"
}
frame_length
仅变长协议需要,且必须为帧头后一项
{
"use": "frame_length",
"data_type": "uint16_t"
}
frame_tail
协议帧尾,用于协议数据校验,非必须项,目前支持如下校验方式
固定值校验,仅对帧尾进行固定值比对,相同则校验通过。
{
"use": "frame_tail",
"check_type": "fixed",
"hex": "ee"
}
和校验,对帧尾之前所有数据累加求和,sum类型为
bytes
对应长度的无符号整形,sum相等则校验通过。{
"use": "frame_tail",
"check_type": "sum",
"bytes": 1
}
循环冗余校验(CRC),类似和校验,仅计算方式替换为CRC
{
"use": "frame_tail",
"check_type": "crc",
"polynomial": "0x5503",
"initial_value": "0x5503",
"final_xor": "0x5503",
"reflect_input": true,
"reflect_output": true
}
异或校验(BCC),类似和校验,仅计算方式替换为BCC
{
"use": "frame_tail",
"check_type": "bcc"
}
reserved
保留字节,作为协议中暂时不用部分的占用符
{
"use": "reserved",
"bytes": 11,
"placeholder": "0xff"
}
其中,
placeholder
表示当前保留字节填充字符(适用于write
类型协议),若为空则默认填充0x00。flag
用于表示标志项,支持位域,对于可写协议,将根据标志项生成对应下拉框控件,对于可读协议,将根据接收到的值显示对应标志项。
{
"use": "flag",
"bit_field": [
{
"bits": 2,
"name": "mode",
"elements": [
"write",
"read",
"restart=3"
]
},
{
"bits": 2
},
{
"bits": 1,
"name": " led",
"elements": [
"off",
"on"
]
}
]
}
其中,name为空表示此项为保留位,bits表示占用比特,elements可单独指定枚举值,如上面
restart=3
,未指定则顺延,规则同C语言枚举。value
表示常规数值项,
read
协议将生成只读文本控件,write
协议将生成可编辑单行文本控件,若数据类型为数组,则将生成数组大小对应的资源数量,其中资源名称命名方式q_i
,如这里为q_0,q_1,q_2,q_3。{
"name": "q",
"use": "value",
"data_type": "float[4]"
}
line
表示需要使用波形显示的数据项,除波形资源外,还将生成
value
对应全部资源。{
"name": "eop",
"use": "line",
"data_type": "uint8_t/100"
}
position
表示需要显示三维位置的数据项,除三维位置资源外,还将生成二维位置,
line
相应资源,注意,数据类型必须为长度为3的数组。{
"name": "pos",
"use": "position",
"data_type": "int24_t/1000[3]"
}
attitude
表示需要显示物体3D姿态的数据项,除姿态资源外,还将生成
line
相应资源,注意,数据类型必须为长度为3的数组。{
"name": "angle",
"use": "attitude",
"data_type": "int16_t/100[3]"
}
position_attitude
表示需要同时显示3D位置和姿态的数据项,不同于单纯
position
,此项生成的3D资源中,模型将同时绘制位置及姿态角,2D资源中将额外位置航向角。{
"name": "pose",
"use": "position_attitude",
"position": {
"data_type": "int24_t/1000[3]"
},
"attitude": {
"data_type": "int16_t/100[3]"
}
}
hex_array
表示16进制变长数组,对于
read
协议,将生成对应多行只读控件,16进制显示,对于write
协议,将生成对应可编辑多行控件。{
"name": "dt",
"use": "hex_array",
"length": {
"data_type": "uint16_t"
}
}
block_with_id
同一帧协议,但根据
block+id
不同,数据分别归属于不同组,例如可用于多激光测距传感器TOFSense级联情况下数据输出协议帧。{
"use": "block_with_id",
"block_id": {
"data_type":"uint8_t"
},
"block": [
{
"use":"value",
"data_type":"uint32_t",
"name":"systemTime"
},
{
"use":"line",
"data_type":"uint24_t/1000",
"name":"dis"
},
......
]
}
group
同一帧协议中,拥有多个block,block之间根据
block_id
区分,block个数通过block_count
计算,可用于室内高精度实时定位系统 LinkTrack 的Node系列变长协议,用以显示多个节点位置信息或距离信息等。{
"use": "group",
"block_count": {
"data_type": "uint8_t"
},
"block_id": {
"import": "LtBlockRoleId"
},
"block": [
{
"import": "LtDis"
},
{
"import": "LtFpRssi"
},
......
]
}
内存分布:
block_count
+[block_id
+block
]+…+[block_id
+block
]protocols|协议
name
mode
协议模式,均从上位机角度描述,分为如下三种
read
表示只读协议,上位机仅从收到的数据中提取并解析该协议write
表示只写协议,上位机仅根据协议生成对应控件,用户可修改控件生成新的协议帧数据,用于下发-
minimum_length
表示协议帧最小字节数,对定长协议而言,表示全部字节数,用于校验目的,若格式定义错误导致实际解析的协议最小长度不等于用户输入的
minimum_length
,加载协议时将报错提醒。block
json数组,按先后顺序定义了整个协议格式,可通过
import
调用items
中的公共项,也可直接编写单项,具体项定义规则参考前面itemsscripts
可通过JavaScript语法定义多个数据处理函数,处理来自当前所属协议的实时数据以及用户自定义的数据,并将函数输出结果通过本软件支持的可视化方式呈现出来,同时也支持console输出,用户可在脚本函数中自定义打印内容,内容将在软件的日志信息中实时显示,用户可用脚本定义自己的数据处理算法,如常见数据滤波算法(示例中提供了中值滤波,滑动窗口滤波,求取标准差等函数),或者做数据检查,日志提醒输出等。
"scripts": {
"global_properties": [
"length"
],
"import": ["example_script.js"],
"items": [
{
"name": "pos_processed",
"args": {
"from_frame_data": [
"pos_0",
"pos_1",
"pos_2"
],
"from_user_input": [
"z_offset"
],
"from_global_properties": [
"length"
]
},
"outputs": [
"x","y","z"
],
"function": "positionFilter",
"use": "position"
},
{
"name": "angle_0",
"args": {
"from_frame_data": [
"angle_0"
],
"from_user_input": [
"min","max"
]
},
"function": "checkRange"
}
]
}
其中
global_properties
表示当前分组下所有脚本函数均可使用的全局属性,软件将自动生成对应的控件供用户编辑属性,如用于定义多个滤波函数的数据长度import
用于引入JavaScript文件,后续function
即从引入的文件中查找items
表示脚本的集合name
表示脚本名称,将用于定义资源名称args
表示将会传入脚本函数的参数集合,不需要类型无需填写,按顺序传入function
参数列表from_frame_data
从实时协议帧中获取数据from_user_input
软件将为每个脚本单独生成各自的参数控件,可实时改变参数from_global_properties
从前面的global_properties
中获取参数
- function 表示脚本函数,简单函数可直接行内编辑,但没有语法检查,推荐在JavaScript文件中编辑,倘若在前面import的文件中无法找到函数,则尝试直接解析函数,若解析失败则会报错。