php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #49976 Can't read anything from serial port
Submitted: 2009-10-23 17:43 UTC Modified: 2010-12-20 09:31 UTC
Votes:48
Avg. Score:4.8 ± 0.6
Reproduced:48 of 48 (100.0%)
Same Version:30 (62.5%)
Same OS:30 (62.5%)
From: rpiccini at software4u dot it Assigned:
Status: Open Package: *General Issues
PHP Version: * OS: *
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2009-10-23 17:43 UTC] rpiccini at software4u dot it
Description:
------------
Either on WIN XP or UBUNTU 9.0 can't read back any data from serial port after correctly written to.

I'm trying to talk to a fiscal printer trough a custom protocol based on ACK/NACK technique (send data -> receive answer -> respond to answer -> ...)

With a serial port scanner (and from the ticket that are correctly printed) I can see that the sent data are well received from fiscal printer.

But any "replay" to sent data (which are present if data are sent to serial port from other kind of software/programming languages) are present.

The PHP Version is 5.2.11.
There were a similar bug report on 
http://bugs.php.net/bug.php?id=35531
but its state is "closed" (even if the case history is very similar and the problem persists).

Reproduce code:
---------------
<?php
  // on UBUNTU
  $fp = fopen('/dev/ttyS0','r+');
  // on WIN XP
  /*fp = fopen('COM1:','r+');*/
  stream_set_timeout($fp, 0, 100);
  stream_set_blocking($fp,0);

  $stx = chr(2);
  $etx = chr(3);
  $string = $stx."030301346".$etx;     // command to eject paper
  fputs($fp,$string);
  echo "SENT: ".$string."<br />\n";      // display string sent to serial port
  $buffer = fread($fp,128);              // tested with several int values
  echo "RECEIVED: ".$buffer."<br />\n";  // display NOTHING!
  fclose($fp);
?> 


Expected result:
----------------
a correct ACK (chr(6)) or an incorrect NACK (chr(15)) from serial port (sent by the fiscal printer)

Actual result:
--------------
NOTHING (no a single char)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-10-23 18:22 UTC] johannes@php.net
For using the serial port from linux I'd suggest to take a look at the dio extension so you can set baud rate, parity, ... via 
dio_tcsetattr()

Are you sure your device really returns anything? did you try other serial port applications?
 [2009-10-25 15:33 UTC] rpiccini at software4u dot it
First of all sorry for my bad english.

Anyway. Yes, I'm sure that with my code can't read anything back on the serial port. Can write but can't read replies.
I've already tried with other applications and the serial port has always worked good as I expected. 
As I've already wrote in my firs post I can correclty send the same commands to the serial port using other programming languages (and also with a specific built-up application under WIN XP) and I get back the right reply from the port (ASCII chr(6) in this case) using always the same hardwar during my tests.
Just for information. I've a dual-boot PC (WIN XP and Ubuntu linux 9.04) so the hardware (PC, serial port, fiscal printer) are exactly the same for both operating system.

I'm developing a cross-platform application (WIN/Linux) so I MUST find a way to make the serial port to be read correctly on both o.s.
I don't have much experience with dio/pecl functions...but I wouldn't like to use them, I'd prefer to have the standard PHP functions (fgets/fread) working "correctly" (Why can I write correctly with fputs but can't read with fgets/fread ???).

I've also tried to insert a "sleep" between the fputs and fread operations just to verify any eventually time-related issue...but it still doesn't work:

<?php
  // on UBUNTU
  $fp = fopen('/dev/ttyS0','r+');
  // on WIN XP
  /*fp = fopen('COM1:','r+');*/
  stream_set_timeout($fp, 0, 100);
  stream_set_blocking($fp,0);

  $stx = chr(2);
  $etx = chr(3);
  $string = $stx."030301346".$etx;     // command to eject paper
  fputs($fp,$string);
  echo "SENT: ".$string."<br />\n";      // display string sent to
serial port
  usleep(200);                           // a delay before reading the port
  //sleep(1);                            // more delay tried...
  $buffer = fread($fp,128);              // tested with several int
values
  echo "RECEIVED: ".$buffer."<br />\n";  // display NOTHING!
  fclose($fp);
?> 

Curiosity. I've found a PHP class on www.phpclasses.org/browse/package/3679.html in which is developed a function for serial port reading ONLY on Linux (but it seems doesn't work!) and NOT for WINDOWS...why seems this thing so difficult to manage?? 

I do think this is a bug...pleas help me!
 [2009-10-25 20:22 UTC] jani@php.net
How about you open it in binary mode? Like this:

 $fp = fopen('/dev/ttyS0','rb+');

Might work bit better on windows..?

 [2009-10-25 20:23 UTC] jani@php.net
Oops, and this of course: 

$fp = fopen('COM1:','rb+');
 [2009-10-26 11:12 UTC] rpiccini at software4u dot it
Thanks for reply, but binary mode doesn't help to make it works. On WIN XP and Ubuntu too nothing's changed.
 
Anyway, I found a difference during fread instruction between WIN and Ubuntu that I haven't seen before (doesn't matter if binary mode is activated or not):
 
[CODE]
$buffer = fread($fp,128); 
//$buffer = fgets($fp);   // tried also with fgets
[/CODE]
 
On WIN XP "fread" (and fgets too) hangs (never ending loop), while on UBUNTU $buffer is always empty (can't read reply from serial port) but the script doesn't loop on fread and goes (for the rest of my code) correctly to the end.
 
It seems like "stream_set_blocking($fp,0)" doesn't work at all on WIN.
 
By the way, I haven't yet solved my problem...
 [2010-01-15 20:19 UTC] stash_85 at hotmail dot com
I also have the same problem trying to connect to a gprs modem via serial port.

I can send commands using fputs but the script hangs while trying to read from the resource using fgets, fread or stream_get_contents...

I think the problem, at least in my case, is that the response doesn't have an end or something and the fact that the reading limit doesn't work in this case.

The strange thing in my case is that back in 2007 i wrote an sms gateway using a GPRS modem and it used to work with fgets. The same script today, does not work.

exec('mode com9 baud=9600 data=8 stop=1 parity=n xon=on');
$fd = fopen('COM9', "r+");
if ($fd){
  stream_set_timeout($fd, 1);
  stream_set_blocking($fd, 0);
  fputs($fd, "AT\r");
  $response="";
  while(!feof($fd)){
    $response.=stream_get_contents($fd, 2); // This will not work as it hangs the script here.
//  $response.=fread($fd, 2); // This will not work as it hangs the script here.
//  $response.=fgets($fd, 2); // This will not work as it hangs the script here.
//  $response.=fgets($fd); // This will not work as it hangs the script here. It used to work back in 2007.
    $lines=ereg_replace("\r","",$response);
    $lines=explode("\n",$lines);
    if (in_array("OK",$lines)) break;
    if (in_array("ERROR",$lines)) break;
  }
  print_r($lines);
  fclose($fd);
}


I managed to make it work using the php_dio extension on windows php 5.2.9.

exec('mode com9 baud=9600 data=8 stop=1 parity=n xon=on');
$fd = dio_open('COM9', O_RDWR);
if ($fd){
  dio_write($fd, "AT\r");
  $response="";
  while(1){
    $response.=dio_read($fd, 2);
//  $response.=dio_read($fd, 5);  // This will not work as it hangs the script here.
    $lines=ereg_replace("\r","",$response);
    $lines=explode("\n",$lines);
    if (in_array("OK",$lines)) break;
    if (in_array("ERROR",$lines)) break;
  }
  print_r($lines);
  dio_close($fd);
}

RESULT: 
Array ( [0] => AT [1] => OK )

I hope i helped a bit with the above script. But please, someone has to resolve this bug. Those problems make people underestimate PHP...

--
Christos.
 [2010-12-20 09:31 UTC] jani@php.net
-Package: Feature/Change Request +Package: *General Issues
 [2010-12-20 09:31 UTC] jani@php.net
-Operating System: WIN XP / UBUNTU 9.04 +Operating System: * -PHP Version: 5.2.11 +PHP Version: *
 [2011-04-22 21:59 UTC] beekerstudios at gmail dot com
I struggled to find solutions to doing serial with php. I went so far as to do it in python, 
which I'm a novice at, but it brought to light why it wasn't working for me in php, my commands 
were just wrong. It's amazing how little documentation on it there is. Someone needs to do a good 
blog post about it. (looks at self)

On to why my actually useful comment...
Sleeping the script between fputs and fgets seems to do the job of resolving this. Yah it stalls 
the script a bit, but for the most part it's workable. It just means you can't constantly send 
messages to a device with serial commands.

function sendSerialCommand($port,$command){
    `mode $port: BAUD=9600 PARITY=N data=8 stop=1 xon=off`;
    $fp = fopen ($port.":", "r+");
    if (!$fp) {
        echo "Uh-oh. Port not opened.";
    } else {
	if($command == "on"){
	    echo "Turning on.<br />";
	    $string = "\x2a\x70\x6f\x77\x3d\x6f\x6e\x23";
        } else if($command == "off"){
	    echo "Turning off.<br />";
	    $string = "\x2a\x70\x6f\x77\x3d\x6f\x66\x66\x23";
        } else if($command == "status"){
	    echo "Checking status.<br />";
	    $string = "\x2a\x70\x6f\x77\x3d\x3f\x23";
	}
	fputs ($fp, $string);
	sleep(1);
	$response="";
  	while(!feof($fp)){
    	    $response.=stream_get_contents($fp, 2);
    	    $lines=explode("\n",$response);
  	}
  	print_r($lines);
        fclose ($fp);
    }
}
sendSerialCommand("COM3","on")
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Tue Sep 17 08:01:27 2019 UTC