123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- <?php
- /**
- * Mapon cars GPS location service low-level api
- */
- class MaponAPI {
- /**
- * @var string Your API key
- */
- public $apiKey;
- /**
- * @var string API URL, with trailing slash
- */
- public $apiUrl;
- public $libVersion = 1.0;
- public $debug = false;
- /**
- * @param string $apiKey Your API key
- * @param string $apiUrl Your API url, with trailing slash
- */
- public function __construct($apiKey, $apiUrl) {
- $this->apiKey = $apiKey;
- $this->apiUrl = rtrim($apiUrl, '/') . '/';
- }
- /**
- * @param string $requestMethod
- * @param string $apiMethod
- * @param array $getData
- * @param array $postData
- * @return stdClass
- * @throws ApiException
- */
- public function callMethod($requestMethod, $apiMethod, $getData = array(), $postData = array()) {
- if (!function_exists('json_decode')) {
- throw new ApiException('Please enable php json extension');
- }
- $getData += array(
- 'key' => $this->apiKey,
- '_phplibv' => $this->libVersion,
- );
- $url = $this->apiUrl . $apiMethod . '.json';
- $res = $this->getUrlContent($url, $requestMethod, $getData, $postData);
- $json = json_decode($res);
- if (is_null($json) || (!isset($json->data) && !isset($json->error))) {
- if ($this->debug) {
- echo "Response from API:\n" . $res . "\n";
- }
- throw new ApiException('Error while parsing API response');
- }
- if (isset($json->error)) {
- throw new ApiException($json->error->msg, $json->error->code);
- }
- return $json;
- }
- /**
- * @param string $urlDomain Domain + path WITHOUT query part
- * @param string $requestMethod get or post
- * @param array $queryData
- * @param array $postData
- * @return mixed
- * @throws ApiException
- */
- private function getUrlContent($urlDomain, $requestMethod, array $queryData = array(), array $postData = array()) {
- $isPost = $requestMethod == 'post';
- $urlDomain .= '?' . http_build_query($queryData);
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $urlDomain);
- curl_setopt($ch, CURLOPT_POST, $isPost ? 1 : 0);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- if ($isPost) {
- curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
- }
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- $output = curl_exec($ch);
- $error = curl_error($ch);
- curl_close($ch);
- if (!$output) {
- throw new ApiException('Could not HTTP request: ' . var_export($error, true));
- }
- return $output;
- }
- /**
- * Call GET API request
- *
- * @param string $action Class and action, for example, unit/list
- * @param array $queryData Data which will be passed as GET parameters
- * @return stdClass
- * @throws ApiException
- */
- public function get($action, $queryData = array()) {
- return $this->callMethod('get', $action, $queryData);
- }
- /**
- * Call POST API request
- *
- * @param $action Class and action, for example, object/save
- * @param array $postData Data which will be passed as POST data
- * @return stdClass
- * @throws ApiException
- */
- public function post($action, $postData = array()) {
- return $this->callMethod('post', $action, array(), $postData);
- }
- /**
- * Decodes encoded route polyline and returns lat/lng array.
- * If $speed string is given, then return array will also contain velocity for each coordinate.
- * If $start_time is given then each coordinate will also contain time.
- * All this information can be obtained by actions which return route data.
- *
- * Based on:
- * http://code.google.com/apis/maps/documentation/polylinealgorithm.html
- *
- * @param string $encoded Encoded route
- * @param string $speed Encoded speed
- * @param integer $startTime Route start time in unix timestamp
- * @return array
- */
- public function decodePolyline($encoded, $speed = null, $startTime = null) {
- if (!is_null($speed)) {
- $speed = $this->decodeSpeed($speed);
- }
- $length = strlen($encoded);
- $index = 0;
- $points = array();
- $lat = 0;
- $lng = 0;
- while ($index < $length) {
- // Temporary variable to hold each ASCII byte.
- $b = 0;
- // The encoded polyline consists of a latitude value followed by a
- // longitude value. They should always come in pairs. Read the
- // latitude value first.
- $shift = 0;
- $result = 0;
- do {
- // The `ord(substr($encoded, $index++))` statement returns the ASCII
- // code for the character at $index. Subtract 63 to get the original
- // value. (63 was added to ensure proper ASCII characters are displayed
- // in the encoded polyline string, which is `human` readable)
- $b = ord(substr($encoded, $index++)) - 63;
- // AND the bits of the byte with 0x1f to get the original 5-bit `chunk.
- // Then left shift the bits by the required amount, which increases
- // by 5 bits each time.
- // OR the value into $results, which sums up the individual 5-bit chunks
- // into the original value. Since the 5-bit chunks were reversed in
- // order during encoding, reading them in this way ensures proper
- // summation.
- $result |= ($b & 0x1f) << $shift;
- $shift += 5;
- }
- // Continue while the read byte is >= 0x20 since the last `chunk`
- // was not OR'd with 0x20 during the conversion process. (Signals the end)
- while ($b >= 0x20);
- // Check if negative, and convert. (All negative values have the last bit
- // set)
- $dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1));
- // Compute actual latitude since value is offset from previous value.
- $lat += $dlat;
- // The next values will correspond to the longitude for this point.
- $shift = 0;
- $result = 0;
- do {
- $b = ord(substr($encoded, $index++)) - 63;
- $result |= ($b & 0x1f) << $shift;
- $shift += 5;
- } while ($b >= 0x20);
- $dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1));
- $lng += $dlng;
- // The actual latitude and longitude values were multiplied by
- // 1e5 before encoding so that they could be converted to a 32-bit
- // integer representation. (With a decimal accuracy of 5 places)
- // Convert back to original values.
- $points[] = array(
- 'lat' => $lat * 1e-5,
- 'lng' => $lng * 1e-5
- );
- }
- if (!is_null($speed)) {
- foreach ($speed as $k => $v) {
- $points[$k]['speed'] = $v[1];
- if (!is_null($startTime)) {
- $startTime += $v[0];
- $points[$k]['time'] = $startTime;
- }
- }
- }
- return $points;
- }
- /**
- * decodes time offsets and speeds
- * @param string $str
- * @return array
- */
- public function decodeSpeed($str) {
- $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.';
- $points = strlen($str) / 4;
- $data = array();
- for ($i = 0; $i < $points; $i++) {
- $pos = $i * 4;
- $offset = strpos($chars, $str[$pos]) * 64;
- $offset += strpos($chars, $str[$pos + 1]);
- $speed = strpos($chars, $str[$pos + 2]) * 64;
- $speed += strpos($chars, $str[$pos + 3]);
- $data[] = array($offset, $speed);
- }
- return $data;
- }
- }
- /**
- * Nothing to see here
- */
- class ApiException extends \Exception {
-
- }
|