Przeglądaj źródła

优化简易通协议

webconsole 6 lat temu
rodzic
commit
7cbc615bbe
4 zmienionych plików z 693 dodań i 120 usunięć
  1. 180 0
      Home/Lib/Class/Gps.php
  2. 156 120
      Home/Lib/Class/Jytgps.php
  3. 170 0
      Home/Lib/Class/Lhtcp.php
  4. 187 0
      Home/Lib/Class/Lhtlv.php

+ 180 - 0
Home/Lib/Class/Gps.php

@@ -0,0 +1,180 @@
+<?php
+namespace WokermanProto;
+
+class Gps {
+			
+
+
+ 
+	public static function input( $buffer, $connection ){
+		if (strlen($buffer) < 4) {
+			return 0;
+		}
+		$unpack_data = unpack('C1magic/C1method/n1length', $buffer);
+		return $unpack_data['length'] + 6;
+	}
+	
+ 
+	private static function bin2str( $hex, $space ){
+		$data = unpack("C*chars",$hex);
+		$bin = '';
+		foreach($data as $key=>$value){
+			$bin .= sprintf('%02X',$value);
+			if($space)
+				$bin .= ' ';
+		}
+		return trim($bin);
+	}
+	
+ 
+	private static function packValue( $value ){
+		if($value['cmd'] == 0x02){
+			return pack('C1',$value['result']);
+		}
+		elseif($value['cmd'] == 0x04){
+			return pack('C1',$value['result']);
+		}
+		elseif($value['cmd'] == 0x03){
+			return pack('n1',$value['data']);
+		}
+		elseif($value['cmd'] == 0x01 || $value['cmd'] == 0xBE){
+			return pack('H*', $value['data']);
+		}
+		else{
+			return false;
+		}
+	}
+	
+ 
+	private static function unpackValue( $cmd, $value, $length ){
+		if($cmd == 0x01){ //设备注册
+			if($length == 6)
+				return array('uid' => self::bin2str($value,false) );
+			else
+				return null;
+		}
+		elseif($cmd == 0x05){ //设备心跳
+			return null;
+		}
+		elseif($cmd == 0x07){ //上报IMSI
+			if($length == 21){
+				return array(
+					'uid' => self::bin2str(substr($value,0,6),false) ,
+					'imsi' => substr($value,6,15) 
+				);
+			}
+			else
+				return null;
+		}
+		elseif($cmd == 0x08){ //设备响应
+			if($length == 2){
+				return array(
+					'type' => Ord(substr($value,0,1)) ,
+					'result' => Ord(substr($value,1,1)) 
+				);
+			}
+			else
+				return null;
+		}	
+		elseif($cmd == 0xbe){ //上报地理位置
+			if($length == 20){
+				//解析设置的时间间隔,设置的设备数量
+				//$info = unpack('C1status/C1nbsphere/C1dxsphere/C1speed1/C1speed2/n1longitude/n1latitude/', substr($value,10,4));
+				$info = array();
+				//定位状态
+				$info['state'] = Ord(substr($value,0,1));
+				//南北半球
+				$info['nbsphere'] = Ord(substr($value,1,1));
+				//东西半球
+				$info['dxsphere'] = Ord(substr($value,2,1));
+				//速度
+				$speed1 = Ord(substr($value,3,1));
+				$speed2 = Ord(substr($value,4,1));
+				$info['speed'] = $speed1 .'.'.$speed2;
+				//经度
+				$longitude1 = Ord(substr($value,5,1));
+				$longitude2 = Ord(substr($value,6,1))*256*256+Ord(substr($value,7,1))*256+Ord(substr($value,8,1));
+				$info['longitude'] = $longitude1 .'.'.sprintf("%05d", $longitude2);
+				//纬度
+				$latitude1 = Ord(substr($value,9,1));
+				$latitude2 = Ord(substr($value,10,1))*256*256+Ord(substr($value,11,1))*256+Ord(substr($value,12,1));
+				$info['latitude'] = $latitude1 .'.'. sprintf("%05d", $latitude2);
+				//解析时间
+				$year1 = Ord(substr($value,13,1));
+				$year2 = Ord(substr($value,14,1));
+				$month = Ord(substr($value,15,1));
+				$day = Ord(substr($value,16,1));
+				$hour = Ord(substr($value,17,1));
+				$minute = Ord(substr($value,18,1));
+				$second = Ord(substr($value,19,1));
+				$info['time'] = sprintf("%02d%02d-%02d-%02d %02d:%02d:%02d",$year1 ,$year2 ,$month, $day, $hour, $minute, $second);
+		
+				return $info;
+			}
+			else
+				return null;
+		}
+		elseif($cmd == 0xbd){ //上报报警
+			if($length == 1)
+				return array('v' => self::bin2str($value) );
+			else
+				return null;
+		}
+		return $value;
+	}
+	
+ 
+	public static function decode( $buffer ){
+		//解码头部数据
+		$unpack_head = unpack('C1magic/C1cmd/n1length', $buffer);
+		$unpack_head['method'] = sprintf("method%'04x",$unpack_head['cmd']);
+		//判断头部引导符
+		if( $unpack_head['magic'] != 0xEC )
+			return null;
+		//判断最后结尾符
+		if( Ord(substr($buffer,-1)) != 0x68 )
+			return null;
+		//判断签名是否正确
+		
+		//如果长度等于0则没有值数据
+		if($unpack_head['length'] == 0)
+			return $unpack_head;
+		
+		//解码值数据
+		$value = substr($buffer,4,$unpack_head['length']);
+		$unpack_value = self::unpackValue($unpack_head['cmd'],$value,$unpack_head['length']);
+		if(!$unpack_value)
+			return null;
+		
+		//头部+值一起返回
+		return array_merge($unpack_head,$unpack_value);
+	}
+	
+ 
+	public static function encode( $value ){
+		$pack_value = self::packValue($value);
+		$length = strlen($pack_value);
+		$sign = $value['cmd'] + $length;
+		for($i=0;$i<strlen($pack_value);$i++){
+			$sign += Ord($pack_value[$i]);
+		}
+		$buf = pack('C1C1n1', 0xEC,$value['cmd'],$length) . $pack_value .pack('C1', $sign). pack('C1', 0x68);
+		return $buf;
+	}
+	
+ 
+	private static function str2bin( $text ){
+		if (!is_string($text)) 
+			return null;
+		$arr = explode(' ',$text);
+		$bin = '';
+		foreach($arr as $hex){
+			if(strlen($hex) == 2){
+				$bin .= chr( hexdec($hex) );
+			}
+		}
+		return $bin;
+	}
+	
+
+}

+ 156 - 120
Home/Lib/Class/Jytgps.php

@@ -1,9 +1,15 @@
 <?php
-namespace Jiaruan;
+namespace WokermanProto;
 
 class Jytgps {
 			
+ 
+	const LOCATION_FORMAT_FLOAT = 0;
+ 
+	const LOCATION_FORMAT_RAW = 1;
 
+	private static $locationFormat ;
+	
 
  
 	public static function str2bin( $text ){
@@ -30,8 +36,8 @@ class Jytgps {
 	
  
 	public static function encode( $value ){
-		echo 'encode:'.PHP_EOL;
-		var_dump($value);
+		//echo 'encode:'.PHP_EOL;
+		//var_dump($value);
 		
 		return $value['head_char'].$value['identify'].$value['version'].'Y'.$value['function_code'].$value['function_keyword'].$value['end_char'];
 		
@@ -39,130 +45,57 @@ class Jytgps {
 	
  
 	public static function decode( $buffer ){
-		$length = strlen($buffer);
-		$data = array();
-		$data['head_char'] = substr($buffer,0,1);
-		$data['identify'] = substr($buffer,1,2);
-		$data['version'] = substr($buffer,3,2);
-		$data['replay'] = substr($buffer,5,1);
-		$index = strpos($buffer,',')+1;
-		$data['device_id'] = substr($buffer,6,$index-1-6);
-		$re = substr($buffer,$index,1);
-		if($re == 'Y'){
-			$data['function_code'] = substr($buffer,$index+1,1);
-			$data['function_keyword'] = substr($buffer,$index+2,1);
-			$data['end_char'] = substr($buffer,$index+3,1);
-		}else{
-			$data['function_code'] = substr($buffer,$index,1);
-			$data['function_keyword'] = substr($buffer,$index+1,1);
-			$order_data = substr($buffer,$index+2,$length-1);
-			$data['order_data'] = $order_data;
-			$data['end_char'] = substr($buffer,-1);
-			//解析指令数据
-			/*
+		/*
 			function_code(终端--功能类指令): A-上传状态类信息  B-上传定位类信息
 			function_keyword(功能项):
-			*/
-			$data['method'] = 'method000'.$data['function_code'];
-			$data['packet'] = $buffer;
-			if($data['function_code'] == 'B'&& $data['function_keyword'] == 'A'){
-				
-				$orders = explode('&',$order_data);
-				foreach ($orders as $order) {
-					if($order){
-						$code = substr($order,0,1);
-						//解析定位数据
-						if($code=='A'){
-							//A0732142233550011405829060520190600
-							//时分秒
-							$times = substr($order,1,2).':'.substr($order,3,2).':'.substr($order,5,2); 
-							//定位纠偏  纠偏公式   abcde.fghi    abc+de/60+fghi/600000
-							$lat1 = substr($order,7,4);
-							$lat2 = substr($order,11,4);
-							$lat_a = floor($lat1/100);
-							$lat_b = (($lat1 - $lat_a*100).'.'.$lat2 )/60;
-							$lat = $lat_a + $lat_b;
-		
-							$lng1 = substr($order,15,5);
-							$lng2 = substr($order,20,4);
-							$lng_a = floor($lng1/100);
-							$lng_b = (($lng1 - $lng_a*100).'.'.$lng2 )/60;
-							$lng = $lng_a + $lng_b;
-							$data['lat'] = $lat;
-							$data['lng'] = $lng;
-							/*
-								$lat_0 =  substr($order,7,4).'.'.substr($order,11,4);
-								$lng_0 =  substr($order,15,5).'.'.substr($order,20,4);
-								$data['lat_0'] = $lat_0;
-								$data['lng_0'] = $lng_0;
-								*/
-							$f = ord(substr($order,24,1));
-							$data['f'] = $f;
-							$data['type'] = 1;//1-表示取GPS坐标数据,2-表示取基站坐标
-							switch ($f) {
-								case 48://0x0011 0000 西经、南纬、定位
-								$data['ew']='W';
-								$data['ns']='S';
-								$data['location']=true;
-								break;
-								case 49://0x0011 0001 西经、南纬、非定位
-								$data['ew']='W';
-								$data['ns']='S';
-								$data['location']=false;
-								break;
-								case 50://0x0011 0010 西经、北纬、定位
-								$data['ew']='W';
-								$data['ns']='N';
-								$data['location']=true;
-								break;
-								case 51://0x0011 0011 西经、北纬、非定位
-								$data['ew']='W';
-								$data['ns']='N';
-								$data['location']=false;
-								break;
-								case 52://0x0011 0100 东经、南纬、定位
-								$data['ew']='E';
-								$data['ns']='S';
-								$data['location']=true;
-								break;
-								case 53://0x0011 0101东经、南纬、非定位
-								$data['ew']='E';
-								$data['ns']='S';
-								$data['location']=false;
-								break;
-								case 54://0x0011 0110东经、北纬、定位
-								$data['ew']='E';
-								$data['ns']='N';
-								$data['location']=true;
-								break;
-								case 55://0x0011 0111 东经、北纬、非定位
-								$data['ew']='E';
-								$data['ns']='N';
-								$data['location']=false;
-								break;
-								case 63://0x0011 1111 表示设备直接调用第三方的基站位置解析接口成经纬度信息上传,该标志位用来区分正常的GPS 定位经纬度信息
-								$data['ew']=null;
-								$data['ns']=null;
-								$data['type']=2;
-								break;
-		
-								default:
-								break;
-							}
-		
-							$data['speed'] = substr($order,25,2);
-							$data['direction'] = substr($order,27,2);
-							$dates = '20'.substr($order,33,2).'-'.substr($order,31,2).'-'.substr($order,29,2); //年月日
-							$data['device_time'] = $dates.' '.$times;
-						}
+		*/
+		$length = strlen($buffer);
+		$str = rtrim($buffer,"#");
+		$arr = explode('#',$str);
+		$decode = array();
+		foreach($arr as $key=>$row){
+			$buffer = $row.'#';
+			$data = array();
+			$data['head_char'] = substr($buffer,0,1);
+			$data['identify'] = substr($buffer,1,2);
+			$data['version'] = substr($buffer,3,2);
+			$data['reply'] = substr($buffer,5,1);
+			$index = strpos($buffer,',')+1;
+			$data['device_id'] = substr($buffer,6,$index-1-6);
+			$re = substr($buffer,$index,1);
+			if($re == 'Y'){  //Y回应的数据包,功能码和关键词的起始位置和非回应的不一样
+				$data['function_code'] = substr($buffer,$index+1,1);
+				$data['function_keyword'] = substr($buffer,$index+2,1);
+				$data['end_char'] = substr($buffer,$index+3,1);
+			}else{
+				$data['function_code'] = substr($buffer,$index,1);
+				$data['function_keyword'] = substr($buffer,$index+1,1);
+				$data['order_data'] = substr($buffer,$index+2,$length-1);
+				$data['end_char'] = substr($buffer,-1);
+				//解析指令数据
+				$data['method'] = 'method000'.$data['function_code'];
+				if($data['function_code'] == 'A'){ //上报状态
+					array_push($decode, $data);
+				}
+				elseif($data['function_code'] == 'B'){ //上报定位
+					if($data['function_keyword'] == 'A'){
+						$data = self::decodeLocation($data);
+						if($data['lat'] !== false)
+							array_push($decode, $data);
+						else
+							echo 'lat empty ' . PHP_EOL;
+					}
+					else{
+						//....跳过
 					}
 				}
-				
-		
+				else{
+					//....跳过
+				}
 			}
 		}
 		
-		return $data;
+		return $decode;
 	}
 	
  
@@ -177,5 +110,108 @@ class Jytgps {
 		return trim($bin);
 	}
 	
+ 
+	private  function decodeLocation( $data ){
+		$orders = explode('&',$data['order_data']);
+		$data['lat'] = false;
+		$data['lng'] = false;
+		foreach ($orders as $order) {
+			$code = substr($order,0,1);
+			//解析定位数据
+			if($code=='A'){
+				//A0732142233550011405829060520190600
+				//时分秒
+				$times = substr($order,1,2).':'.substr($order,3,2).':'.substr($order,5,2); 
+				//定位纠偏  纠偏公式   abcde.fghi    abc+de/60+fghi/600000
+				$lat1 = substr($order,7,4);
+				$lat2 = substr($order,11,4);
+				$lng1 = substr($order,15,5);
+				$lng2 = substr($order,20,4);
+				if(self::locationFormat == self::LACATION_FORMAT_FLOAT){
+					$lat_a = floor($lat1/100);
+					$lat_b = (($lat1 - $lat_a*100).'.'.$lat2 )/60;
+					$data['lat'] = $lat_a + $lat_b;
+					$lng_a = floor($lng1/100);
+					$lng_b = (($lng1 - $lng_a*100).'.'.$lng2 )/60;
+					$data['lng'] = $lng_a + $lng_b;
+				}else{
+					$data['lat'] = $lat1 .'.'. $lat2;
+					$data['lng'] = $lng1 .'.'. $lng2;
+				}
+				
+				/*
+									$lat_0 =  substr($order,7,4).'.'.substr($order,11,4);
+									$lng_0 =  substr($order,15,5).'.'.substr($order,20,4);
+									$data['lat_0'] = $lat_0;
+									$data['lng_0'] = $lng_0;
+									*/
+				$f = ord(substr($order,24,1));
+				$data['f'] = $f;
+				$data['type'] = 1;//1-表示取GPS坐标数据,2-表示取基站坐标
+				switch ($f) {
+					case 48://0x0011 0000 西经、南纬、定位
+					$data['ew']='W';
+					$data['ns']='S';
+					$data['location']=true;
+					break;
+					case 49://0x0011 0001 西经、南纬、非定位
+					$data['ew']='W';
+					$data['ns']='S';
+					$data['location']=false;
+					break;
+					case 50://0x0011 0010 西经、北纬、定位
+					$data['ew']='W';
+					$data['ns']='N';
+					$data['location']=true;
+					break;
+					case 51://0x0011 0011 西经、北纬、非定位
+					$data['ew']='W';
+					$data['ns']='N';
+					$data['location']=false;
+					break;
+					case 52://0x0011 0100 东经、南纬、定位
+					$data['ew']='E';
+					$data['ns']='S';
+					$data['location']=true;
+					break;
+					case 53://0x0011 0101东经、南纬、非定位
+					$data['ew']='E';
+					$data['ns']='S';
+					$data['location']=false;
+					break;
+					case 54://0x0011 0110东经、北纬、定位
+					$data['ew']='E';
+					$data['ns']='N';
+					$data['location']=true;
+					break;
+					case 55://0x0011 0111 东经、北纬、非定位
+					$data['ew']='E';
+					$data['ns']='N';
+					$data['location']=false;
+					break;
+					case 63://0x0011 1111 表示设备直接调用第三方的基站位置解析接口成经纬度信息上传,该标志位用来区分正常的GPS 定位经纬度信息
+					$data['ew']=null;
+					$data['ns']=null;
+					$data['type']=2;
+					break;
+		
+					default:
+					break;
+				}
+		
+				$data['speed'] = substr($order,25,2);
+				$data['direction'] = substr($order,27,2);
+				$dates = '20'.substr($order,33,2).'-'.substr($order,31,2).'-'.substr($order,29,2); //年月日
+				$data['device_time'] = $dates.' '.$times;
+			}
+		}
+		return $data;
+	}
+	
+ 
+	public  function setLocationFormat( $format ){
+		self::locationFormat = $format;
+	}
+	
 
 }

+ 170 - 0
Home/Lib/Class/Lhtcp.php

@@ -0,0 +1,170 @@
+<?php
+namespace WokermanProto;
+
+class Lhtcp {
+			
+
+
+ 
+	public static function input( $buffer, $connection ){
+		if (strlen($buffer) < 6) {
+			return 0;
+		}
+		if(Ord($buffer[0]) == 0xF5){
+			$unpack_data = unpack('C4magic/C1length', $buffer);
+			return $unpack_data['length'];
+		}else if(Ord($buffer[0]) == 0xF6){
+			$unpack_data = unpack('C4magic/S1length', $buffer);
+			return $unpack_data['length'];
+		}else if(Ord($buffer[0]) == 0xEC){
+			$unpack_data = unpack('C1magic/C1method/n1length', $buffer);
+			return $unpack_data['length'] + 6;
+		}else{
+			return strlen($buffer);
+		}
+		
+		
+	}
+	
+ 
+	private static function bin2str( $hex, $space ){
+		$data = unpack("C*chars",$hex);
+		$bin = '';
+		foreach($data as $key=>$value){
+			$bin .= sprintf('%02X',$value);
+			if($space)
+				$bin .= ' ';
+		}
+		return trim($bin);
+	}
+	
+ 
+	private static function packValue( $value ){
+		if($value['cmd'] == 0x01){
+			return '';
+		}
+		elseif($value['cmd'] == 0x0F){
+			return '';
+		}
+		else{
+			return false;
+		}
+	}
+	
+ 
+	private static function unpackValue( $cmd, $value, $length ){
+		if($cmd == 0x0F){ //设备心跳
+			return array();
+		}
+		elseif($cmd == 0x01){ //上报标签
+				//解析车辆信息
+				$count = $length/6;
+				$labels = array();
+				for($i=0;$i<$count;$i++){
+					$rfid = self::bin2strr(substr($value,$j,6),false);
+					$j += 6;
+					$info = array(
+						'rfid' => $rfid,
+						'time' => date('Y-m-d H:i:s') 
+					);
+					array_push($labels,$info);
+				}
+				return array(
+					'labels' => $labels
+				);
+		}
+		return $value;
+	}
+	
+ 
+	public static function decode( $buffer ){
+		//判断最后结尾符
+		if( Ord(substr($buffer,-2,1)) != 0x0D || Ord(substr($buffer,-1)) != 0x0A ){
+			return null;
+		}
+		//解码头部数据
+		$unpack_magic = unpack('C4magic', $buffer);
+		//判断头部引导符
+		if( $unpack_magic['magic1'] == 0xF6 && $unpack_magic['magic2'] == 0xF6 && 
+		   $unpack_magic['magic3'] == 0xF6 && $unpack_magic['magic4'] == 0xF6){
+		   $unpack_head = unpack('S1length/C1project/C1type/', substr($buffer,4,4));
+			$unpack_head['version'] = 0xF6;
+			$unpack_head['cmd'] = Ord(substr($buffer,14,1));
+			$unpack_head['method'] = sprintf("method%'04x",$unpack_head['cmd']);
+			$unpack_head['uid'] = self::bin2strr(substr($buffer,8,6),false);
+			$unpack_head['uid_raw'] = substr($buffer,8,6);
+			//解码值数据
+			$value = substr($buffer,15,$unpack_head['length']-17);
+			$unpack_value = self::unpackValue($unpack_head['cmd'],$value,$unpack_head['length']-17);
+		}
+		//判断头部引导符
+		else if( $unpack_magic['magic1'] == 0xF5 && $unpack_magic['magic2'] == 0xF5 && 
+		   $unpack_magic['magic3'] == 0xF5 && $unpack_magic['magic4'] == 0xF5){
+			$unpack_head = unpack('C1length/C1project/C1type/', substr($buffer,4,3));
+			$unpack_head['uid'] = self::bin2strr(substr($buffer,7,6),false);
+			$unpack_head['uid_raw'] = substr($buffer,7,6);
+			//解码值数据
+			$unpack_head['version'] = 0xF5;
+			$unpack_head['cmd'] = Ord(substr($buffer,13,1));
+			$unpack_head['method'] = sprintf("method%'04x",$unpack_head['cmd']);
+			$value = substr($buffer,14,$unpack_head['length']-16);
+			$unpack_value = self::unpackValue($unpack_head['cmd'],$value,$unpack_head['length']-16);
+		}
+		else if( $unpack_magic['magic1'] == 0xEC ){
+					$unpack = \Jiaruan\Lhtlv::decode($buffer);
+					$unpack['version'] = 0xEC;
+					return $unpack;
+		}
+		else{
+			return null;
+		}
+		//头部+值一起返回
+		return array_merge($unpack_head,$unpack_value);
+	}
+	
+ 
+	public static function encode( $value ){
+		if($value['version'] == 0xF6){
+			$buf = pack('C1C1C1C1S1C1C1',0xF6,0xF6,0xF6,0xF6,17,0x65,0x00).$value['uid_raw'].pack('C1',$value['cmd']).pack('C1C1',0x0D,0x0A);
+		}else if($value['version'] == 0xF5){
+			$buf = pack('C1C1C1C1C1C1C1',0xF5,0xF5,0xF5,0xF5,16,0x65,0x00).$value['uid_raw'].pack('C1',$value['cmd']).pack('C1C1',0x0D,0x0A);
+		}else if($value['version'] == 0xEC){
+			$buf = \Jiaruan\Lhtlv::encode($value);
+		}else{
+			echo 'version error'.PHP_EOL;
+			return '';
+		}
+		if(APP_DEBUG){
+			echo self::bin2str($buf,true).PHP_EOL;
+		}
+		return $buf;
+	}
+	
+ 
+	private static function str2bin( $text ){
+		if (!is_string($text)) 
+			return null;
+		$arr = explode(' ',$text);
+		$bin = '';
+		foreach($arr as $hex){
+			if(strlen($hex) == 2){
+				$bin .= chr( hexdec($hex) );
+			}
+		}
+		return $bin;
+	}
+	
+ 
+	private static function bin2strr( $hex, $space ){
+		$data = unpack("C*chars",$hex);
+		$bin = '';
+		foreach($data as $key=>$value){
+			$bin = sprintf('%02X',$value).$bin;
+			if($space)
+				$bin .= ' ';
+		}
+		return trim($bin);
+	}
+	
+
+}

+ 187 - 0
Home/Lib/Class/Lhtlv.php

@@ -0,0 +1,187 @@
+<?php
+namespace WokermanProto;
+
+class Lhtlv {
+			
+
+
+ 
+	public static function input( $buffer, $connection ){
+		if (strlen($buffer) < 4) {
+			return 0;
+		}
+		$unpack_data = unpack('C1magic/C1method/n1length', $buffer);
+		return $unpack_data['length'] + 6;
+	}
+	
+ 
+	private static function bin2str( $hex, $space ){
+		$data = unpack("C*chars",$hex);
+		$bin = '';
+		foreach($data as $key=>$value){
+			$bin .= sprintf('%02X',$value);
+			if($space)
+				$bin .= ' ';
+		}
+		return trim($bin);
+	}
+	
+ 
+	private static function packValue( $value ){
+		if($value['cmd'] == 0x02){
+			return pack('C1',$value['result']);
+		}
+		elseif($value['cmd'] == 0x04){
+			return pack('C1',$value['result']);
+		}
+		elseif($value['cmd'] == 0x09){
+			return pack('C1n1',$value['type'],$value['data']);
+		}
+		elseif($value['cmd'] == 0x01 || $value['cmd'] == 0xBC){
+			return pack('H*', $value['data']);
+		}
+		else{
+			return false;
+		}
+	}
+	
+ 
+	private static function unpackValue( $cmd, $value, $length ){
+		if($cmd == 0x01){ //设备注册
+			if($length == 6)
+				return array('uid' => self::bin2str($value,false) );
+			else
+				return null;
+		}
+		elseif($cmd == 0x05){ //设备心跳
+			return null;
+		}
+		elseif($cmd == 0x07){ //上报IMSI
+			if($length == 21){
+				return array(
+					'uid' => self::bin2str(substr($value,0,6),false) ,
+					'imsi' => substr($value,6,15) 
+				);
+			}
+			else
+				return null;
+		}
+		elseif($cmd == 0x08){ //设备响应
+			if($length == 2){
+				return array(
+					'type' => Ord(substr($value,0,1)) ,
+					'result' => Ord(substr($value,1,1)) 
+				);
+			}
+			else
+				return null;
+		}	
+		elseif($cmd == 0xbc){ //上报标签
+			if($length >= 14){
+				//解析设置的时间间隔,设置的设备数量
+				$setting = unpack('n1maxtime/n1maxlabels', substr($value,10,4));
+				//解析车辆信息
+				$count = ($length - 14)/14;
+				$labels = array();
+				for($i=0;$i<$count;$i++){
+					//解析RFID
+					$j = 14+$i*14;
+					$rfid = self::bin2str(substr($value,$j,6),false);
+					$j += 6;
+					//解析SSD信号强度
+					$ssd = Ord(substr($value,$j,1));
+					//解析时间
+					$year1 = Ord(substr($value,$j+1,1));
+					$year2 = Ord(substr($value,$j+2,1));
+					$month = Ord(substr($value,$j+3,1));
+					$day = Ord(substr($value,$j+4,1));
+					$hour = Ord(substr($value,$j+5,1));
+					$minute = Ord(substr($value,$j+6,1));
+					$second = Ord(substr($value,$j+7,1));
+					$hour = sprintf('%02d',$hour);
+					$minute = sprintf('%02d',$minute);
+					$second = sprintf('%02d',$second);
+					$time = date('Y-m-d').' '.$hour.':'.$minute.':'.$second;
+					if(strtotime($time) > time()){
+						$time = date('Y-m-d H:i:s',strtotime('-1 day',strtotime($time)));
+					}
+					$info = array(
+						'rfid' => $rfid,
+						'ssd' => $ssd,
+						'time' => $time 
+					);
+					array_push($labels,$info);
+				}
+				return array(
+					'maxtime' => $setting['maxtime'],
+					'maxlabels' => $setting['maxlabels'],
+					'labels' => $labels
+				);
+			}
+			else
+				return null;
+		}
+		elseif($cmd == 0xbd){ //上报报警
+			if($length == 1)
+				return array('v' => self::bin2str($value) );
+			else
+				return null;
+		}
+		return $value;
+	}
+	
+ 
+	public static function decode( $buffer ){
+		//解码头部数据
+		$unpack_head = unpack('C1magic/C1cmd/n1length', $buffer);
+		$unpack_head['method'] = sprintf("method%'04x",$unpack_head['cmd']);
+		//判断头部引导符
+		if( $unpack_head['magic'] != 0xEC )
+			return null;
+		//判断最后结尾符
+		if( Ord(substr($buffer,-1)) != 0x68 )
+			return null;
+		//判断签名是否正确
+		
+		//如果长度等于0则没有值数据
+		if($unpack_head['length'] == 0)
+			return $unpack_head;
+		
+		//解码值数据
+		$value = substr($buffer,4,$unpack_head['length']);
+		$unpack_value = self::unpackValue($unpack_head['cmd'],$value,$unpack_head['length']);
+		if(!$unpack_value)
+			return null;
+		
+		//头部+值一起返回
+		return array_merge($unpack_head,$unpack_value);
+	}
+	
+ 
+	public static function encode( $value ){
+		$pack_value = self::packValue($value);
+		$length = strlen($pack_value);
+		$sign = $value['cmd'] + $length;
+		for($i=0;$i<strlen($pack_value);$i++){
+			$sign += Ord($pack_value[$i]);
+		}
+		$buf = pack('C1C1n1', 0xEC,$value['cmd'],$length) . $pack_value .pack('C1', $sign). pack('C1', 0x68);
+		return $buf;
+	}
+	
+ 
+	private static function str2bin( $text ){
+		if (!is_string($text)) 
+			return null;
+		$arr = explode(' ',$text);
+		$bin = '';
+		foreach($arr as $hex){
+			if(strlen($hex) == 2){
+				$bin .= chr( hexdec($hex) );
+			}
+		}
+		return $bin;
+	}
+	
+
+}