涂鸦 IoT 开发平台产品开发生态设备接入最佳实践自定义协议设备接入(数据解析)

自定义协议设备接入(数据解析)

更新时间:2023-02-17 03:11:21下载pdf

本文档提供 TuyaLink 设备接入中数据解析的示例。

阅读此篇文档前,建议先查看 数据解析

基本介绍

结合实际应用需求,本文档为开发者提供一份数据解析脚本参考。您可以根据以下示例学习应用。

设备端开发

请参考 自定义透传协议

脚本模板

脚本模板是平台默认提供的基本函数代码块,包含上行、下行的函数定义。


/**
* 
* 当设备上报数据到云端时本函数将设备的自定义协议数据转换为tylink协议json格式。
* @param {array} rawData 设备原始数据的字节数组,示例:[0x10,0xFF,0x01,0x02]。
* @returns {object} 返回转换之后的结果对象,该对象应包含如下属性:
* msgType:转换之后的tylink协议消息类型;
* payload:转换之后的tylink协议消息主体;
* 返回结果示例:
* {
*     "msgType":"thing.property.report",
*     "payload":{
*         "msgId":"100001",
*         "time":1636625851737,
*         "data":{
*             "color":{
*                 "value":"RED",
*                 "time":1636625851737
*             }
*         }
*     }
* }
*/
 function rawDataToTyLink(rawData) {
   

 
 }



/**
* 
* 当云端下发数据到设备时本函数将tylink协议json格式转换为设备自定义格式。
* @param {object} tylinkData 云端下发的tylink协议数据对象,该对象应包含如下属性:
* msgType:当前下发的tylink协议消息类型;
* payload:当前下发的tylink协议消息主体;
* 示例:
* {
*     "msgType":"thing.property.set",
*     "payload":{
*         "msgId":"1000324923",
*         "time":1636625851737,
*         "data":{"color":"BLUE"}
*     }
* }
* @returns {array} 返回转换之后的设备协议数据字节数组,实例:[0x12,0xEF,0x03,0x12]。
*/
function tyLinkToRawData(tylinkData) {
  
 
 
}


脚本示例

示例 1:智能彩灯

  1. 创建产品。
    产品创建页,选择 光源 产品品类,来创建 智能彩灯 产品,智能化方式选择 设备生态接入,产品信息选择数据协议为 自定义透传。创建详情见下图。关于创建产品,详情可查看 创建产品

    自定义协议设备接入(数据解析)

  2. 功能定义。
    功能定义 页签中,对产品进行功能定义,完成基本设备模型设计。
    关于功能定义详情,可查看 功能定义
    自定义协议设备接入(数据解析)

  3. 脚本编写。
    可参考下方功能代码,拷贝至 脚本调试 框中。

    /**
    *
    * 以下是一个智能彩灯设备的自定义协议解析示例:
    *
    * ## 彩灯设备模型定义
    * {
    *    "code":"0asdlk234234",
    *    "name":"智能彩灯",
    *    "services":[
    *        {
    *            "properties":[
    *                {"abilityId":1, "code":"color",      "name":"颜色", "typeSpec":{"type":"enum", "range":[ "RED", "GREEN", "BLUE" ] }},
    *                {"abilityId":2, "code":"brightness", "name":"亮度", "typeSpec":{"type":"value", "min":0, "max":100, "step":1, "scale":0}},
    *                {"abilityId":3, "code":"switch",     "name":"开关", "typeSpec":{"type":"bool"}}
    *            ]
    *        }
    *    ]
    * }
    *
    * ## 彩灯设备协议格式定义
    * +-----+---+---+---+---+---+---+---+---+---+---+---+---+-----+---+---+---+
    * |  \  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 |  4  | 5 | 6 | 7 |
    * +-----+---+---+---+---+---+---+---+---+---+---+---+---+-----+---+---+---+
    * |  0  |    version    |      cmd      |             code                |
    * +-----+---------------+---------------+---------------+-----+---+---+---+
    * |  2  |                          property id                            |
    * +-----+-----------------------------------------------------------------+
    * |  4  |                          property value                         |
    * +-----+-----------------------------------------------------------------+
    *
    **/
    
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~tylink协议常量~~~~~~~~~~~~~~~~~~~~~~~~~//
    var MSG_PROPERTY_SET 		= "thing.property.set";  		 
    var MSG_PROPERTY_REPORT 	= "thing.property.report"; 		 	
    //~~~~~~~~~~~~~~~~~~~~~~~~~tylink协议常量~~~~~~~~~~~~~~~~~~~~~~~~~//
    
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~自定义协议常量~~~~~~~~~~~~~~~~~~~~~~~~~//
    var VERSION 				= 0x1;  // 协议版本
    var CMD_TYPE_SET 			= 0x1;	// 属性下发
    var CMD_TYPE_REPORT 		= 0x2;	// 属性上报
    
    var PROPERTY_COLOR		= 0x1;  // 颜色属性标识
    var PROPERTY_BRIGHTNESS = 0x2;	// 亮度属性标识
    var PROPERTY_SWITCH		= 0x3;  // 开关属性标识
    
    var CODE_SUCCESS 	= 0;
    var CODE_ERROR 		= 1;
    
    var COLOR_TO_CODE = {"RED":0, "GREEN":1, "BLUE":2};  
    var CODE_TO_COLOR = {0:"RED", 1:"GREEN", 2:"BLUE"};  
    //~~~~~~~~~~~~~~~~~~~~~~~~~自定义协议常量~~~~~~~~~~~~~~~~~~~~~~~~~//
    
    
    /**
    * 	示例1:下发颜色属性设置消息
    *	传入参数:
    *   	{"msgType":"thing.property.set", "payload":{"msgId":"15", "data":{"color":"BLUE"}}}
    *   输出结果:
    *  		[0x11,0x00,0x00,0x01,0x00,0x02]
    */
    function tyLinkToRawData(json) {
    	// 根据消息类型分别处理编码逻辑
    	if(json.msgType == MSG_PROPERTY_SET) {
    		return encodePropertySet(json.payload);
    	}
    }
    
    
    /**
    * 	示例1:上报亮度属性数据
    *	传入参数:
    *		[0x12,0x00,0x00,0x02,0x00,0x32]
    *   输出结果:
    *  		{"msgType":"thing.property.report","payload":{"data":{"brightness":{"value":50}}}}
    *	
    */
    function rawDataToTyLink(bytes) {
    	var packet = decode(bytes);
    
    	// 根据命令类型分别处理解码逻辑
    	if(packet.cmd == CMD_TYPE_REPORT) {
    		return decodePropertyReport(packet);
    	} 
    }
    
    
    
    /** 编码属性设置消息 */
    function encodePropertySet(json) {
    	var data    = json.data;
    
    	if(data.color !== undefined) {
    		return encode(CMD_TYPE_SET, 0, PROPERTY_COLOR, COLOR_TO_CODE[data.color]);
    	} else if (data.brightness !== undefined) {
    		return encode(CMD_TYPE_SET, 0, PROPERTY_BRIGHTNESS, data.brightness);
    	} else if (data.switch !== undefined) {
    		return encode(CMD_TYPE_SET, 0, PROPERTY_SWITCH, data.switch ? 1 : 0);
    	} 
    }
    
    /** 编码自定义数据包 */
    function encode(cmd, code, proId, proVal) {
    	var data = [];
    	// 4位版本+4位命令类型
    	data = data.concat(encodeUint8(((VERSION << 4) & 0xF0) | (cmd & 0xF)));
    	// 8位code
    	data = data.concat(encodeUint8(code));
    	if(proId != null) {
    		// 16位属性标识
    		data = data.concat(encodeInt16(proId));
    		// 16位属性值
    		data = data.concat(encodeInt16(proVal));
    	}
    	return data;
    }
    
    
    
    /** 解码属性上报消息 */
    function decodePropertyReport(packet) {
    	var proId 	= packet.proId;
    	var proVal 	= packet.proVal;
    	
    	var data = {"msgType": MSG_PROPERTY_REPORT,
    				"payload":{"data":{}}}
    	var payload = data.payload; 
    	if(proId == PROPERTY_COLOR) {
    		payload.data.color = {"value": CODE_TO_COLOR[proVal]};
    	} else if(proId == PROPERTY_BRIGHTNESS) {
    		payload.data.brightness = {"value": proVal};
    	} else if(proId == PROPERTY_SWITCH) {
    		payload.data.switch = {"value": proVal == 1};
    	}
    	return data;
    }
    
    /** 解码自定义数据包 */
    function decode(bytes) {
    	var uint8RawData = new Uint8Array(bytes);
    	var dataView 	 = new DataView(uint8RawData.buffer, 0);
    	var packet		 = {};
    
    	var header   	= dataView.getInt16(0);
    	packet.version 	= (header & 0xF000) >> 12;
    	packet.cmd 		= (header & 0x0F00) >> 8;
    	packet.code 	= (header & 0x00FF);
    
    	if(bytes.length > 2) {
    		packet.proId = dataView.getInt16(2);
    	}
    	if(bytes.length > 4) {
    		packet.proVal = dataView.getInt16(4);
    	}
    	return packet;
    }
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~实用工具方法~~~~~~~~~~~~~~~~~~~~~~~~~//
    
    function encodeUint8(value) {
    	var uint8Array = new Uint8Array(1);
    	var dv = new DataView(uint8Array.buffer, 0);
    	dv.setUint8(0, value);
    	return [].slice.call(uint8Array);
    }
    
    function encodeInt16(value) {
    	var uint8Array = new Uint8Array(2);
    	var dv = new DataView(uint8Array.buffer, 0);
    	dv.setInt16(0, value);
    	return [].slice.call(uint8Array);
    }
    function encodeInt32(value) {
    	var uint8Array = new Uint8Array(4);
    	var dv = new DataView(uint8Array.buffer, 0);
    	dv.setInt32(0, value);
    	return [].slice.call(uint8Array);
    }
    
    
  4. 调试脚本。

    1. 脚本调试 框中输入脚本。
    2. 在下拉框中分别选择 云端下发数据设备上报数据 两种模拟数据输入方式,进行脚本验证。
    3. (可选)单击 保存 保存输入的脚本。
    4. 脚本确认完毕后,单击 执行
    5. 在右侧 执行结果 框中查看验证结果,验证正确后单击 发布为正式版本
      自定义协议设备接入(数据解析)
  5. 发布为正式版本。
    填写发布说明,版本发布成功后,当前产品所有在线设备会通过数据解析进行数据上报和处理。
    自定义协议设备接入(数据解析)

示例2:智能摄像头

  1. 创建产品。
    产品创建页 选择“低功耗摄像机”产品品类来创建“智能摄像头“产品,选择数据协议为自定义透传。创建详情见下图。
    关于创建产品,详情可查看创建产品
    自定义协议设备接入(数据解析)

  2. 功能定义。
    功能定义 页签中,对产品进行功能定义,完成基本设备模型设计。
    关于功能定义,详情可查看 功能定义
    自定义协议设备接入(数据解析)

  3. 脚本编写。
    可参考下方功能代码,拷贝至 脚本调试 框中。

    /**
    *
    * 以下提供一个包含属性、事件、动作的智能摄像头示例:
    * ## 智能摄像头设备模型
    * {
    *     "code":"0asdlk234234",
    *     "name":"智能摄像头",
    *     "services":[
    *         {
    *             "properties":[
    *                 {"abilityId":1, "code":"nightvision","name":"红外夜视", "accessMode":"rw", "typeSpec":{"type":"enum", "range":[ "OFF", "ON", "AUTO" ] }}
    *             ],
    *             "events":[
    *                 {"abilityId":2, "code":"fault",     "name":"故障事件", "outputParams":[{"code":"faultNumber", "name":"故障编号", "typeSpec":{"type":"value", "min":0, "max":20, "step":1, "scale":0}} }]}
    *             ],
    *             "actions":[
    *             	  {"abilityId":3, "code":"ptzcontrol",  "name":"云台转动", "inputParams":[{"code":"direction", "typeSpec":{"type":"enum", "range":[ "UP", "DOWN", "LEFT","RIGHT" ]}}]
    *             ]
    *         }
    *     ]
    * }
    * 
    * ## 智能摄像头协议以utf8字符串方式编码,每个协议字段之间使用","分割,其格式如下:
    * <version>,<cmd>,<sub cmd>,<code>,<ack>,<msgId>,<timestamp>,<cmd args>
    **/
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~tylink协议常量~~~~~~~~~~~~~~~~~~~~~~~~~//
    var MSG_PROPERTY_SET 		= "thing.property.set";  		 
    var MSG_PROPERTY_SET_RES	= "thing.property.set.response"; 	
    var MSG_PROPERTY_REPORT 	= "thing.property.report"; 		 	
    var MSG_PROPERTY_REPORT_RES = "thing.property.report.response"; 
    var MSG_ACTION_EXECUTE 		= "thing.action.execute"; 		 	
    var MSG_ACTION_EXECUTE_RES 	= "thing.action.execute.response";
    var MSG_EVENT_TRIGGER 		= "thing.event.trigger"; 		 	
    var MSG_EVENT_TRIGGER_RES 	= "thing.event.trigger.response";
    //~~~~~~~~~~~~~~~~~~~~~~~~~tylink协议常量~~~~~~~~~~~~~~~~~~~~~~~~~//
    
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~自定义协议常量~~~~~~~~~~~~~~~~~~~~~~~~~//
    var VERSION 				= 0x1;  // 协议版本
    var CMD_PROPERTY_SET 		= 0x1;  // 属性设置		 
    var CMD_PROPERTY_SET_RES	= 0x2;  // 属性设置响应	
    var CMD_PROPERTY_REPORT 	= 0x3;  // 属性上报	 	
    var CMD_PROPERTY_REPORT_RES = 0x4;  // 属性上报响应
    var CMD_ACTION_EXECUTE 		= 0x5;  // 动作执行	 	
    var CMD_ACTION_EXECUTE_RES 	= 0x6;  // 动作执行响应
    var CMD_EVENT_TRIGGER 		= 0x7;  // 事件触发	 	
    var CMD_EVENT_TRIGGER_RES 	= 0x8;  // 事件触发响应
    
    var SUB_CMD_NIGHT_VISION	= 0x1;  // 红外夜视功能
    var SUB_CMD_FAULT 			= 0x2;	// 故障上报功能
    var SUB_CMD_PTZ_CONRTOLR  	= 0x3;  // 云台转动功能
    var SEPARATOR				= ','; 	// 字段分割符
    //~~~~~~~~~~~~~~~~~~~~~~~~~自定义协议常量~~~~~~~~~~~~~~~~~~~~~~~~~//
    
    /**
    * 	示例1:下发红外夜视设置消息
    *	传入参数:
    *   	{"msgType":"thing.property.set", "payload":{"msgId":"1001", "sys":{"ack":1}, "time":1637114892287, "data":{"nightvision":"ON"}}}
    *   输出结果:
    *  		[0x31,0x2c,0x31,0x2c,0x31,0x2c,0x30,0x2c,0x31,0x2c,0x31,0x30,0x30,0x31,0x2c,0x31,0x36,0x33,0x37,0x31,0x31,0x34,0x38,0x39,0x32,0x32,0x38,0x37,0x2c,0x4f,0x4e]
    *
    * 	示例2:下发属性上报响应消息
    *	传入参数:
    *   	{"msgType":"thing.property.report.response", "payload":{"msgId":"1994", "time":1637114892287, "code":1000}}
    *   输出结果:
    *  		[0x31,0x2c,0x34,0x2c,0x30,0x2c,0x31,0x30,0x30,0x30,0x2c,0x30,0x2c,0x31,0x39,0x39,0x34,0x2c,0x31,0x36,0x33,0x37,0x31,0x31,0x34,0x38,0x39,0x32,0x32,0x38,0x37]
    *
    * 	示例3:下发动作执行消息
    *	传入参数:
    *   	{"msgType":"thing.action.execute", "payload":{"msgId":"2011", "time":1637114892287, "data":{"actionCode":"ptzcontrol", "inputParams":{"direction":"UP"}}}}
    *   输出结果:
    *  		[0x31,0x2c,0x35,0x2c,0x33,0x2c,0x30,0x2c,0x31,0x2c,0x32,0x30,0x31,0x31,0x2c,0x31,0x36,0x33,0x37,0x31,0x31,0x34,0x38,0x39,0x32,0x32,0x38,0x37,0x2c,0x55,0x50]
    *
    * 	示例4:下发事件上报响应消息
    *	传入参数:
    *   	{"msgType":"thing.event.trigger.response", "payload":{"msgId":"2028","time":1637114892289, "code":0}}
    *   输出结果:
    *  		[0x31,0x2c,0x38,0x2c,0x30,0x2c,0x30,0x2c,0x30,0x2c,0x32,0x30,0x32,0x38,0x2c,0x31,0x36,0x33,0x37,0x31,0x31,0x34,0x38,0x39,0x32,0x32,0x38,0x39]
    */
    function tyLinkToRawData(json) {
    	if(json.msgType == MSG_PROPERTY_SET) {
    		// 编码属性设置消息
    		return encodePropertySet(json.payload);
    	} else if(json.msgType == MSG_PROPERTY_REPORT_RES) {
    		// 编码属性上报响应消息
    		return encodeResponse(CMD_PROPERTY_REPORT_RES, json.payload);
    	} else if(json.msgType == MSG_ACTION_EXECUTE) {
    		// 编码动作执行消息
    		return encodeActionExecute(json.payload);
    	} else if(json.msgType == MSG_EVENT_TRIGGER_RES) {
    		// 编码事件触发响应消息
    		return encodeResponse(CMD_EVENT_TRIGGER_RES, json.payload);
    	}
    }
    
    
    
    /**
    * 	示例1:上报红外夜视属性数据
    *	传入参数:
    		[0x31,0x2c,0x33,0x2c,0x31,0x2c,0x30,0x2c,0x31,0x2c,0x31,0x34,0x2c,0x31,0x36,0x33,0x37,0x31,0x31,0x34,0x38,0x39,0x32,0x32,0x38,0x37,0x2c,0x4f,0x4e] 
    *   输出结果:
    *  		{"msgType":"thing.property.report","payload":{"msgId":"14", "time":1637114892287, "sys":{"ack":1}, "data":{"nightvision":{"value":"ON","time": 1637114892287}}}}
    *
    * 	示例2:上报属性设置响应消息
    *	传入参数:
    *   	[0x31,0x2c,0x32,0x2c,0x30,0x2c,0x30,0x2c,0x30,0x2c,0x31,0x35,0x2c,0x31,0x36,0x33,0x37,0x31,0x31,0x34,0x38,0x39,0x32,0x32,0x38,0x37]
    *   输出结果:
    *		{"msgType":"thing.property.set.response", "payload":{"msgId":"15",  "time":1637114892287, "code":0}}
    *  
    * 	示例3:上报设备故障事件
    *	传入参数:
    *   	[0x31,0x2c,0x37,0x2c,0x32,0x2c,0x30,0x2c,0x31,0x2c,0x31,0x36,0x2c,0x31,0x36,0x33,0x37,0x31,0x31,0x34,0x38,0x39,0x32,0x32,0x38,0x37,0x2c,0x35]
    *   输出结果:
    *		{"msgType":"thing.event.trigger", "payload":{"msgId":"16",  "time":1637114892287,"sys":{"ack":1}, "data":{"eventCode":"fault", "outputParams":{"faultNumber":5}}}}
    *  
    * 	示例4:上报设备动作结果
    *	传入参数:
    *   	[0x31,0x2c,0x36,0x2c,0x30,0x2c,0x30,0x2c,0x30,0x2c,0x31,0x37,0x2c,0x31,0x36,0x33,0x37,0x31,0x31,0x34,0x38,0x39,0x32,0x32,0x38,0x37]
    *   输出结果:
    *		{"msgType":"thing.action.execute.response", "payload":{"msgId":"17",  "time":1637114892287, "code":0}}
    * 
    */
    function rawDataToTyLink(bytes) {
    	var packet = decode(bytes);
    	if(packet.cmd == CMD_PROPERTY_REPORT) {
    		// 解码属性上报数据
    		return decodePropertyReport(packet);
    	} else if(packet.cmd == CMD_PROPERTY_SET_RES){
    		// 解码属性设置响应数据
    		return decodePropertySetResponse(packet);
    	} else if(packet.cmd == CMD_EVENT_TRIGGER){
    		// 解码事件触发数据
    		return decodeEventTrigger(packet);
    	} else if(packet.cmd == CMD_ACTION_EXECUTE_RES){
    		// 解码动作执行数据
    		return decodeActionExecuteRes(packet);
    	}
    }
    
    
    
    /** 编码属性设置消息 */
    function encodePropertySet(json) {
    	var data = json.data;
    	var sys = json.sys;
    	if(data.nightvision !== undefined) {
    		return encode(CMD_PROPERTY_SET, SUB_CMD_NIGHT_VISION, 0, (sys && sys.ack) ? 1 : 0, json.msgId, json.time, data.nightvision);
    	} 
    }
    
    /** 编码属性上报响应消息 */
    function encodeResponse(cmdType, json) {
    	return encode(cmdType, 0, json.code, 0, json.msgId, json.time);
    }
    
    /** 编码动作执行消息 */
    function encodeActionExecute(json) {
    	var data = json.data;
    	if(data.actionCode == "ptzcontrol") {
    		return encode(CMD_ACTION_EXECUTE, SUB_CMD_PTZ_CONRTOLR, 0, 1, json.msgId, json.time, data.inputParams.direction);
    	}
    }
    
    /** 编码自定义数据包 */
    function encode(cmd, subCmd, code, ack, msgId, timestamp, cmdArgs) {
    	var line = [VERSION].concat([].slice.call(arguments)).join(SEPARATOR);
    	return encodeUtf8(line);
    }
    
    
    /** 解码属性上报消息 */
    function decodePropertyReport(packet) {
    	var msgId 	= packet.msgId;
    	var subCmd 	= packet.subCmd;
    	var args 	= packet.args;
    	var time	= packet.timestamp;
    	
    	var result = {"msgType": MSG_PROPERTY_REPORT,
    				"payload":{"msgId": msgId,
    						"time":time,
    						"data":{}, 
    						"sys":{"ack":packet.ack}}}
    	var params = result.payload.data; 
    	if(subCmd == SUB_CMD_NIGHT_VISION) {
    		params.nightvision = {"value": args, "time": time};
    	}
    	return result;
    }
    
    /** 解码属性设置响应消息  */
    function decodePropertySetResponse(packet) {
    	return {
    			"msgType": MSG_PROPERTY_SET_RES, 
    			"payload":{"msgId": packet.msgId, 
    					"time": packet.timestamp,
    					"code": packet.code}
    		};
    }
    
    
    /** 解码事件触发 */
    function decodeEventTrigger(packet) {
    	var msgId 	= packet.msgId;
    	var subCmd 	= packet.subCmd;
    	var args 	= packet.args;
    	var time	= packet.timestamp;
    	
    	var result = {"msgType": MSG_EVENT_TRIGGER,
    				"payload":{"msgId": msgId, 
    						"time":time,
    						"data":{}, 
    						"sys":{"ack":packet.ack}}}
    	var params = result.payload.data; 
    	params.eventTime = time;
    	if(subCmd == SUB_CMD_FAULT) {
    		params.eventCode = "fault";
    		params.outputParams = {"faultNumber": parseInt(args)};
    	}
    	return result;
    }
    
    /** 解码动作执行响应消息  */
    function decodeActionExecuteRes(packet) {
    	return {
    			"msgType": MSG_ACTION_EXECUTE_RES, 
    			"payload":{"msgId": packet.msgId.toString(), 
    						"time":packet.timestamp,
    					"code": packet.code}
    		};
    }
    
    
    /** 解码自定义数据包 */
    function decode(bytes) {
    	var line = decodeUtf8(bytes);
    	var fields = line.split(SEPARATOR);
    	return {
    		"version"	:parseInt(fields[0]),
    		"cmd"		:parseInt(fields[1]),
    		"subCmd"	:parseInt(fields[2]),
    		"code"		:parseInt(fields[3]),
    		"ack"		:fields[4] == "1" ? 1 : 0,
    		"msgId"		:fields[5],
    		"timestamp"	:parseInt(fields[6]),
    		"args"		:fields[7]
    	}
    }
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~实用工具方法~~~~~~~~~~~~~~~~~~~~~~~~~//
    
    function encodeUtf8(text) {
    	const code = encodeURIComponent(text);
    	const bytes = [];
    	for (var i = 0; i < code.length; i++) {
    		const c = code.charAt(i);
    		if (c === '%') {
    			const hex = code.charAt(i + 1) + code.charAt(i + 2);
    			const hexVal = parseInt(hex, 16);
    			bytes.push(hexVal);
    			i += 2;
    		} else bytes.push(c.charCodeAt(0));
    	}
    	return bytes;
    }
    
    function decodeUtf8(bytes) {
    	var encoded = "";
    	for (var i = 0; i < bytes.length; i++) {
    		encoded += '%' + bytes[i].toString(16);
    	}
    	return decodeURIComponent(encoded);
    }
    
    
  4. 脚本调试。

    1. 脚本调试 框中输入脚本。
    2. 在下拉框中分别选择 云端下发数据设备上报数据 两种模拟数据输入方式进行脚本验证。
    3. (可选)单击 保存 保存输入的脚本。
    4. 脚本确认完毕后,单击 执行
    5. 在右侧 执行结果 框中查看验证结果,验证正确后单击 发布为正式版本
      自定义协议设备接入(数据解析)
  5. 发布为正式版本。

    填写发布说明。版本发布成功后,当前产品所有在线设备会通过数据解析进行数据上报和处理。

    自定义协议设备接入(数据解析)

脚本注意事项

  • 编写脚本前,请认真阅读脚本示例说明。
  • 单个脚本文件大小不超过 128 KB。