原生代码映射方式根据通信协议规定的字段含义,逐个实现了属性和二进制报文之间的转换。
原生代码的编码类型有两种——紧凑型编码(compact)和可变长编码(TLV)。不同于紧凑型编码,可变长编码只有在编码或者解析时才能知道具体的位置代表什么含义。 TLV由标签(tag)、长度(length)、值(value)三部分组成。
# 紧凑型编码方式
# 入参编码
入参编码定义了输入参数至二进制透传指令的转换规则。入参编码需要先设定编码的长度、字节序和编码方式,根据设定的编码长度,下方会生成代表每个字节的小方块。
选择小方块后点击编辑规则进行对应的字节位编码,支持三种编码规则:指定常量、分配属性和代码转换。
指定常量:为该字节(或比特位)分配一个十进制常量。
分配属性:赋予入参属性值到指定的位置,如下图所示,将指令参数power
赋予指令的第12位。
代码转换:将入参属性经过groovy脚本运算后赋与指定位置
如果指令目标位置取值只取决于单条属性,可以通过“分配属性”选中该属性,在脚本中通过data
变量使用该属性;
如果指令目标位置取值取决于多条属性,可以在操作参数转换中配置指令参数,在脚本中通过src.
的方式使用该属性。
注意脚本编码中获取参数的变量与原生代码不同。
TIP
解代码中可以通过logout("this is a test log",scriptLogInfo);来打印需要的日志,调试台调试的时候可以显示这些日志。 其中第一个入参为打印的日志,第二个入参为固定参数,不要改动。
# 出参解码
出参解码定义了设备上报二进制指令至设备属性的转换规则。出参解码同样需要先设定指令长度、字节序和解码方式,不同于入参编码的是,出参指令长度包含10位集团消息体(下图中指令下标0-9的灰色方块)。
出参解码下指令范围首部有若干个灰色的方块,默认代表设备电控协议头,它们的含义是:
下标 | 说明 |
---|---|
0 | 同步头 |
1 | 消息长度 |
2 | 家电类型 |
3 | 帧同步校验 |
4 | 保留字段 |
5 | 保留字段 |
6 | 消息标识 |
7 | 框架协议版本 |
8 | 家电协议版本 |
9 | 消息类型标识 |
出参解码定义了指令到属性的映射规则,因此必须先选中某个属性,然后在下方的指令范围中选择对应下标的指令进行转换。
出参解码支持直接转换和代码转换两种方式:
直接转换:将指令选定位的值赋给该属性。
代码转换:通过groovy脚本对指令进行变换后赋给该属性,脚本可以通过src[index]
的方式获取指令指定下标的值。下图中通过脚本将指令下标为39和40的数据进行计算后转化为了workingTime
属性。
# TLV型编码方式
# TLV入参编码
假设有电控协议结构如下图。
因为该电控协议包含10byte的mcu头,长度设置为2。
编码方式中选中“紧凑型+tlv”->紫色方框。
结合之前的电控协议的第12位可知,添加前置字段需要勾选tlv规则数量,长度为1,填充到指定长度也是1。最大指令长度可以设置为54。
关联tlv分组处“选择”->“+”。
根据电控协议可知,该控制功能中,该分组是定长的,固定由2位功能码+3位值组成,tlv标签位(tag)长度为2byte,长度位(length)为0byte,值位(value)的长度为3byte。本例中分组规则为定长,如果使用变长,点击右边的“使用变长”。
选择“新增条目”后进入tlv规则编辑界面,标识选中属性,若sleep在电控文档中对应的功能码为0x00,转换十进制得到0,则tag填0,编辑入参编码并保存。此时,入参编码同紧凑型编码方式。
保存tlv规则和tlv分组后,需要选择指定的tlv分组及用到的规则。
# TLV出参编码
如果电控协议的出参解码也使用TLV规则,则需要配置TLV出参解码规则,并在出参解码中指定规则。
TLV出参解码规则使用相对位,src[0]代表(value)值位的第0位。
# 前置脚本检查
返回空字符串或者null表示通过校验,非空则返回错误提示,示例脚本如下,使用java语法,入参为JsonObject (opens new window) 类型的src。
Integer workStatus = src.getInteger("workStatus");
if (null == workStatus) {
return "错误,入参中请包含工作状态";
} else if (100 < workStatus) {
return "工作状态输入超出范围";
} else {
return null;//可以返回空字符串或者null,表示正常
}
注,全状态动作中会先进行查询然后再进行操作,使用的前置检查脚本来源于全状态查询,此时可以使用state获取查询到的状态。例如全状态查询结果为{"A":1,……},则脚本可以这样Integer A = state.getInteger("A");
获取