协议解析开发
开发流程概述
开发步骤
- 1.登录协议管理后台
- 2.创建协议、填入相关标识信息
- 3.对着文档嘎嘎写、调试运行
- 4.部署上线
打开http://${host}:{port}/magic/debug/index.html 账号密码和平台的一致
1、登录协议控制台

2、创建协议

3、编写与调试
开发环境
平台支持JavaScript(ES5) 、 jar(打包上传) 和 内置编辑器,推荐使用内置编辑器,安全可控扩展性强
- 脚本写好了,如下
JavaScript
import log;
// 16进制转10进制数字
var hexToInt = hex => {
return Integer.parseInt(hex, 16);
};
// 预解码,解析上报的设备编号 deviceId
var preDecode = payload => {
var result = {}
var payloadHex = payload.toUpperCase() // 转为大写
// 校验报文长度和帧头
if (payloadHex.length() >= 18 && payloadHex.substring(0, 4) === "A5A5") {
// 从第5位开始取4字节(8个字符)作为 deviceId
result.deviceId = payloadHex.substring(4, 12)
}
return result
}
var decode =(payload,context) => {
log.info("进入编解码,payload={},context={}",payload,context)
var result = [];
var payloadHex =payload.toUpperCase();
var propertiesObj = { "messageType": "PROPERTIES", "properties": {} };
var eventObj = { "messageType": "EVENT", "event": "", "data": {} };
// 验证帧头帧尾
if (payloadHex.substring(0, 4) != "A5A5" || payloadHex.substring(payloadHex.length() - 4) != "5A5A") {
return jsonToStr([{ "error": "无效帧格式" }]);
}
// 提取核心字段
var deviceId = payloadHex.substring(4, 8); // 设备ID(4字节)
var cmdCode = payloadHex.substring(8, 10); // 命令码(1字节)
var dataLen = hexToInt(payloadHex.substring(10, 12)); // 数据长度
var dataHex = payloadHex.substring(12, 12 + dataLen * 2); // 数据区
var checksum = payloadHex.substring(12 + dataLen * 2, 14 + dataLen * 2); // 校验和
// 设备ID存入所有对象
propertiesObj.deviceId = deviceId;
eventObj.deviceId = deviceId;
//验证新内容
propertiesObj.context=context;
propertiesObj.tcpEncode = 'HEX';
propertiesObj.replyPayload = '727270632C676574637371'
// 1. 属性上报(命令码01)
if (cmdCode == "01" && dataLen == 7) {
// 解析开关状态(01=开,00=关)
propertiesObj.properties.powerState = dataHex.substring(0, 2) == "01" ? "01" : "00";
// 解析电流(2字节,单位0.01A)
var currentHex = dataHex.substring(2, 6);
propertiesObj.properties.current = (hexToInt(currentHex) * 0.01).toFixed(2);
// 解析电压(2字节,单位0.1V)
var voltageHex = dataHex.substring(6, 10);
propertiesObj.properties.voltage = (hexToInt(voltageHex) * 0.1).toFixed(1);
// 解析功率(2字节,单位1W)
var powerHex = dataHex.substring(10, 14);
propertiesObj.properties.power = hexToInt(powerHex).toString();
// 加入结果集
result.push(propertiesObj);
}
// 2. 事件上报(命令码02)
if (cmdCode == "02" && dataLen >= 3) {
// 事件类型(01=过载,02=过压,03=上线,04=下线)
var eventType = dataHex.substring(0, 2);
if (eventType == "01") {
eventObj.event = "overload";
eventObj.data.overload = hexToInt(dataHex.substring(2, 6)) + "W"; // 过载功率
}
if (eventType == "03") {
eventObj.event = "online";
eventObj.data.online = "设备上线";
}
if (eventType == "04") {
eventObj.event = "offline";
eventObj.data.offline = "设备下线";
}
result.push(eventObj);
}
// 3. 响应报文(命令码04)
if (cmdCode == "04" && dataLen == 1) {
var replyObj = {
"messageType": "REPLY",
"function": "switch",
"data": { "result": dataHex == "00" ? "success" : "fail" }
};
replyObj.deviceId = deviceId;
result.push(replyObj);
}
return jsonToStr(result);
};
var encode = payload => {
var obj = toJson(payload);
var deviceId = obj.data.deviceId; // 设备ID(4位16进制,如"0001")
var func = obj.function;
var params = obj.data;
// 控制开关(function=switch)
if (func == "switch") {
var state = params.state; // 目标状态:01=开,00=关
if (state != "01" && state != "00") {
return ""; // 无效状态,返回空
}
// 数据区:控制类型(01)+目标状态
var dataHex = "01" + state;
var dataLen = dataHex.length() / 2; // 数据长度(字节数)
var cmdCode = "03"; // 控制指令命令码
// 拼接完整报文(无校验和)
var frame = "A5A5" +
deviceId +
cmdCode +
Integer.toHexString(dataLen) + // 数据长度(1位16进制)
dataHex +
"5A5A";
return frame.toUpperCase(); // 转为大写16进制
}
return ""; // 不支持的指令
};
//预解码,得到deviceId
//return preDecode("A5A5000101070105DC08F004B05A5A")
//属性上报报文
// return decode('A5A5000101070105DC08F004B07A5A5A');
//过载事件报文
// return decode("A5A5000102030104B0F35A5A")
// return encode('{"deviceId": "0001","function": "switch","data": { "state": "01" }}')
// return encode('{"messageType":"FUNCTIONS","function":"switch","data":{"deviceId":"00010107","state":"01"}}')
- 试一下断点

4、部署上线
- 部署上线
