123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- <?php
- if (!defined('BASEPATH')) {
- exit('No direct script access allowed');
- }
- define("SERIAL_DEVICE_NOTSET", 0);
- define("SERIAL_DEVICE_SET", 1);
- define("SERIAL_DEVICE_OPENED", 2);
- class Serial
- {
- var $_device = null;
- var $_windevice = null;
- var $_dHandle = null;
- var $_dState = SERIAL_DEVICE_NOTSET;
- var $_buffer = "";
- var $_os = "";
- var $autoflush = true;
- function Serial()
- {
- setlocale(LC_ALL, "en_US");
- $sysname = php_uname();
- if (substr($sysname, 0, 5) === "Linux") {
- $this->_os = "linux";
- if ($this->_exec("stty --version") === 0) {
- register_shutdown_function(array($this, "deviceClose"));
- } else {
- trigger_error("No stty availible, unable to run.", E_USER_ERROR);
- }
- } elseif (substr($sysname, 0, 7) === "Windows") {
- $this->_os = "windows";
- register_shutdown_function(array($this, "deviceClose"));
- } else {
- trigger_error("Host OS is neither linux nor windows, unable tu run.", E_USER_ERROR);
- exit();
- }
- }
- function deviceSet($device)
- {
- if ($this->_dState !== SERIAL_DEVICE_OPENED) {
- if ($this->_os === "linux") {
- if (preg_match("@^COM(\d+):?$@i", $device, $matches)) {
- $device = "/dev/ttyS" . ($matches[1] - 1);
- }
- if ($this->_exec("stty -F " . $device) === 0) {
- $this->_device = $device;
- $this->_dState = SERIAL_DEVICE_SET;
- return true;
- }
- } elseif ($this->_os === "windows") {
- if (preg_match("@^COM(\d+):?$@i", $device, $matches) and $this->_exec(exec("mode " . $device)) === 0) {
- $this->_windevice = "COM" . $matches[1];
- $this->_device = "\\.\com" . $matches[1];
- $this->_dState = SERIAL_DEVICE_SET;
- return true;
- }
- }
- //trigger_error("Specified serial port is not valid", E_USER_WARNING);
- return false;
- } else {
- //trigger_error("You must close your device before to set an other one", E_USER_WARNING);
- return false;
- }
- }
- function deviceOpen($mode = "r+b")
- {
- if ($this->_dState === SERIAL_DEVICE_OPENED) {
- //trigger_error("The device is already opened", E_USER_NOTICE);
- return true;
- }
- if ($this->_dState === SERIAL_DEVICE_NOTSET) {
- //trigger_error("The device must be set before to be open", E_USER_WARNING);
- return false;
- }
- if (!preg_match("@^[raw]\+?b?$@", $mode)) {
- //trigger_error("Invalid opening mode : " . $mode . ". Use fopen() modes.", E_USER_WARNING);
- return false;
- }
- $this->_dHandle = @fopen($this->_device, $mode);
- if ($this->_dHandle !== false) {
- stream_set_blocking($this->_dHandle, 0);
- $this->_dState = SERIAL_DEVICE_OPENED;
- return true;
- }
- $this->_dHandle = null;
- trigger_error("Unable to open the device", E_USER_WARNING);
- return false;
- }
- function deviceClose()
- {
- if ($this->_dState !== SERIAL_DEVICE_OPENED) {
- return true;
- }
- if (fclose($this->_dHandle)) {
- $this->_dHandle = null;
- $this->_dState = SERIAL_DEVICE_SET;
- return true;
- }
- trigger_error("Unable to close the device", E_USER_ERROR);
- return false;
- }
- function confBaudRate($rate)
- {
- if ($this->_dState !== SERIAL_DEVICE_SET) {
- trigger_error("Unable to set the baud rate : the device is either not set or opened", E_USER_WARNING);
- return false;
- }
- $validBauds = array(
- 110 => 11,
- 150 => 15,
- 300 => 30,
- 600 => 60,
- 1200 => 12,
- 2400 => 24,
- 4800 => 48,
- 9600 => 96,
- 19200 => 19,
- 38400 => 38400,
- 57600 => 57600,
- 115200 => 115200
- );
- if (isset($validBauds[$rate])) {
- if ($this->_os === "linux") {
- $ret = $this->_exec("stty -F " . $this->_device . " " . (int)$rate, $out);
- } elseif ($this->_os === "windows") {
- $ret = $this->_exec("mode " . $this->_windevice . " BAUD=" . $validBauds[$rate], $out);
- } else {
- return false;
- }
- if ($ret !== 0) {
- trigger_error("Unable to set baud rate: " . $out[1], E_USER_WARNING);
- return false;
- }
- }
- }
- function confParity($parity)
- {
- if ($this->_dState !== SERIAL_DEVICE_SET) {
- trigger_error("Unable to set parity : the device is either not set or opened", E_USER_WARNING);
- return false;
- }
- $args = array(
- "none" => "-parenb",
- "odd" => "parenb parodd",
- "even" => "parenb -parodd",
- );
- if (!isset($args[$parity])) {
- trigger_error("Parity mode not supported", E_USER_WARNING);
- return false;
- }
- if ($this->_os === "linux") {
- $ret = $this->_exec("stty -F " . $this->_device . " " . $args[$parity], $out);
- } else {
- $ret = $this->_exec("mode " . $this->_windevice . " PARITY=" . $parity{0}, $out);
- }
- if ($ret === 0) {
- return true;
- }
- trigger_error("Unable to set parity : " . $out[1], E_USER_WARNING);
- return false;
- }
- function confCharacterLength($int)
- {
- if ($this->_dState !== SERIAL_DEVICE_SET) {
- trigger_error("Unable to set length of a character : the device is either not set or opened", E_USER_WARNING);
- return false;
- }
- $int = (int)$int;
- if ($int < 5) $int = 5;
- elseif ($int > 8) $int = 8;
- if ($this->_os === "linux") {
- $ret = $this->_exec("stty -F " . $this->_device . " cs" . $int, $out);
- } else {
- $ret = $this->_exec("mode " . $this->_windevice . " DATA=" . $int, $out);
- }
- if ($ret === 0) {
- return true;
- }
- trigger_error("Unable to set character length : " . $out[1], E_USER_WARNING);
- return false;
- }
- function confStopBits($length)
- {
- if ($this->_dState !== SERIAL_DEVICE_SET) {
- trigger_error("Unable to set the length of a stop bit : the device is either not set or opened", E_USER_WARNING);
- return false;
- }
- if ($length != 1 and $length != 2 and $length != 1.5 and !($length == 1.5 and $this->_os === "linux")) {
- trigger_error("Specified stop bit length is invalid", E_USER_WARNING);
- return false;
- }
- if ($this->_os === "linux") {
- $ret = $this->_exec("stty -F " . $this->_device . " " . (($length == 1) ? "-" : "") . "cstopb", $out);
- } else {
- $ret = $this->_exec("mode " . $this->_windevice . " STOP=" . $length, $out);
- }
- if ($ret === 0) {
- return true;
- }
- trigger_error("Unable to set stop bit length : " . $out[1], E_USER_WARNING);
- return false;
- }
- function confFlowControl($mode)
- {
- if ($this->_dState !== SERIAL_DEVICE_SET) {
- trigger_error("Unable to set flow control mode : the device is either not set or opened", E_USER_WARNING);
- return false;
- }
- $linuxModes = array(
- "none" => "clocal -crtscts -ixon -ixoff",
- "rts/cts" => "-clocal crtscts -ixon -ixoff",
- "xon/xoff" => "-clocal -crtscts ixon ixoff"
- );
- $windowsModes = array(
- "none" => "xon=off octs=off rts=on",
- "rts/cts" => "xon=off octs=on rts=hs",
- "xon/xoff" => "xon=on octs=off rts=on",
- );
- if ($mode !== "none" and $mode !== "rts/cts" and $mode !== "xon/xoff") {
- trigger_error("Invalid flow control mode specified", E_USER_ERROR);
- return false;
- }
- if ($this->_os === "linux")
- $ret = $this->_exec("stty -F " . $this->_device . " " . $linuxModes[$mode], $out);
- else
- $ret = $this->_exec("mode " . $this->_windevice . " " . $windowsModes[$mode], $out);
- if ($ret === 0) return true;
- else {
- trigger_error("Unable to set flow control : " . $out[1], E_USER_ERROR);
- return false;
- }
- }
- function setSetserialFlag($param, $arg = "")
- {
- if (!$this->_ckOpened()) return false;
- $return = exec("setserial " . $this->_device . " " . $param . " " . $arg . " 2>&1");
- if ($return{0} === "I") {
- trigger_error("setserial: Invalid flag", E_USER_WARNING);
- return false;
- } elseif ($return{0} === "/") {
- trigger_error("setserial: Error with device file", E_USER_WARNING);
- return false;
- } else {
- return true;
- }
- }
- function sendMessage($str, $waitForReply = 0.1)
- {
- $this->_buffer .= $str;
- if ($this->autoflush === true) $this->flush();
- usleep((int)($waitForReply * 1000000));
- }
- function readPort($count = 0)
- {
- if ($this->_dState !== SERIAL_DEVICE_OPENED) {
- trigger_error("Device must be opened to read it", E_USER_WARNING);
- return false;
- }
- if ($this->_os === "linux") {
- $content = "";
- $i = 0;
- if ($count !== 0) {
- do {
- if ($i > $count) $content .= fread($this->_dHandle, ($count - $i));
- else $content .= fread($this->_dHandle, 128);
- } while (($i += 128) === strlen($content));
- } else {
- do {
- $content .= fread($this->_dHandle, 128);
- } while (($i += 128) === strlen($content));
- }
- return $content;
- } elseif ($this->_os === "windows") {
- $content = "";
- $i = 0;
- if ($count !== 0) {
- do {
- if ($i > $count) {
- $content .= fread($this->_dHandle, ($count - $i));
- } else {
- $content .= fread($this->_dHandle, 128);
- }
- } while (($i += 128) === strlen($content));
- } else {
- do {
- $content .= @fread($this->_dHandle, 128);
- } while (($i += 128) === strlen($content));
- }
- return $content;
- }
- trigger_error("Reading serial port is not implemented for Windows", E_USER_WARNING);
- return false;
- }
- function flush()
- {
- if (!$this->_ckOpened()) return false;
- if (fwrite($this->_dHandle, $this->_buffer) !== false) {
- $this->_buffer = "";
- return true;
- } else {
- $this->_buffer = "";
- trigger_error("Error while sending message", E_USER_WARNING);
- return false;
- }
- }
- function _ckOpened()
- {
- if ($this->_dState !== SERIAL_DEVICE_OPENED) {
- trigger_error("Device must be opened", E_USER_WARNING);
- return false;
- }
- return true;
- }
- function _ckClosed()
- {
- if ($this->_dState !== SERIAL_DEVICE_CLOSED) {
- trigger_error("Device must be closed", E_USER_WARNING);
- return false;
- }
- return true;
- }
- function _exec($cmd, &$out = null)
- {
- $desc = array(
- 1 => array("pipe", "w"),
- 2 => array("pipe", "w")
- );
- $proc = proc_open($cmd, $desc, $pipes);
- $ret = stream_get_contents($pipes[1]);
- $err = stream_get_contents($pipes[2]);
- fclose($pipes[1]);
- fclose($pipes[2]);
- $retVal = proc_close($proc);
- if (func_num_args() == 2) $out = array($ret, $err);
- return $retVal;
- }
- }
|