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

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

更新时间: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。