title: GPS tracker server side script
body: <p>I have a GPS Tracking unit that I want to connect to my server. I am using PHP SocketServer.class.php. Now my problem is the data I receive from the Tracking is </p>
  
  <blockquote>
    <p>))±</p>
  </blockquote>
  
  <p>But that is wrong. Here is a <a href="http://www.armand.co.za/Amwell/" rel="nofollow">link</a> to download the Standard Protocol for the Unit. Could someone please show me where my fault could be...</p>
  
  <p>index.php</p>
  
  <pre><code>error_reporting(0);
  set_time_limit(0);
  ob_implicit_flush();
  
  require_once("SocketServer.class.php"); // Include the File
  $server = new SocketServer("154.0.160.80",5522); // Create a Server binding to the given ip address and listen to port 31337 for connections
  $server-&gt;max_clients = 10; // Allow no more than 10 people to connect at a time
  $server-&gt;hook("CONNECT","handle_connect"); // Run handle_connect every time someone connects
  $server-&gt;hook("INPUT","handle_input"); // Run handle_input whenever text is sent to the server
  $server-&gt;infinite_loop(); // Run Server Code Until Process is terminated.
  
  
  function handle_connect(&amp;$server,&amp;$client,$input)
  {
      SocketServer::socket_write_smart($client-&gt;socket,"String? ","");
  }
  function handle_input(&amp;$server,&amp;$client,$input)
  {
  
  }
  </code></pre>
  
  <p>SocketServer.class.php</p>
  
  <pre><code>/*! @class      SocketServer
      @author     Navarr Barnier
      @abstract   A Framework for creating a multi-client server using the PHP language.
   */
  class SocketServer
  {
      /*! @var        config
          @abstract   Array - an array of configuration information used by the server.
       */
      protected $config;
  
      /*! @var        hooks
          @abstract   Array - a dictionary of hooks and the callbacks attached to them.
       */
      protected $hooks;
  
      /*! @var        master_socket
          @abstract   resource - The master socket used by the server.
       */
      protected $master_socket;
  
      /*! @var        max_clients
          @abstract   unsigned int - The maximum number of clients allowed to connect.
       */
      public $max_clients = 10;
  
      /*! @var        max_read
          @abstract   unsigned int - The maximum number of bytes to read from a socket at a single time.
       */
      public $max_read = 1024;
  
      /*! @var        clients
          @abstract   Array - an array of connected clients.
       */
      public $clients;
  
      /*! @function   __construct
          @abstract   Creates the socket and starts listening to it.
          @param      string  - IP Address to bind to, NULL for default.
          @param      int - Port to bind to
          @result     void
       */
      public function __construct($bind_ip,$port)
      {
          set_time_limit(0);
          $this-&gt;hooks = array();
  
          $this-&gt;config["ip"] = $bind_ip;
          $this-&gt;config["port"] = $port;
  
          $this-&gt;master_socket = socket_create(AF_INET, SOCK_STREAM, 0);
          socket_bind($this-&gt;master_socket,$this-&gt;config["ip"],$this-&gt;config["port"]) or die("Issue Binding");
          socket_getsockname($this-&gt;master_socket,$bind_ip,$port);
          socket_listen($this-&gt;master_socket);
          SocketServer::debug("Listenting for connections on {$bind_ip}:{$port}");
      }
  
      /*! @function   hook
          @abstract   Adds a function to be called whenever a certain action happens.  Can be extended in your implementation.
          @param      string  - Command
          @param      callback- Function to Call.
          @see        unhook
          @see        trigger_hooks
          @result     void
       */
      public function hook($command,$function)
      {
          $command = strtoupper($command);
          if(!isset($this-&gt;hooks[$command])) { $this-&gt;hooks[$command] = array(); }
          $k = array_search($function,$this-&gt;hooks[$command]);
          if($k === FALSE)
          {
              $this-&gt;hooks[$command][] = $function;
          }
      }
  
      /*! @function   unhook
          @abstract   Deletes a function from the call list for a certain action.  Can be extended in your implementation.
          @param      string  - Command
          @param      callback- Function to Delete from Call List
          @see        hook
          @see        trigger_hooks
          @result     void
       */
      public function unhook($command = NULL,$function)
      {
          $command = strtoupper($command);
          if($command !== NULL)
          {
              $k = array_search($function,$this-&gt;hooks[$command]);
              if($k !== FALSE)
              {
                  unset($this-&gt;hooks[$command][$k]);
              }
          } else {
              $k = array_search($this-&gt;user_funcs,$function);
              if($k !== FALSE)
              {
                  unset($this-&gt;user_funcs[$k]);
              }
          }
      }
  
      /*! @function   loop_once
          @abstract   Runs the class's actions once.
          @discussion Should only be used if you want to run additional checks during server operation.  Otherwise, use infinite_loop()
          @param      void
          @see        infinite_loop
          @result     bool    - True
      */
      public function loop_once()
      {
          // Setup Clients Listen Socket For Reading
          $read[0] = $this-&gt;master_socket;
          for($i = 0; $i &lt; $this-&gt;max_clients; $i++)
          {
              if(isset($this-&gt;clients[$i]))
              {
                  $read[$i + 1] = $this-&gt;clients[$i]-&gt;socket;
              }
          }
  
          // Set up a blocking call to socket_select
          if(socket_select($read,$write = NULL, $except = NULL, $tv_sec = 5) &lt; 1)
          {
          //  SocketServer::debug("Problem blocking socket_select?");
              return true;
          }
  
          // Handle new Connections
          if(in_array($this-&gt;master_socket, $read))
          {
              for($i = 0; $i &lt; $this-&gt;max_clients; $i++)
              {
                  if(empty($this-&gt;clients[$i]))
                  {
                      $temp_sock = $this-&gt;master_socket;
                      $this-&gt;clients[$i] = new SocketServerClient($this-&gt;master_socket,$i);
                      $this-&gt;trigger_hooks("CONNECT",$this-&gt;clients[$i],"");
                      break;
                  }
                  elseif($i == ($this-&gt;max_clients-1))
                  {
                      SocketServer::debug("Too many clients... :( ");
                  }
              }
  
          }
  
          // Handle Input
          for($i = 0; $i &lt; $this-&gt;max_clients; $i++) // for each client
          {
              if(isset($this-&gt;clients[$i]))
              {
                  if(in_array($this-&gt;clients[$i]-&gt;socket, $read))
                  {
                      $input = socket_read($this-&gt;clients[$i]-&gt;socket, $this-&gt;max_read);
                      if($input == null)
                      {
                          $this-&gt;disconnect($i);
                      }
                      else
                      {
                          SocketServer::debug("{$i}@{$this-&gt;clients[$i]-&gt;ip} --&gt; {$input}");
                          $this-&gt;trigger_hooks("INPUT",$this-&gt;clients[$i],$input);
                      }
                  }
              }
          }
          return true;
      }
  
      /*! @function   disconnect
          @abstract   Disconnects a client from the server.
          @param      int - Index of the client to disconnect.
          @param      string  - Message to send to the hooks
          @result     void
      */
      public function disconnect($client_index,$message = "")
      {
          $i = $client_index;
          SocketServer::debug("Client {$i} from {$this-&gt;clients[$i]-&gt;ip} Disconnecting");
          $this-&gt;trigger_hooks("DISCONNECT",$this-&gt;clients[$i],$message);
          $this-&gt;clients[$i]-&gt;destroy();
          unset($this-&gt;clients[$i]);          
      }
  
      /*! @function   trigger_hooks
          @abstract   Triggers Hooks for a certain command.
          @param      string  - Command who's hooks you want to trigger.
          @param      object  - The client who activated this command.
          @param      string  - The input from the client, or a message to be sent to the hooks.
          @result     void
      */
      public function trigger_hooks($command,&amp;$client,$input)
      {
          if(isset($this-&gt;hooks[$command]))
          {
              foreach($this-&gt;hooks[$command] as $function)
              {
                  //SocketServer::debug("Triggering Hook '{$function}' for '{$command}'");
                  $continue = call_user_func($function,$this,$client,$input);
                  if($continue === FALSE) { break; }
              }
          }
      }
  
      /*! @function   infinite_loop
          @abstract   Runs the server code until the server is shut down.
          @see        loop_once
          @param      void
          @result     void
      */
      public function infinite_loop()
      {
          $test = true;
          do
          {
              $test = $this-&gt;loop_once();
          }
          while($test);
      }
  
      /*! @function   debug
          @static
          @abstract   Outputs Text directly.
          @discussion Yeah, should probably make a way to turn this off.
          @param      string  - Text to Output
          @result     void
      */
      public static function debug($text)
      {
          echo("{$text}\r\n");
      }
  
      /*! @function   socket_write_smart
          @static
          @abstract   Writes data to the socket, including the length of the data, and ends it with a CRLF unless specified.
          @discussion It is perfectly valid for socket_write_smart to return zero which means no bytes have been written. Be sure to use the === operator to check for FALSE in case of an error. 
          @param      resource- Socket Instance
          @param      string  - Data to write to the socket.
          @param      string  - Data to end the line with.  Specify a "" if you don't want a line end sent.
          @result     mixed   - Returns the number of bytes successfully written to the socket or FALSE on failure. The error code can be retrieved with socket_last_error(). This code may be passed to socket_strerror() to get a textual explanation of the error.
      */
      public static function socket_write_smart(&amp;$sock,$string,$crlf = "\r\n")
      {
          SocketServer::debug("&lt;-- {$string}");
          if($crlf) { $string = "{$string}{$crlf}"; }
          return socket_write($sock,$string,strlen($string));
      }
  
      /*! @function   __get
          @abstract   Magic Method used for allowing the reading of protected variables.
          @discussion You never need to use this method, simply calling $server-&gt;variable works because of this method's existence.
          @param      string  - Variable to retrieve
          @result     mixed   - Returns the reference to the variable called.
      */
      function &amp;__get($name)
      {
          return $this-&gt;{$name};
      }
  }
  
  /*! @class      SocketServerClient
      @author     Navarr Barnier
      @abstract   A Client Instance for use with SocketServer
   */
  class SocketServerClient
  {
      /*! @var        socket
          @abstract   resource - The client's socket resource, for sending and receiving data with.
       */
      protected $socket;
  
      /*! @var        ip
          @abstract   string - The client's IP address, as seen by the server.
       */
      protected $ip;
  
      /*! @var        hostname
          @abstract   string - The client's hostname, as seen by the server.
          @discussion This variable is only set after calling lookup_hostname, as hostname lookups can take up a decent amount of time.
          @see        lookup_hostname
       */
      protected $hostname;
  
      /*! @var        server_clients_index
          @abstract   int - The index of this client in the SocketServer's client array.
       */
      protected $server_clients_index;
  
      /*! @function   __construct
          @param      resource- The resource of the socket the client is connecting by, generally the master socket.
          @param      int - The Index in the Server's client array.
          @result     void
       */
      public function __construct(&amp;$socket,$i)
      {
          $this-&gt;server_clients_index = $i;
          $this-&gt;socket = socket_accept($socket) or die("Failed to Accept");
          SocketServer::debug("New Client Connected");
          socket_getpeername($this-&gt;socket,$ip);
          $this-&gt;ip = $ip;
      }
  
      /*! @function   lookup_hostname
          @abstract   Searches for the user's hostname and stores the result to hostname.
          @see        hostname
          @param      void
          @result     string  - The hostname on success or the IP address on failure.
       */
      public function lookup_hostname()
      {
          $this-&gt;hostname = gethostbyaddr($this-&gt;ip);
          return $this-&gt;hostname;
      }
  
      /*! @function   destroy
          @abstract   Closes the socket.  Thats pretty much it.
          @param      void
          @result     void
       */
      public function destroy()
      {
          socket_close($this-&gt;socket);
      }
  
      function &amp;__get($name)
      {
          return $this-&gt;{$name};
      }
  
      function __isset($name)
      {
          return isset($this-&gt;{$name});
      }
  }
  </code></pre>