<?php
/**
 * @author  mexxval
 * @link  http://blog.sci-smart.ru
 */


interface ScalesComPort {
  function open();
  function close();
  function write($data);
  function read($len);
}

class LocalScalesComPort implements ScalesComPort {
  protected $fp;
  protected $tty;
  protected $timeout = 5;

  public function __construct($tty) {
    $this->tty = $tty;
  }
  public function close() {
      if ($this->fp !== null) {
      @fclose($this->fp);
      }
      $this->fp = null;
      return true;
  }
  public function open($timeout = 5) {
    $this->timeout = $timeout;
    $this->fp = @fopen($this->tty, 'w+b');
    return $this->fp;
  }
  public function write($binary, $timeout = 500000) {
      if (!$this->fp) {
      return false;
      }
      # timeout in MICROseconds
      $this->setSocketTimeout($timeout);
      return @fwrite($this->fp, $binary, strlen($binary));
  }
  public function read($length, $timeout = 500000) {
      $this->setSocketTimeout($timeout);
      return @fread($this->fp, $length);
  }

  protected function setSocketTimeout($usec) {
      $sec = 0;
      return stream_set_timeout($this->fp, $sec, $usec);
  }
}

class comportScalesComPort implements ScalesComPort {
  protected $fp;
  protected $tty;
  protected $timeout = 500000;

  public function __construct($tty) {
    $this->tty = $tty;
  }
  public function close() {
      if ($this->fp !== null) {
		comport_close($this->fp);
      }
      $this->fp = null;
      return true;
  }
  public function open($timeout = 500000) {
    $this->timeout = $timeout;
    $this->fp = comport_open($this->tty);
    comport_set_timeout($this->fp, 0, $this->timeout/1000, 0, $this->timeout/1000, 0);
    return $this->fp;
  }
  public function write($binary, $timeout = 500000) {
      if (!$this->fp) {
		return false;
      }
      comport_set_timeout($this->fp, 0, $this->timeout/1000, 0, $this->timeout/1000, 0);
      return comport_writeb($this->fp, $binary);
  }
  public function read($length, $timeout = 500000) {
      comport_set_timeout($this->fp, 0, $this->timeout/1000, 0, $this->timeout/1000, 0);
      return comport_readb($this->fp, $length);
  }
}

class RemoteScalesPort extends LocalScalesComPort implements ScalesComPort {
  protected $host;
  protected $port;
  public function __construct($host, $port) {
    $this->host = $host;
    $this->port = $port;
  }
  public function open($tmout = 3) {
    if (!$this->fp) {
      //$this->fp = @fsockopen($this->host, $this->port, $errno, $errstr, $tmout);
      $this->fp = @stream_socket_client($this->host.':'.$this->port, $errno, $errstr, $tmout);
      if (!$this->fp) {
        throw new Exception('Socket open error №'.$errno.'. '.$errstr);
      }
    }
    return $this->fp ;
  }
}

class RemoteScalesSocket extends LocalScalesComPort implements ScalesComPort {
  protected $host;
  protected $port;
  public function __construct($host, $port) {
    $this->host = $host;
    $this->port = $port;
  }
  public function open($tmout = 3) {
    if (!$this->fp) {
      $this->fp = @socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
      @socket_connect($this->fp, $this->host, $this->port);
    }
    return $this->fp;
  }
  public function close() {
    if ($this->fp !== null) {
    @socket_close($this->fp);
    }
    $this->fp = null;
    return true;
  }
  public function write($binary, $timeout = 500000) {
    if (!$this->fp)  return false;
    socket_set_option($this->fp,SOL_SOCKET, SO_SNDTIMEO, array("sec"=>0, "usec"=>$timeout));
    return @socket_write($this->fp, $binary, strlen($binary));
  }
  public function read($length, $timeout = 500000) {
    if (!$this->fp)  return false;
    socket_set_option($this->fp,SOL_SOCKET, SO_RCVTIMEO, array("sec"=>0, "usec"=>$timeout));
    return @socket_read($this->fp,$length,PHP_BINARY_READ);
  }
  protected function setSocketTimeout($usec) {
  }
}

class SshScalesComPort implements ScalesComPort {
  public function __construct($host, $tty) {
  }
  public function open(){}
  public function close(){}
  public function write($bin){}
  public function read($len){}
}


