SOURCE

/*激光测距仪*/
function Decode(fPort, bytes) {
  var obj = {};
  if(fPort ==1){
    //心跳包
    obj.type = 4;
    obj.SensorType = 40;       
    obj.SensorNumberThird = 1;	  	
    obj.name  = "report";  	
    parse_states_data(bytes, obj);
  }else if(fPort ==8){
    // 检测数据
    var rawdata = '';
    for(var i = 0; i < bytes.length; i++) {
        rawdata += bytes[i] + ' ';
    }
    obj.Rawdata = rawdata;
    parse_inspect_data(bytes, obj);
  }
  return obj;
}


/**
 * 检测数据解析
 */
function parse_inspect_data(bytes, obj) {
    var myDate       = new Date();
    var current_time = myDate.toLocaleString();
	var rawdata = ""; 
    // 转成ASCII码
    for(var i = 0; i < bytes.length; i++) {
        var str = hexCharCodeToStr(bytes[i].toString(16));
        rawdata += str;
    }
    console.log("rawdata", rawdata);
    // 正确应答  D=Xm, N#<CR><LF> 
    // 错误应答 E=Y <CR><LF> 
    if(rawdata.length > 0) {
        var first = rawdata.substring(0, 1);
        if(first == 'D') {
            var distance = rawdata.substring(rawdata.indexOf('=') + 1, rawdata.indexOf('m'));
            obj.Value = parseFloat(distance) * 1000;
            obj.Flag = 1;
        }else if(first == 'E') {
            obj.Flag = -1;
        }else {
            obj.Flag = -1;
        }
    }
	obj.SensorType		  = 40;
	obj.SensorNumberThird = 1;
	obj.Timestamp 		  = current_time;
}

// 10进制转16进制
function decTohex(value, length) {
    var number = value.toString(16);
    return (Array(length).join("0") + number).slice(-length);//高位补0
}

// 16进制ASCII码转字符串
function hexCharCodeToStr(hexCharCodeStr) {
    var trimedStr = hexCharCodeStr.trim();
    var rawStr =
        trimedStr.substr(0, 2).toLowerCase() === "0x" ?
        trimedStr.substr(2) :
        trimedStr;
    var len = rawStr.length;
    if (len % 2 !== 0) {
        // alert("Illegal Format ASCII Code!");
        return "";
    }
    var curCharCode;
    var resultStr = [];
    for (var i = 0; i < len; i = i + 2) {
        curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value
        resultStr.push(String.fromCharCode(curCharCode));
    }
    return resultStr.join("");
}

/******************************************************************************/
function parse_states_data(bytes, obj)
{
	var i = 2;    /* bytes数组下标,指向第一个对象编号 */
	var r = 1;    /* 对象解析结果,解析成功返回对象数据长度,否则返回0*/
	while (i < bytes.length) {
		switch (bytes[i]) {
			case 0x02:
				r = obj_02_time_parse(bytes, obj, i);
			break;
			case 0x03:
				r = obj_03_communicate_quality_parse(bytes, obj, i);
			break;
			case 0x04:
				r = obj_04_device_info_parse(bytes, obj, i);
			break;
			case 0x05:
				r = obj_05_run_info_parse(bytes, obj, i);
			break;
			case 0x06:
				r = obj_06_report_interval_parse(bytes, obj, i);
			break;
			case 0x07:
				r = obj_07_deveui_parse(bytes, obj, i);
			break;
			case 0x10:
				r = obj_10_level_parse(bytes, obj, i);
			break;
			case 0x11:
				r = obj_11_pwron_level_parse(bytes, obj, i);
			break;
			case 0x12:
				r = obj_12_warning_status_parse(bytes, obj, i);
			break;
			case 0x13:
				r = obj_13_on_off_parse(bytes, obj, i);
			break;
			case 0x15:
				r = obj_15_adc_parse(bytes, obj, i);
			break;
			case 0x17:
				r = obj_17_battery_voltage_parse(bytes, obj, i);
			break;
			case 0x18:
				r = obj_18_current_acc_flow_parse(bytes, obj, i);
			break;
			case 0x19:
				r = obj_19_day_acc_flow_parse(bytes, obj, i);
			break;
			case 0x20:
				r = obj_20_acrc_parm_parse(bytes, obj, i);
			break;
			case 0x25:
				r = obj_25_pir_status_parse(bytes, obj, i);
			break;
			case 0x26:
				r = obj_26_vibrating_wire_parse(bytes, obj, i);
			break;
			case 0x30:
				r = obj_30_em_parse(bytes, obj, i);
			break;
			case 0x32:
				r = obj_32_temp_humi_parse(bytes, obj, i);
			break;
		}
		if (r > 0) {
			i += (r + 1);   /* r为本次解析对象的数据长度,+1指向下一个对象 */
		} else {
			obj.result = "byte[" + i + "] " + "object " + add0(bytes[i].toString(16), 2) + " decode fail";
			break;
		}
	}
}

/******************************************************************************/
function parse_hca526t_data(bytes, obj)
{
    var myDate       = new Date();
    var current_time = myDate.toLocaleString() 
    var xValue;
    var yValue;
    var temValue;
    var xHex   = IntToHex(bytes[4], 2)  + IntToHex(bytes[5], 2)  + IntToHex(bytes[6], 2) ;
    var yHex   = IntToHex(bytes[7], 2)  + IntToHex(bytes[8], 2)  + IntToHex(bytes[9], 2) ;
    var temHex = IntToHex(bytes[10], 2) + IntToHex(bytes[11], 2) + IntToHex(bytes[12], 2) ;
    
    if(xHex.substring(0, 1) === "0"){//温度最高位为0,正数
        xValue = parseFloat(xHex) *(0.001);
    }else{//最高位为1,负数
      xValue = parseFloat(xHex.substring(1, xHex.length)) *(-1*0.001);
    }
     if(yHex.substring(0, 1) === "0"){//温度最高位为0,正数
        yValue = parseFloat(yHex) *(0.001);
    }else{//最高位为1,负数
      yValue = parseFloat(yHex.substring(1, xHex.length)) *(-1*0.001);
    }
      if(temHex.substring(0, 1) === "0"){//温度最高位为0,正数
        temValue = parseFloat(temHex) *(0.001);
    }else{//最高位为1,负数
      temValue = parseFloat(temHex.substring(1, xHex.length)) *(-1*0.001);
    }  
	
	obj.Flag 			  = 1;
	obj.SensorType		  = 3;
	obj.SensorNumberThird = bytes[2];
	obj.Timestamp 		  = current_time;
	obj.X				  = parseFloat( xValue.toFixed(3));
	obj.Y 				  = parseFloat(yValue.toFixed(3));
	obj.Temperature		  = parseFloat(temValue.toFixed(3));	
}

/******************************************************************************/
function obj_02_time_parse(bytes, obj, i)
{
        /* bytes长度减去已解析数据长度i,再减去 1 byte对象编号,剩下的数据长度是否符合当前对象的数据长度 */
        if ((bytes.length - i - 1) < 4) { 
                return 0;
        } else {
                obj.timestamp  = parseInt((add0(bytes[i+1].toString(16), 2) + 
                                                               add0(bytes[i+2].toString(16), 2) + 
                                                               add0(bytes[i+3].toString(16), 2) + 
                                                               add0(bytes[i+4].toString(16), 2)), 16);
            /* 时间戳为UTC时间,单位为秒,Date()要求输入参数为毫秒,转本地时间字符串 */
            obj.local_time = new Date(obj.timestamp  * 1000).toLocaleString();
                return 4;
        }
}

function obj_03_communicate_quality_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 4) {
		return 0;
	} else {
		obj.rssi = toSignInt(add0(bytes[i+1].toString(16), 2) + 
							 add0(bytes[i+2].toString(16), 2));
		obj.snr  = toSignInt(add0(bytes[i+3].toString(16), 2) + 
							 add0(bytes[i+4].toString(16), 2)) / 10;
		return 4;
	}
}

function obj_04_device_info_parse(bytes, obj, i)
{
	var obj_dev_info   = {};
	var array_dev_type = ["ZigBee红外空调遥控器", "LoRa红外空调遥控器", "NB-IoT红外空调遥控器", 
					      "LoRa路灯控制器", "LoRa电测执行器", "LoRa串口协议转换器", 
					      "LoRa人体红外感应器", "LoRa温湿度传感器", "LoRa环境传感器", 
						  "LoRa水表", "NB-IoT电测执行器"];
	
	if ((bytes.length - i - 1) < 12) {
		return 0;
	} else {
		obj_dev_info.dev_type = array_dev_type[i+1];
		obj_dev_info.hwver    = "v" + bytes[i+5] + "." + bytes[i+6] + "." + bytes[i+7];
		obj_dev_info.swver    = "v" + bytes[i+9] + "." + bytes[i+10] + "." + bytes[i+11];
		obj.device_info       = obj_dev_info;
		return 12;
	}
}

function obj_05_run_info_parse(bytes, obj, i)
{
	var obj_run_time = {};
	if ((bytes.length - i - 1) < 12) {
		return 0;
	} else {
	    obj_run_time.run_total = parseInt((add0(bytes[i+1].toString(16), 2)   + 
	    					               add0(bytes[i+2].toString(16), 2)   + 
	    					               add0(bytes[i+3].toString(16), 2)   + 
	    					               add0(bytes[i+4].toString(16), 2)), 16);
	    obj_run_time.on_total  = parseInt((add0(bytes[i+5].toString(16), 2)   + 
	    					               add0(bytes[i+6].toString(16), 2)   + 
	    					               add0(bytes[i+7].toString(16), 2)   + 
	    					               add0(bytes[i+8].toString(16), 2)), 16);
	    obj_run_time.on_24h    = parseInt((add0(bytes[i+9].toString(16), 2)   + 
	    					               add0(bytes[i+10].toString(16), 2)  + 
	    					               add0(bytes[i+11].toString(16), 2)  + 
	    					               add0(bytes[i+12].toString(16), 2)), 16);
	    obj.run_time           = obj_run_time;
		return 12;
	}
}

function obj_06_report_interval_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 4) { 
		return 0;
	} else {
		obj.report_interval  = parseInt((add0(bytes[i+1].toString(16), 2) + 
	    						         add0(bytes[i+2].toString(16), 2) + 
	    						         add0(bytes[i+3].toString(16), 2) + 
	    						         add0(bytes[i+4].toString(16), 2)), 16);
		return 4;
	}
}

function obj_07_deveui_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 8) { 
		return 0;
	} else {
		obj.deveui = add0(bytes[i+1].toString(16), 2) + 
	    			 add0(bytes[i+2].toString(16), 2) + 
	    			 add0(bytes[i+3].toString(16), 2) + 
	    			 add0(bytes[i+4].toString(16), 2) + 
	    			 add0(bytes[i+5].toString(16), 2) + 
	    			 add0(bytes[i+6].toString(16), 2) + 
	    			 add0(bytes[i+7].toString(16), 2) +
	    			 add0(bytes[i+8].toString(16), 2);
		return 8;
	}
}

function obj_10_level_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 1) {
		return 0;
	} else {
	    obj.level = parseInt((add0(bytes[i+1].toString(16), 2)), 16);
		return 1;
	}
}

function obj_11_pwron_level_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 1) {
		return 0;
	} else {
	    obj.pwron_level = parseInt((add0(bytes[i+1].toString(16), 2)), 16);
		return 1;
	}
}

function obj_12_warning_status_parse(bytes, obj, i)
{	
	
	
	if ((bytes.length - i - 1) < 1) {
		return 0;
	} else {
		if (obj.warn) {
			obj.warn.push(warn_type_get(bytes[i+1]));
		} else {
			obj.warn = [];
			obj.warn.push(warn_type_get(bytes[i+1]));
		}
		return 1;
	}
}

function obj_13_on_off_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 1) {
		return 0;
	} else {
	    if (bytes[i+1] > 0) {
	    	obj.relay = "on";
	    } else {
	    	obj.relay = "off";
	    }
		return 1;
	}
}

function obj_15_adc_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 4) {
		return 0;
	} else {
	    obj.adc = parseInt((add0(bytes[i+1].toString(16), 2) + 
	    					add0(bytes[i+2].toString(16), 2) + 
	    					add0(bytes[i+3].toString(16), 2) + 
	    					add0(bytes[i+4].toString(16), 2)), 16) / 1000;
		return 4;
	}
}

function obj_17_battery_voltage_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 3) {
		return 0;
	} else {
	    obj.bat_percent = parseInt((add0(bytes[i+1].toString(16), 2)), 16);
	    obj.bat_vol     = parseInt((add0(bytes[i+2].toString(16), 2) + 
	    							add0(bytes[i+3].toString(16), 2)), 16) / 1000;
		return 3;
	}
}

function obj_18_current_acc_flow_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 4) {
		return 0;
	} else {
	    obj.cur_acc_flow = parseInt((add0(bytes[i+1].toString(16), 2) + 
	    							 add0(bytes[i+2].toString(16), 2) + 
	    							 add0(bytes[i+3].toString(16), 2) + 
	    							 add0(bytes[i+4].toString(16), 2)), 16) / 100;
	    return 4;
	}
}

function obj_19_day_acc_flow_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 4) {
		return 0;
	} else {
	    obj.day_acc_flow = parseInt((add0(bytes[i+1].toString(16), 2) + 
	    							 add0(bytes[i+2].toString(16), 2) + 
	    							 add0(bytes[i+3].toString(16), 2) + 
	    							 add0(bytes[i+4].toString(16), 2)), 16) / 100;
	    return 4;
	}
}

function obj_20_acrc_parm_parse(bytes, obj, i)
{
	var obj_ac_params = {};
	
	if ((bytes.length - i - 1) < 6) {
		return 0;
	} else {
	    obj_ac_params.temp  = parseInt((add0(bytes[i+1].toString(16), 2)   + 
	    					            add0(bytes[i+2].toString(16), 2)), 16) / 10;
	    obj_ac_params.mode  = ac_params_mode_parse(bytes[i+3]);
	    obj_ac_params.speed = ac_params_wind_speed_parse(bytes[i+4]);
	    obj_ac_params.vwind = ac_params_wind_swing_parse(bytes[i+5]);
	    obj_ac_params.hwind = ac_params_wind_swing_parse(bytes[i+6]);
	    obj.ac_params       = obj_ac_params;
		return 6;
	}
}

function obj_25_pir_status_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 1) {
		return 0;
	} else {
		obj.pir = bytes[i+1];
		return 1;
	}
}

function obj_26_vibrating_wire_parse(bytes, obj, i)
{
	var obj_vibrating_wire = {};
	if ((bytes.length - i - 1) < 6) {
		return 0;
	} else {
	    obj_vibrating_wire.temp = toSignInt(add0(bytes[i+1].toString(16), 2) + 
	                                        add0(bytes[i+2].toString(16), 2)) / 10;
	    obj_vibrating_wire.freq = toSignInt(add0(bytes[i+3].toString(16), 2) + 
	                                        add0(bytes[i+4].toString(16), 2) + 
	                                        add0(bytes[i+5].toString(16), 2) + 
	                                        add0(bytes[i+6].toString(16), 2)) / 10;
											
	    obj.vibrating_wire      = obj_vibrating_wire;
		return 6;
	}
}

function obj_30_em_parse(bytes, obj, i)
{
	var obj_em = {};
	
	if ((bytes.length - i - 1) < 20) {
		return 0;
	} else {
	    obj_em.u  = parseInt((add0(bytes[i+1].toString(16), 2)   + 
	    					  add0(bytes[i+2].toString(16), 2)   + 
	    					  add0(bytes[i+3].toString(16), 2)   + 
	    					  add0(bytes[i+4].toString(16), 2)), 16) / 100;
	    obj_em.i  = parseInt((add0(bytes[i+5].toString(16), 2)   + 
	    					  add0(bytes[i+6].toString(16), 2)   + 
	    					  add0(bytes[i+7].toString(16), 2)   + 
	    					  add0(bytes[i+8].toString(16), 2)), 16) / 1000;
	    obj_em.p  = parseInt((add0(bytes[i+9].toString(16), 2)   + 
	    					  add0(bytes[i+10].toString(16), 2)  + 
	    					  add0(bytes[i+11].toString(16), 2)  + 
	    					  add0(bytes[i+12].toString(16), 2)), 16) / 100;
	    obj_em.pf = parseInt((add0(bytes[i+13].toString(16), 2)  + 
	    					  add0(bytes[i+14].toString(16), 2)), 16) / 1000;
	    obj_em.f  = parseInt((add0(bytes[i+15].toString(16), 2)  + 
	    					  add0(bytes[i+16].toString(16), 2)), 16) / 100;
	    obj_em.e  = parseInt((add0(bytes[i+17].toString(16), 2)  + 
	    					  add0(bytes[i+18].toString(16), 2)  + 
	    					  add0(bytes[i+19].toString(16), 2)  + 
	    					  add0(bytes[i+20].toString(16), 2)), 16) / 100;
	    obj.em    = obj_em;
		return 20;
	}
}

function obj_32_temp_humi_parse(bytes, obj, i)
{
	if ((bytes.length - i - 1) < 4) {
		return 0;
	} else {
	    obj.temp = toSignInt(add0(bytes[i+1].toString(16), 2) + 
	                         add0(bytes[i+2].toString(16), 2)) / 10;
	    obj.humi = toSignInt(add0(bytes[i+3].toString(16), 2) + 
	                         add0(bytes[i+4].toString(16), 2)) / 10;
		return 4;
	}
}

/******************************************************************************/
/*
 * 警报状态取值	|  说明
 * -------------|-----------------------------------------------
 * 0x00	        |  ok(正常)
 * 0x01	        |  over-cur(过流)
 * 0x02	        |  no-cur(断路)
 * 0x03	        |  relay-fault(继电器故障)
 * 0x04	        |  over-vol(过压)
 * 0x05	        |  em-fault(电能测量芯片故障)
 * 0x06	        |  ertc-fault(外置RTC芯片故障)
 * 0x07	        |  wmeter-fault(水表传感器故障)
 * 0x08	        |  eflash-fault(外置Flash芯片故障)
 * 0x09	        |  vw-fault(振弦传感器故障)
 * 0x0a-0x0f	|  保留
 * 0x10	        |  temp-humi-fault(温湿度传感器故障)
 * 0x11	        |  temp-oulimit(温度超过上限)
 * 0x12	        |  temp-bllimit(温度低于下限)
 * 0x13	        |  humi-oulimit(湿度超过上限)
 * 0x14	        |  humi-bllimit(湿度低于下限)
 * 0x15-0xff	|  保留
 */

function warn_type_get (data)
{
	var warn_type;
	
	switch (data) {
	case 0x00:
		warn_type = "ok";
	break;
	case 0x01:
		warn_type = "over-cur";
	break;
	case 0x02:
		warn_type = "no-cur";
	break;
	case 0x03:
		warn_type = "relay-fault";
	break;
	case 0x04:
		warn_type = "over-vol";
	break;
	case 0x05:
		warn_type = "em-fault";
	break;
	case 0x06:
		warn_type = "ertc-fault";
	break;	
	case 0x07:
		warn_type = "wmeter-fault";
	break;	
	case 0x08:
		warn_type = "eflash-fault";
	break;
	case 0x09:
		warn_type = "vw-fault";
	break;
	case 0x10:
		warn_type = "temp-humi-fault";
	break;	
	case 0x11:
		warn_type = "temp-oulimit";
	break;	
	case 0x12:
		warn_type = "temp-bllimit";
	break;	
	case 0x13:
		warn_type = "humi-oulimit";
	break;	
	case 0x14:
		warn_type = "humi-bllimit";
	break;
	default:
		warn_type = "unkonw";
	break;
	}
	return warn_type;
}

/******************************************************************************************************/
function ac_params_mode_parse(n)
{
	var ac_mode = ["power_off", "auto", "cool", "heat", "blow", "dry"];
	
	if (n < ac_mode.length) {
		return ac_mode[n];
	} else {
		return "unkonw";
	}
}

function ac_params_wind_speed_parse(n)
{
	var ac_wind_speed = ["auto", "low", "mid", "high"];
	
	if (n < ac_wind_speed.length) {
		return ac_wind_speed[n];
	} else {
		return "unkonw";
	}
}

function ac_params_wind_swing_parse(n)
{
	if (n > 0) {
		return "on";
	} else {
		return "off";
	}
}

/******************************************************************************/
 /* 补0 */
function add0(str, length)
{
	for (; str.length < length; ){
		str = '0' + str;
	}
	return str;
}

/******************************************************************************/
/* 有符号位数转为10进制数 */
function toSignInt(str)
{
	var tmp;
	var unsign_value;
	var unsign_value_str;
	var unsign_bin_str = "";
	
	var bin_str = parseInt(str, 16).toString(2);
	var bitNum  = str.length * 4;
	
	if (bin_str.length < bitNum) {
		while (bin_str.length < bitNum) {
		  bin_str = "0" + bin_str;
		}
	}
	 
	if (bin_str.substring(0, 1) == "0") {
		tmp = parseInt(bin_str, 2);
		return tmp;
	} else {
		unsign_value     = parseInt(bin_str, 2) - 1;
		unsign_value_str = unsign_value.toString(2);
		unsign_bin_str   = unsign_value_str.substring(1, bitNum);
		unsign_bin_str   = unsign_bin_str.replace(/0/g, "z");
		unsign_bin_str   = unsign_bin_str.replace(/1/g, "0");
		unsign_bin_str   = unsign_bin_str.replace(/z/g, "1");
		tmp              = parseInt(-unsign_bin_str, 2);
	 
		return tmp;
	  }
}

function IntToHex(value, length) {
    var number = value.toString(16);
    return (Array(length).join("0") + number).slice(-length);//高位补0
}



function test(value) {
    var arr = value.split(" ");
    var result = '';
    for(var  i = 0; i < arr.length; i++) {
        result += "'" + arr[i] + "'" + ","; 
    }
    return result;
}

var a = '44 3D 31 2E 32 33 34 6D 2C 35 30 30 23 3C 43 52 3E 3C 4C 46 3E';
var bytes = ['44','3D','31','2E','32','33','34','6D','2C','35','30','30','23','3C','43','52','3E','3C','4C','46','3E'];
var bytes2 = [68,61,50,46,52,50,55,109,44,54,51,50,35,13,10];
var aa = {};
// parse_inspect_data(bytes, aa);
console.log(Decode(8, bytes2));
// console.log(test(a))
console 命令行工具 X clear

                    
>
console