Giter Site home page Giter Site logo

php-serial's Introduction

PHP Serial

PHP Serial was written at a time where I did not know any other language than PHP and I started to get seriously bored with its abilities.

I somehow got hold of a « Citizen C2202-PD » point-of-sale display, and I wanted to play around with it. I also managed to get the documentation of it, and created a convenience class to access the serial port though the Linux file.

Afterwards, I posted it to PHP Classes, and this probably is what brought it any visibility.

Example

<?php
include 'PhpSerial.php';

// Let's start the class
$serial = new PhpSerial;

// First we must specify the device. This works on both linux and windows (if
// your linux serial device is /dev/ttyS0 for COM1, etc)
$serial->deviceSet("COM1");

// We can change the baud rate, parity, length, stop bits, flow control
$serial->confBaudRate(2400);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");

// Then we need to open it
$serial->deviceOpen();

// To write into
$serial->sendMessage("Hello !");

State of the project

Interestingly enough, this piece of code that is widely untested has created a lot if interest ever since it was created, and especially nowadays with everybody toying around with Arduinos and Raspberry Pis. I receive about 1 email every month asking for help with the code or sending patches/suggestions.

I think that it is time for me to remove the dust off this project and to give it a full visibility on modern tools, aka GitHub.

Bugs

There is lots of bugs. I know there is. I just don't know which are they.

Platform support

  • Linux: the initially supported platform, the one I used. Probably the less buggy one.
  • MacOS: although I never tried it on MacOS, it is similar to Linux and some patches were submitted to me, so I guess it is OK
  • Windows: it seems to be working for some people, not working for some others. Theoretically there should be a way to get it done.

Concerns

I have a few concerns regarding the behaviour of this code.

  • Inter-platform consistency. I seriously doubt that all operations go the same way across all platforms.
  • Read operations. Reading was never needed in my project, so all the tests I did on that matter were theoretic. I was also quite naive, so the API is probably not optimal. What we need is to re-think reading from scratch.
  • Configuration done by calling functions. This is so Java. It would be much better to be able to pass a configuration array once and for all. Furthermore, I suspect that the order of call matters, which is bad.
  • Auto-closing the device. There is an auto-close function that is registered at PHP shutdown. This sounds quite ridiculous, something has to be done about that.
  • Use exceptions. Currently there is an heavy use of the errors system to report errors (2007 baby), but this is seriously lame. They have to be replaced by actual exceptions.

Call for contribution

I have about 0 time to code or test this project. However, there is clearly a need for it.

As in all open-source projects, I need people to fit this to their needs and to contribute back their code.

What is needed, IMHO:

  • Address the concerns listed above, and find new ones.
  • Create a reproducible test environment for each OS, and prove that each feature works (basically, unit-testing).
  • Report of use cases, bugs, missing features, etc.

If you feel like doing any of those, do not hesitate to create an issue or a pull-request, I'll gladly consider consider it :)

Licence

PHP Serial Copyright (C) 2007-2014 PHP Serial's contributors (see CONTRIBUTORS file)

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

php-serial's People

Contributors

xowap avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-serial's Issues

Calling deviceOpen hangs up the PHP process

I am using Linux version 4.19.0-14-amd64 and PHP 7.4 and try to access a GSM modem.

When fopen('/dev/ttyS0', 'r+b') is called within deviceOpen() method PHP is blocking and does not resume. I have searched around and found out that people who use C open serial ports with O_RDWR | O_NDELAY mode (see here).

In PHP there is an undocumented flag n, which makes fopen using non-blocking mode. Here are my sources:

When I call $serial->deviceOpen('r+bn') with the "n" flag, my code works ;-)

I hope this will help somebody.

Logic Error in readPort

readPort will always return more characters than the amount requested. If you iterate through this loop, you'll see this. $i is the # of characters read off the serial port, which is equal to the strlen of $content until the loop exits. Let's take a request for 256 characters as an example.

1st loop: $i = 0, $count = 256; if/else loop in do-while falls through to else
2nd loop: $i = 128, $count = 256; if/else loop falls through to else
3rd loop: $i = 256 (requested amount; $count = 256; if/else loop falls through to else, because if statement is "if $i is greater than $count, then execute", and the condition for exiting the do/while loop is $i must not equal the length of $content.
4th loop: $i = 384, $count = 256; if loop triggered; function attempts to set the length of $content to $count by passing a negative value to fread, which, as far as I can tell, fails to actually do this. The value of $content is now some random value that is greater than $count, up to 384 characters, and definitely over the value of count. I've reproduced this on Ubuntu 12.04 and 14.04.

This causes the do / while condition to fail, and the loop exits (unless the value of $content is exactly 384, in which case, the loop will iterate again, and add another 128 characters).

         $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;

The fix is to restructure this to use some other logic structure, but, in the interim, if you change the logic of the if loop to "if ($i >= $count)", the loop will exit and return the requested number of characters. Note: this fix will break a ton of code that unknowingly depends on this function returning more than the requested number of characters, which, especially in serial communications, when you're dealing with small chunks of data, could result in a lot of situations where less than 128 bytes of extra characters are being pulled.

Using a non generic Prolific USB-to-Serial Comm Port

For the sake of saving time look at my stackoverflow question for overview

https://stackoverflow.com/questions/64686285/why-is-my-array-not-populating-when-reading-the-serial-port-confirmed-communica

Essentially what's happening is that this code has worked well for other scales we used, but this scale is having issues. The only difference in setup is the physical cable connection. I have confirmed through 2 serial monitors that the data is coming through, and I am able to write commands to the device.

I decided against buying a $150+ proprietary serial to usb, and instead went with the DB9 serial connection, and bought a DB9 Serial to USB cable to connect to the same USB Hub that is feeding data to the server (php files in link are running locally on server). https://www.usbgear.com/CA-232-1MB.html#:~:text=The%20PL%2D2303%20Prolific%20serial,plug%20on%20the%20other%20end.

If this script is still being supported, any leads would help tremendously on getting this to work.

Read port never get response on Windows

$serial->deviceSet("COM2"); $serial->confBaudRate(115200); $serial->deviceOpen(); $serial->sendMessage("AT+CMGF=1\n\r"); $serial->sendMessage("AT+cmgs=\"6299999999\"\n\r"); $serial->sendMessage("test \n\r"); $serial->sendMessage(chr(26)); sleep(7); var_dump($serial->readPort());

Compatibility issue with busybox stty

While it is possible to use the busybox applet stty, the check is failing because the busybox version of stty does not support the "--version" parameter.
Removing the parameter from the check inside the function phpSerial fixes this issue.

Issue in Linux

My Code is working in my local windows machine. When I upload it to my linux and test it I am getting Specified serial port is not valid.

I think it's an issue with my server with the USB port. Does anyone know how to fix it?
First in my server I couldn't find ttyUSB0 or ttyUSB1 and I used mknod /dev/ttyUSBn c 188 n to create them.
But when I tried to do the stty -F /dev/ttyUSB1 directly on my server, I am getting stty: /dev/ttyUSB1: No such device or address error. I tried everything but its not working. Please someone help me to fix this.

Windows 10 Errors

Hi, I am trying to use this class for sending SMS using GSM Modem on COM6 over Windows 10 Platform, albeit unsuccessfully. Any help will be highly appreciated. Echoing the variables at key points (as a lame debugging effort) results in the following output:

$device=COM6
MATCH? 1
$cmd=mode COM6 xon=on BAUD=9600

$ret=Device COM6 is not currently available.
$err=
$retVal=-1

Warning: Specified serial port is not valid in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 123

Warning: Unable to set the baud rate : the device is either not set or opened in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 225

Warning: Unable to set parity : the device is either not set or opened in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 292

Warning: Unable to set length of a character : the device is either not set or opened in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 346

Warning: Unable to set the length of a stop bit : the device is either not set or opened in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 399

Warning: Unable to set flow control mode : the device is either not set or opened in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 461

Warning: The device must be set before to be open in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 151

Warning: Device must be opened in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 665

Warning: Device must be opened in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 665

Warning: Device must be opened in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 665

Warning: Device must be opened in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 665

Warning: Device must be opened to read it in C:\xampp\htdocs\myboscom_sms\include\PhpSerial.php on line 580

Modified code is as follows:
`<?php
define ("SERIAL_DEVICE_NOTSET", 0);
define ("SERIAL_DEVICE_SET", 1);
define ("SERIAL_DEVICE_OPENED", 2);

/**

  • Serial port control class
    *

  • THIS PROGRAM COMES WITH ABSOLUTELY NO WARRANTIES !

  • USE IT AT YOUR OWN RISKS !
    *

  • @author Rémy Sanchez [email protected]

  • @author Rizwan Kassim [email protected]

  • @thanks Aurélien Derouineau for finding how to open serial ports with windows

  • @thanks Alec Avedisyan for help and testing with reading

  • @thanks Jim Wright for OSX cleanup/fixes.

  • @copyright under GPL 2 licence
    */
    class PhpSerial
    {
    public $_device = null;
    public $_winDevice = null;
    public $_dHandle = null;
    public $_dState = SERIAL_DEVICE_NOTSET;
    public $_buffer = "";
    public $_os = "";

    /**

    • This var says if buffer should be flushed by sendMessage (true) or
    • manually (false)
      *
    • @var bool
      */
      public $autoFlush = true;

    /**

    • Constructor. Perform some checks about the OS and setserial
      *

    • @return PhpSerial
      */
      public function PhpSerial()
      {
      setlocale(LC_ALL, "en_AU");

      $sysName = php_uname();

      if (substr($sysName, 0, 5) === "Linux") {
      $this->_os = "linux";

      if ($this->_exec("stty") === 0) {
          register_shutdown_function(array($this, "deviceClose"));
      } else {
          trigger_error(
              "No stty availible, unable to run.",
              E_USER_ERROR
          );
      }
      

      } elseif (substr($sysName, 0, 6) === "Darwin") {
      $this->_os = "osx";
      register_shutdown_function(array($this, "deviceClose"));
      } elseif (substr($sysName, 0, 7) === "Windows") {
      $this->_os = "windows";
      register_shutdown_function(array($this, "deviceClose"));
      } else {
      trigger_error("Host OS is neither osx, linux nor windows, unable " .
      "to run.", E_USER_ERROR);
      exit();
      }
      }

    //
    // OPEN/CLOSE DEVICE SECTION -- {START}
    //

    /**

    • Device set function : used to set the device name/address.

    • -> linux : use the device address, like /dev/ttyS0

    • -> osx : use the device address, like /dev/tty.serial

    • -> windows : use the COMxx device name, like COM1 (can also be used

    • with linux)
      
    • @param string $device the name of the device to be used

    • @return bool
      */
      public function deviceSet($device)
      {
      echo '
      $device='.$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 === "osx") {
          if ($this->_exec("stty -f " . $device) === 0) {
              $this->_device = $device;
              $this->_dState = SERIAL_DEVICE_SET;
      
              return true;
          }
      } elseif ($this->_os === "windows") {
          echo 'MATCH? '.preg_match("@^COM(\\d+):?$@i", $device);
          if (preg_match("@^COM(\\d+):?$@i", $device, $matches)
                  and $this->_exec(
                      //exec("mode " . $device . " xon=on BAUD=".BAUD)
                      "mode " . $device . " xon=on BAUD=".BAUD    
                  ) === 0
          ) {
              $this->_winDevice = "COM" . $matches[1];
              $this->_device = "\\.com" . $matches[1];
              $this->_dState = SERIAL_DEVICE_SET;
              echo '<br/>SERIAL_DEVICE_SET: _winDevice='.$this->_winDevice.', _device='.$this->_device.'<br/>'; 
              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;
      

      }
      }

    /**

    • Opens the device for reading and/or writing.
      *

    • @param string $mode Opening mode : same parameter as fopen()

    • @return bool
      */
      public 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);
      $this->_dHandle = @fopen($this->_winDevice, $mode);
      echo '
      fopen executed: _dHandle = '.$this->_dHandle . '
      ';
      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;
      }

    /**

    • Closes the device
      *

    • @return bool
      */
      public 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;
      }

    //
    // OPEN/CLOSE DEVICE SECTION -- {STOP}
    //

    //
    // CONFIGURE SECTION -- {START}
    //

    /**

    • Configure the Baud Rate

    • Possible rates : 110, 150, 300, 600, 1200, 2400, 4800, 9600, 38400,

    • 57600 and 115200.
      *

    • @param int $rate the rate to set the port in

    • @return bool
      */
      public 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 === "osx") {
      $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;
      }
      
      return true;
      

      } else {
      return false;
      }
      }

    /**

    • Configure parity.

    • Modes : odd, even, none
      *

    • @param string $parity one of the modes

    • @return bool
      */
      public 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
      );
      } elseif ($this->_os === "osx") {
      $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;
      }

    /**

    • Sets the length of a character.
      *

    • @param int $int length of a character (5 <= length <= 8)

    • @return bool
      */
      public 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
      );
      } elseif ($this->_os === "osx") {
      $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;
      }

    /**

    • Sets the length of stop bits.
      *

    • @param float $length the length of a stop bit. It must be either 1,

    •                   1.5 or 2. 1.5 is not supported under linux and on
      
    •                   some computers.
      
    • @return bool
      */
      public 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
      );
      } elseif ($this->_os === "osx") {
      $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;
      }

    /**

    • Configures the flow control
      *

    • @param string $mode Set the flow control mode. Availible modes :

    •                  -> "none" : no flow control
      
    •                  -> "rts/cts" : use RTS/CTS handshaking
      
    •                  -> "xon/xoff" : use XON/XOFF protocol
      
    • @return bool
      */
      public 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
      );
      } elseif ($this->_os === "osx") {
      $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;
      

      }
      }

    /**

    • Sets a setserial parameter (cf man setserial)
    • NO MORE USEFUL !
    • -> No longer supported
    • -> Only use it if you need it
    • @param string $param parameter name

    • @param string $arg parameter value

    • @return bool
      */
      public 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;
      }
      }

    //
    // CONFIGURE SECTION -- {STOP}
    //

    //
    // I/O SECTION -- {START}
    //

    /**

    • Sends a string to the device
      *

    • @param string $str string to be sent to the device

    • @param float $waitForReply time to wait for the reply (in seconds)
      */
      public function sendMessage($str, $waitForReply = 0.1)
      {
      $this->_buffer .= $str;

      if ($this->autoFlush === true) {
      $this->serialflush();
      }

      usleep((int) ($waitForReply * 1000000));
      }

    /**

    • Reads the port until no new datas are availible, then return the content.
      *

    • @param int $count Number of characters to be read (will stop before

    •               if less characters are in the buffer)
      
    • @return string
      */
      public 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" || $this->_os === "osx") {
      // Behavior in OSX isn't to wait for new data to recover, but just
      // grabs what's there!
      // Doesn't always work perfectly for me in OSX
      $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") {
      // Windows port reading procedures still buggy
      $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;
      

      }

      return false;
      }

    /**

    • Flushes the output buffer

    • Renamed from flush for osx compat. issues
      *

    • @return bool
      */
      public function serialflush()
      {
      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;
      

      }
      }

    //
    // I/O SECTION -- {STOP}
    //

    //
    // INTERNAL TOOLKIT -- {START}
    //

    public function _ckOpened()
    {
    if ($this->_dState !== SERIAL_DEVICE_OPENED) {
    trigger_error("Device must be opened", E_USER_WARNING);

        return false;
    }
    
    return true;
    

    }

    public function _ckClosed()
    {
    if ($this->_dState === SERIAL_DEVICE_OPENED) {
    trigger_error("Device must be closed", E_USER_WARNING);

        return false;
    }
    
    return true;
    

    }

    public function _exec($cmd, &$out = null)
    {
    echo '
    $cmd='.$cmd.'
    ';
    $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]);
    echo '<br/>$ret='.$ret.'<br/>';
    echo '$err='.$err.'<br/>';
    
    fclose($pipes[1]);
    fclose($pipes[2]);
    
    $retVal = proc_close($proc);
    echo '$retVal='.$retVal.'<br/>';
    if (func_num_args() == 2) $out = array($ret, $err);
    return $retVal;
    

    }

    //
    // INTERNAL TOOLKIT -- {STOP}
    //
    }`

Any ideas what is wrong? The same mode command works fine on command prompt.

Regards,

Purge COM

Hey! This is more of a question than an issue I think.
Is there a way for me to purge the port after I send a message? A function like PurgeComm that allows me to throw in the handle and the int code for the action I want to perform.
I spent so much time to do this by the exec() function or even using the send message function in this class. Obviously I didn't succeed.
Your help will be very much appreciated. Thank you.

Fix for Windows 10

For anyone having trouble on Windows 10, try this:

In the file PhpSerial.php change line 113 to:
$this->_device = 'COM' . $matches[1] . ':';

PHP-Serial Fails when run from Cron

Created a PHP script to read data froma serial port and store it in a MySql Database. This allows me to store gauge data as it is captured every 'n' minutes.

When I run the script via the ocmmand line, it runs just fine.

I set up a cron job to run it and I get the following error every time:

No stty availible, unable to run.

Checked DMESG and the TTY is there.. go back and run it via the command line and it runs.

Note regarding timing

Hello,

First of all, thank you for this!
Running perfectly on PHP 7.3.10 (XAMPP).

At first I was having trouble sending serial messages to Arduino, until I realized Arduinos reset on every connection, so I simply inserted

sleep(2);

directly after opening the serial port and before

$serial->sendMessage("Whatever");

Same thing applies to some serial Bluetooth devices.

Best regards,
Andreas

Is this project still being maintained?

Is this project still being maintained? I see some nice pull-requests so it would be great if these could be integrated. I can of course fork this project and then implement the request into my branch but I think it would be better for other people that it is kept in one place :)

If you don't have the time I'd be happy to integrate the pull-requests for you if you give me write-access to the repository.

Bug in checking if stty is in the system

I get this problem with Raspberry Pi (Minibian last version).
The script work correctly from CLI but stopped if invoked from web browser.
The apache error log show:
"PHP Fatal error: No stty availible, unable to run. in /var/www/html/PhpSerial.php on line 56"

The problem go away if i changed the line
if ($this->_exec("stty") === 0) {
with the old one:
if ($this->_exec("stty --version") === 0) {

keep open connection to avoid restart

Hi there,

thanks for the script.

The only issue that i see is that at php execution end the connection object is destroyed, therefore on every new request the connection has to be opened again and this forces an arduino restart. I considered serializing a singleton that holds the connection, but things like "database connections" should be avoided for serialization. Is there anyway to keep a connection object in memory ?

Thank you very much

Regards,

Not able to access device, showing errors xampp

After chaning php_serial at line 113

<?php
define ("SERIAL_DEVICE_NOTSET", 0);
define ("SERIAL_DEVICE_SET", 1);
define ("SERIAL_DEVICE_OPENED", 2);

/**
 * Serial port control class
 *
 * THIS PROGRAM COMES WITH ABSOLUTELY NO WARRANTIES !
 * USE IT AT YOUR OWN RISKS !
 *
 * @author Rémy Sanchez <[email protected]>
 * @author Rizwan Kassim <[email protected]>
 * @thanks Aurélien Derouineau for finding how to open serial ports with windows
 * @thanks Alec Avedisyan for help and testing with reading
 * @thanks Jim Wright for OSX cleanup/fixes.
 * @copyright under GPL 2 licence
 */
class Sms_Serial
{
    public $_device = null;
    public $_winDevice = null;
    public $_dHandle = null;
    public $_dState = SERIAL_DEVICE_NOTSET;
    public $_buffer = "";
    public $_os = "";

    /**
     * This var says if buffer should be flushed by sendMessage (true) or
     * manually (false)
     *
     * @var bool
     */
    public $autoFlush = true;

    /**
     * Constructor. Perform some checks about the OS and setserial
     *
     * @return PhpSerial
     */
    public function Sms_Serial()
    {
        setlocale(LC_ALL, "en_US");

        $sysName = php_uname();

        if (substr($sysName, 0, 5) === "Linux") {
            $this->_os = "linux";

            if ($this->_exec("stty") === 0) {
                register_shutdown_function(array($this, "deviceClose"));
            } else {
                trigger_error(
                    "No stty availible, unable to run.",
                    E_USER_ERROR
                );
            }
        } elseif (substr($sysName, 0, 6) === "Darwin") {
            $this->_os = "osx";
            register_shutdown_function(array($this, "deviceClose"));
        } elseif (substr($sysName, 0, 7) === "Windows") {
            $this->_os = "windows";
            register_shutdown_function(array($this, "deviceClose"));
        } else {
            trigger_error("Host OS is neither osx, linux nor windows, unable " .
                          "to run.", E_USER_ERROR);
            exit();
        }
    }

    //
    // OPEN/CLOSE DEVICE SECTION -- {START}
    //

    /**
     * Device set function : used to set the device name/address.
     * -> linux : use the device address, like /dev/ttyS0
     * -> osx : use the device address, like /dev/tty.serial
     * -> windows : use the COMxx device name, like COM1 (can also be used
     *     with linux)
     *
     * @param  string $device the name of the device to be used
     * @return bool
     */
    public 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 === "osx") {
                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 . " xon=on BAUD=9600")
                        ) === 0
                ) {
                    $this->_winDevice = "COM" . $matches[1];
                    //$this->_device = "\\.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;
        }
    }

    /**
     * Opens the device for reading and/or writing.
     *
     * @param  string $mode Opening mode : same parameter as fopen()
     * @return bool
     */
    public 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;
    }

    /**
     * Closes the device
     *
     * @return bool
     */
    public 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;
    }

    //
    // OPEN/CLOSE DEVICE SECTION -- {STOP}
    //

    //
    // CONFIGURE SECTION -- {START}
    //

    /**
     * Configure the Baud Rate
     * Possible rates : 110, 150, 300, 600, 1200, 2400, 4800, 9600, 38400,
     * 57600 and 115200.
     *
     * @param  int  $rate the rate to set the port in
     * @return bool
     */
    public 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 === "osx") {
                $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;
            }

            return true;
        } else {
            return false;
        }
    }

    /**
     * Configure parity.
     * Modes : odd, even, none
     *
     * @param  string $parity one of the modes
     * @return bool
     */
    public 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
            );
        } elseif ($this->_os === "osx") {
            $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;
    }

    /**
     * Sets the length of a character.
     *
     * @param  int  $int length of a character (5 <= length <= 8)
     * @return bool
     */
    public 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
            );
        } elseif ($this->_os === "osx") {
            $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;
    }

    /**
     * Sets the length of stop bits.
     *
     * @param  float $length the length of a stop bit. It must be either 1,
     *                       1.5 or 2. 1.5 is not supported under linux and on
     *                       some computers.
     * @return bool
     */
    public 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
            );
        } elseif ($this->_os === "osx") {
            $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;
    }

    /**
     * Configures the flow control
     *
     * @param  string $mode Set the flow control mode. Availible modes :
     *                      -> "none" : no flow control
     *                      -> "rts/cts" : use RTS/CTS handshaking
     *                      -> "xon/xoff" : use XON/XOFF protocol
     * @return bool
     */
    public 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
            );
        } elseif ($this->_os === "osx") {
            $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;
        }
    }

    /**
     * Sets a setserial parameter (cf man setserial)
     * NO MORE USEFUL !
     * 	-> No longer supported
     * 	-> Only use it if you need it
     *
     * @param  string $param parameter name
     * @param  string $arg   parameter value
     * @return bool
     */
    public 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;
        }
    }

    //
    // CONFIGURE SECTION -- {STOP}
    //

    //
    // I/O SECTION -- {START}
    //

    /**
     * Sends a string to the device
     *
     * @param string $str          string to be sent to the device
     * @param float  $waitForReply time to wait for the reply (in seconds)
     */
    public function sendMessage($str, $waitForReply = 0.1)
    {
        $this->_buffer .= $str;

        if ($this->autoFlush === true) {
            $this->serialflush();
        }

        usleep((int) ($waitForReply * 1000000));
    }

    /**
     * Reads the port until no new datas are availible, then return the content.
     *
     * @param int $count Number of characters to be read (will stop before
     *                   if less characters are in the buffer)
     * @return string
     */
    public 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" || $this->_os === "osx") {
            // Behavior in OSX isn't to wait for new data to recover, but just
            // grabs what's there!
            // Doesn't always work perfectly for me in OSX
            $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") {
            // Windows port reading procedures still buggy
            $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;
        }

        return false;
    }

    /**
     * Flushes the output buffer
     * Renamed from flush for osx compat. issues
     *
     * @return bool
     */
    public function serialflush()
    {
        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;
        }
    }

    //
    // I/O SECTION -- {STOP}
    //

    //
    // INTERNAL TOOLKIT -- {START}
    //

    public function _ckOpened()
    {
        if ($this->_dState !== SERIAL_DEVICE_OPENED) {
            trigger_error("Device must be opened", E_USER_WARNING);

            return false;
        }

        return true;
    }

    public function _ckClosed()
    {
        if ($this->_dState === SERIAL_DEVICE_OPENED) {
            trigger_error("Device must be closed", E_USER_WARNING);

            return false;
        }

        return true;
    }

    public 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;
    }

    //
    // INTERNAL TOOLKIT -- {STOP}
    //
}

I am not able to connect device and getting following errors

Warning: Specified serial port is not valid in C:\xampp\htdocs\gam-sms-master\Sms\phpSerial.php on line 121

Warning: Unable to set the baud rate : the device is either not set or opened in C:\xampp\htdocs\gam-sms-master\Sms\phpSerial.php on line 222

Warning: Unable to set parity : the device is either not set or opened in C:\xampp\htdocs\gam-sms-master\Sms\phpSerial.php on line 290

Warning: Unable to set length of a character : the device is either not set or opened in >C:\xampp\htdocs\gam-sms-master\Sms\phpSerial.php on line 343
object(Sms_Serial)#1 (7) { ["_device"]=> NULL ["_winDevice"]=> NULL ["_dHandle"]=> NULL ["_dState"]=> int(0) ["_buffer"]=> string(0) "" ["_os"]=> string(7) "windows" ["autoFlush"]=> bool(true) }
Warning: The device must be set before to be open in C:\xampp\htdocs\gam-sms-master\Sms\phpSerial.php on line 150

Warning: The device must be set before to be open in C:\xampp\htdocs\gam-sms-master\Sms\phpSerial.php on line 150

Warning: Device must be opened in C:\xampp\htdocs\gam-sms-master\Sms\phpSerial.php on line 662

Warning: Device must be opened to read it in C:\xampp\htdocs\gam-sms-master\Sms\phpSerial.php on line 577
PIN Incorrect

and

testserial.php file is:

require_once('Sms.php');
require_once('Sms/Interface.php');
require_once('Sms/phpSerial.php');

$pin = "0000";

try {
    $serial = new Sms_Serial;
    $serial->deviceSet("COM8");
    $serial->confBaudRate(9600);
    $serial->confParity('none');
    $serial->confCharacterLength(8);
    
    $sms = Sms::factory($serial)->insertPin($pin);

    if ($sms->sendSMS("000000000", "test Hi")) {
        echo "SMS sent\n";
    } else {
        echo "Sent Error\n";
    }

    // Now read inbox
    foreach ($sms->readInbox() as $in) {
        echo"tlfn: {$in['tlfn']} date: {$in['date']} {$in['hour']}\n{$in['msg']}\n";

        // now delete sms
        if ($sms->deleteSms($in['id'])) {
            echo "SMS Deleted\n";
        }
    }
} catch (Exception $e) {
    switch ($e->getCode()) {
        case Sms::EXCEPTION_NO_PIN:
            echo "PIN Not set\n";
            break;
        case Sms::EXCEPTION_PIN_ERROR:
            echo "PIN Incorrect\n";
            break;
        case Sms::EXCEPTION_SERVICE_NOT_IMPLEMENTED:
            echo "Service Not implemented\n";
            break;
        default:
            echo $e->getMessage();
    }
}

Doesn't work with tty made by CMUX

Hi.
I'm trying to use your code to get access to tty lines which is made by CMUX.
https://github.com/insekt/cmux
CMUX is creating 2 new virtual /dev/ttyGSM devices based on my physical ttyUSB0. ttyUSB0 is connected to GSM modem.
It works fine directly with ttyUSB0 but doesn't work with ttyGSM.

To be more specific I can send data to modem with your code via ttyGSM but I can't read reply from modem.

Sending EOF message

Hello, im new at serial connection, and i have a device which use AT Command. We're trying to send an EOF message (or ctrl+z i believe). How do you write an EOF message on PHP? we've tried chr(26) and \x1a but not success, Thank You

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.