= 1483225217) $t += 18; else $t += 17; $t = (($t - 946684800) * 100) / 16; $s[$o++] = chr(($t >> 24) & 0xFF); $s[$o++] = chr(($t >> 16) & 0xFF); $s[$o++] = chr(($t >> 8) & 0xFF); $s[$o] = chr($t & 0xFF); return $t; } private function CorrectTimestamp(&$a, $TimeStamp) { $t = (((($a['timestamp'] *= 65536) + $a['ts2']) * 16) / 100) + 946684800; unset($a['ts2']); $pl = $this->mData; if ($t + 604800 < $TimeStamp) $t = utinds($t, $pl, 1); $a['timestamp'] = $t; $a['n1cx_data'] = $pl; } private function CorrectLatLon(&$a) { $l = ($a['latitude'] * 65536) + $a['lat2']; unset($a['lat2']); if (($l>0) && ($l >> 31)) $l = -(0x7FFFFFFF - ($l & 0x7FFFFFFF)) - 1; $a['latitude'] = (float)$l / (float)600000; $l = ($a['longitude'] * 65536) + $a['lon2']; unset($a['lon2']); if (($l>0) && ($l >> 31)) $l = -(0x7FFFFFFF - ($l & 0x7FFFFFFF)) - 1; $a['longitude'] = (float)$l / (float)600000; } private function CorrectAccelXYZ(&$a) { $a['accelX'] /= 64; $a['accelY'] /= 64; $a['accelZ'] /= 64; } private function CorrectCompassXYZ(&$a) { $g = $a['compassX']; if ($g >= 0x8000) $g -= 0x10000; $a['compassX'] = $g * 0.92; $g = $a['compassY']; if ($g >= 0x8000) $g -= 0x10000; $a['compassY'] = $g * 0.92; $g = $a['compassZ']; if ($g >= 0x8000) $g -= 0x10000; $a['compassZ'] = $g * 0.92; } private function CorrectTempCelsius(&$a) { $t = $a['temp'] & 0xFFF; if ($t >= 0x800) $t = $t - 0x1000; $a['temp'] = $t * (1 / 16); } private static function CorrectCGPS(&$data, $off, $time = 0) { $data[$off + 32] = chr(ord($data[$off + 32]) | 4); $t = 0.0; for ($o = $off, $e = $off + 4; $o < $e; $o++) { $t *= 256; $t += ord($data[$o]); } $t = (($t * 16) / 100) + 946684800; if ($t >= 1483225217) $leap = 18; else $leap = 17; $t -= $leap; if ($time && ($t + 604800 < $time)) $t = N1Cx_data::utinds($time, $data, $off); return $t; } public function __construct($Data = null) { if ($Data !== null) $this->SetData($Data); } public static function GetVersion() { return 7; } public function IsValid() { return $this->mValid; } public function GetLastError() { return $this->mLastError; } public function SetData($Data, $TimeStamp = 0) { if ((gettype($Data) == 'string') && (($Len = strlen($Data)) > 0)) { $this->mData = $Data; switch(ord($Data[0])) { case 0x21: if ($Len !== 16) { $this->mLastError = "Invalid data length [$Len != 16] for data type [0x21]"; break; } $a = unpack( "Cidentifier/ntimestamp/nts2/nlongitude/nlon2/nlatitude/nlat2/Cspeed/Cheading/CIO", $Data); $this->CorrectTimestamp($a, $TimeStamp); $this->CorrectLatLon($a); $a['speed'] * 1.852; $this->maProperties = $a; return $this->mValid = true; case 0x22: if ($Len !== 19) { $this->mLastError = "Invalid data length [$Len != 19] for data type [0x22]"; break; } $a = unpack( "Cidentifier/ntimestamp/nts2/nlongitude/nlon2/nlatitude/nlat2/Cspeed/Cheading/CIO/caccelX/caccelY/caccelZ", $Data); $this->CorrectTimestamp($a, $TimeStamp); $this->CorrectLatLon($a); $a['speed'] *= 1.852; $this->CorrectAccelXYZ($a); $this->maProperties = $a; return $this->mValid = true; case 0x23: if ($Len !== 27) { $this->mLastError = "Invalid data length [$Len != 27] for data type [0x23]"; break; } $a = unpack( "Cidentifier/ntimestamp/nts2/nlongitude/nlon2/nlatitude/nlat2/Cspeed/Cheading/CIO/caccelX/caccelY/caccelZ/vcompassX/vcompassY/vcompassZ/ntemp", $Data); $this->CorrectTimestamp($a, $TimeStamp); $this->CorrectLatLon($a); $a['speed'] *= 1.852; $this->CorrectAccelXYZ($a); $this->CorrectCompassXYZ($a); $this->CorrectTempCelsius($a); $this->maProperties = $a; return $this->mValid = true; case 0x24: if ($Len !== 29) { $this->mLastError = "Invalid data length [$Len != 29] for data type [0x24]"; break; } $a = unpack( "Cidentifier/ntimestamp/nts2/nlongitude/nlon2/nlatitude/nlat2/Cspeed/Cheading/CIO/caccelX/caccelY/caccelZ/vcompassX/vcompassY/vcompassZ/ntemp/vbattery", $Data); $this->CorrectTimestamp($a, $TimeStamp); $this->CorrectLatLon($a); $a['speed'] *= 1.852; $this->CorrectAccelXYZ($a); $this->CorrectCompassXYZ($a); $this->CorrectTempCelsius($a); $a['battery'] *= 0.006406; $this->maProperties = $a; return $this->mValid = true; case 0xD0: if (($Len - 1) % 33) { $this->mLastError = "Invalid data length for data type [0xD0]"; break; } $b = ''; for ($i = 1; $i < $Len; $i += 33) { $t = N1Cx_data::CorrectCGPS($Data, $i, $TimeStamp); if (($i + 33) >= $Len) $b .= chr(0x82); else $b .= chr(0x80); $b .= substr($Data, $i, 33); } $this->maProperties = array( 'identifier' => 0xD0, 'timestamp' => $t, 'cgps_tcp_data' => $b, 'n1cx_data' => $Data ); return $this->mValid = true; case 0xD2: if ($Len != 35) { $this->mLastError = "Invalid data length for data type [0xD2]"; break; } $t = N1Cx_data::CorrectCGPS($Data, 2, $TimeStamp); $this->maProperties = array( 'identifier' => 0xD0, 'timestamp' => $t, 'cgps_tcp_data' => substr($Data, 1), 'n1cx_data' => $Data ); return $this->mValid = true; case 0xFF: $a = unpack("Cidentifier/ncpuID/nc1/nc2/nc3/CresetReason/NpcBeforeReset/nfwVerMajor/nfwVerMinor/NstackInfo", $Data); $a['cpuID'] = sprintf('%02x%02x%02x%02x', $a['cpuID'], $a['c1'], $a['c2'], $a['c3']); unset($a['c1']); unset($a['c2']); unset($a['c3']); $this->maProperties = $a; return $this->mValid = true; default: $this->mLastError = 'Unknown identifier ' . ord($Data[0]); break; } } else $this->mLastError = 'Invalid data'; $this->maProperties = array(); $this->maResponse = $this->mData = null; return $this->mValid = false; } public function GetData() { return $this->mData; } public function ConvertCGPS($Switch = -1) { $s = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07"; $ident = $this->GetProperty('identifier', -1); if ($Switch == -1) { switch ($ident) { case 0x21: case 0x22: case 0x23: $Switch = 0; break; case 0x24: $Switch = 0x06; break; case 0xD0: case 0xD2: return substr($this->maProperties['cgps_tcp_data'] , 1, 33); case 0xFF: $Switch = 0x30; break; default: $this->mLastError = "Unsupported Identifier $ident"; return ''; } } $v = $this->GetProperty('timestamp', 0); if ($v >= 1483225199) $v += 18; else $v += 17; $v = (($v - 946684800) * 100) / 16; if ($v < 1072911600) $v = 1072911600; for ($f = $v, $o = 3; $o >= 0; $o--) { $s[$o] = chr($f & 0xFF); $f /= 256; } switch ($Switch) { default: $this->mLastError = "Unsupported Switch Value $Switch"; return ''; case 0: $v = (int)(($this->GetProperty('temp', 0) + 60) * 256); $s[18] = chr(($v & 0xFF00) >> 8); $s[19] = chr($v & 0xFF); break; case 0x06: $s[16] = chr(0xE2); $f = 6.0 / 0x400; $v = (int)($this->GetProperty('accelX', 0) / $f); $b = ($v & 7) << 5; $s[17] = chr(($v & 0x7FF) >> 3); $v = (int)($this->GetProperty('accelY', 0) / $f); $b |= ($v & 7) << 2; $s[18] = chr(($v & 0x7FF) >> 3); $v = (int)($this->GetProperty('accelZ', 0) / (6.0 / 0x200)); $s[19] = chr(($v & 0x3FF) >> 2); $s[20] = chr($b | ($v & 3)); break; case 0x30; $s[8] = chr(0x30); $s[23] = chr($this->GetProperty('resetReason', 0)); $v = $this->GetProperty('fwVerMinor', 0); $s[29] = chr($v & 0xFF); $s[32] = chr(ord($s[32]) | (($v & 256) >> 4) | (($v & 512) >> 3)); return $s; } $lon = $this->GetProperty('longitude', 0) * 600000; if ($lon < 0) $lon += 0xFFFFFFFF; $s[4] = chr(($lon >> 24) & 0xFF); $s[5] = chr(($lon >> 16) & 0xFF); $s[6] = chr(($lon >> 8) & 0xFF); $s[7] = chr($lon & 0xFF); $lat = $this->GetProperty('latitude', 0) * 600000; if ($lat < 0) $lat += 0xFFFFFFFF; $s[8] = chr(($lat >> 24) & 0xFF); $s[9] = chr(($lat >> 16) & 0xFF); $s[10] = chr(($lat >> 8) & 0xFF); $s[11] = chr($lat & 0xFF); $v = $this->GetProperty('speed', 0) * 100 / 64 / 1.852; $s[12] = chr(($v >> 1) & 0xFF); $s[31] = chr(ord($s[31]) | ($v & 1) | (($v >> 8) & 2)); $v = $this->GetProperty('heading', 0) / 2.56; $s[13] = chr($v & 0xFF); $v = $this->GetProperty('battery', 0); if ($v != 0) { $v = (int)(($v - .2) * 1969); $s[14] = chr(($v >> 8) & 0xFF); $s[15] = chr($v & 0xFF); } if (((int)$lat == 0) || ((int)$lon == 0)) { $s[23] = chr(ord($s[23]) | 33); } $IO = $this->GetProperty('IO', 0); $s[25] = chr($IO & 0xFF); $s[24] = chr(($v & 4) >> 2); if (~$IO & 1) { $s[28] = chr(11); } else { $s[27] = chr(128); } return $s; } public function GetHexData() { return bin2hex($this->mData); } public function SetHexData($hex, $TimeStamp = 0) { return $this->SetData(hex2bin($hex), $TimeStamp); } public function GetProperties() { return $this->maProperties; } public function CanGetProperty($Property) { return isset($this->maProperties[$Property]); } public function GetProperty($Property, $Alt = null) { return isset($this->maProperties[$Property]) ? $this->maProperties[$Property] : $Alt; } public function CanGetResponseData() { return strlen($this->maResponse) ? true : false; } public function GetResponseData() { return $this->maResponse; } static public function GenerateFakeIMEI($hex, $prefix = "9", $type = 1) { if ($type != 1) { $s = $prefix; $h = '000000000000000000000000' . $hex; $d = $v = 0; for ($l = strlen($s), $o = strlen($h); $l < 14; $v >>= 3, $l++) { if (--$d <= 0) { $o -= 6; $d = 8; $v = hexdec(substr($h, $o, 6)); } $s .= $v & 7; } } else $s = $prefix . substr(sprintf('%014d0', hexdec(substr($hex, -10))), -(15 - strlen($prefix)), 14); $c = 0; for($i = 0; $i < 14; $i += 2) { $d = $s[$i+1] << 1; $c += $s[$i] + (int)($d / 10) + ($d % 10); } $s[14] = (10 - ($c % 10)) % 10; return $s; } static public function GenerateCommand($args) { $s = 'cmd_id'; if (!is_array($args) || !isset($args[$s])) return ''; $c = $args[$s]; $r = chr($c & 0xFF); switch ($c) { case 0x00: $s = 'length'; $r .= (isset($args[$s])) ? chr($args[$s] & 0xFF) : chr(0xFF); return $r; case 0x01: $s = 'ledmap'; $r .= (isset($args[$s])) ? chr($args[$s] & 0xFF) : chr(0xFF); $s = 'ton'; $r .= (isset($args[$s])) ? chr($args[$s] & 0xFF) : chr(2); $s = 'toff'; $r .= (isset($args[$s])) ? chr($args[$s] & 0xFF) : chr(2); $s = 'time'; $r .= (isset($args[$s])) ? chr($args[$s] & 0xFF) : chr(20); return $r; case 0x02: $s = 'md_id'; return $r . (isset($args[$s])) ? chr($args[$s] & 0xFF) : chr(0); case 0x10: case 0x11: $s = 'io32'; if (!isset($args[$s])) return ''; $v = $args[$s]; $r .= chr(($v >> 24) & 0xFF) . chr(($v >> 16) & 0xFF) . chr(($v >> 8) & 0xFF) . chr($v & 0xFF); if ($c == 0x10) return $r; $s = 'mask'; if (!isset($args[$s])) return ''; $v = $args[$s]; return $r . chr(($v >> 24) & 0xFF) . chr(($v >> 16) & 0xFF) . chr(($v >> 8) & 0xFF) . chr($v & 0xFF); case 0x12: $s = 'timer'; if (!isset($args[$s])) return ''; $r .= chr($args[$s] & 0xFF); $s = 'time'; if (!isset($args[$s])) return ''; $v = $args[$s]; switch ($r) { case 254: case 255: if ($v < 0) $v = -(0x7FFFFFFF - ($v & 0x7FFFFFFF)) - 1; break; } return $r . chr(($v >> 24) & 0xFF) . chr(($v >> 16) & 0xFF) . chr(($v >> 8) & 0xFF) . chr($v & 0xFF); case 0x14: case 0x15: $s = 'offset'; if (!isset($args[$s])) return ''; $v = $args[$s]; $r .= chr(($v >> 8) & 0xFF) . chr($v & 0xFF); $s = 'bytes'; if (!isset($args[$s]) || !is_string($args[$s])) return ''; $b = $args[$s]; $l = strlen($b); if (!$l || ($l > 123)) return ''; $s = 'mask'; if (isset($args[$s])) { if (!is_string($args[$s]) || (strlen($args[$s]) != $l) || ($l > 61)) return ''; return $r . chr($l | 128) . $b . $args[$s]; } return $r . chr($l) . $b; case 0x16: case 0x18: return $r; case 0x1A: case 0x1B: $s = 'offset'; if (!isset($args[$s])) return ''; $o = $args[$s]; $s = 'bytes'; if (!isset($args[$s]) || !is_string($args[$s])) return ''; $b = $args[$s]; $l = strlen($b); if (!$l) return ''; $s = 0; while ($l) { if ($l > 15) { $v = 15; $o |= 0xF800; } else { $v = $l; $o &= 0x07FF; $o |= $l << 12; } $r .= chr(($o >> 8) & 0xFF) . chr($o & 0xFF) . substr($b, $s, $v); $s += $v; $o += $v; $l -= $v; } return $r; default: return ''; } } } ?>