<?php
namespace Workerman\Protocols;

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;
	}
	

}