Asked  2 Years ago    Answers:  5   Viewed   116 times

I am looking for a way to communicate with RS232 serial COM port on windows. I have found 2 solutions on the net, one which is not totally free (introduces deliberate delays on the function) and another with limited capability on Windows. The latter can only write to a COM port on Windows, not read.

I can't look at the code of the first solution since it is compiled into a .dll (makes sense, otherwise people can just edit the delay and not purchase it...) and the second one seems only to use fopen() to open the port and later fwrite() to it for writing, just like one would do to a stream. But apparently freading it returns nothing.

I know it's possible as the first solution did it, although it does require Apache to use php-cgi module instead of php5module.

Any ideas?

 Answers

5

Every solution above is either inefficient or too much work.

You can just use the PHP-DIO library (dio_fcntl, dio_open, dio_read, dio_write, dio_seek, ...). It's also in the PHP manual's entry for DIO:

This PECL package isn't available by default. To get it for Windows if you have PHP 5.2.x greater than 5.2.6, you can download it as part of a ZIP:

  • Thread-safe (for Apache)

  • Non-thread-safe (for IIS)

Both of these links were found in http://www.deveblog.com/index.php/download-pecl-extensions-for-windows/

Here is the build from Linux, just get it and do the phpize/configure/make/make install thing.

I don't know whether it should be used in an Apache session, but go for it.

Tuesday, December 6, 2022
2

Yes, IIS supports integrated Windows authentication. Access the 'Authentication' option for your website...

...and change the 'Windows Authentication' item to 'enabled' (and perhaps 'Anonymous Authentication' to 'disabled' if you want to force users to authenticate)...

More details are available on Technet.

In PHP the username should be populated in the $_SERVER superglobal. I think as AUTH_USER, but I can't confirm that right now. Use var_dump($_SERVER); to find the correct key.

Wednesday, November 2, 2022
 
2

the php_serial.class.php is kind of broken, i had to adapt it to get a reading out of it, so instead of using the following from the reader method: $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));
                    }

i used just this

     //trigger_error("reading 0 ".$i, E_USER_WARNING);
     $content .= fread($this->_dHandle, $count);


     return str_split($content);

then reconstruct the byte string in php

Sunday, December 11, 2022
 
4

If the linked example fails it means that RXTX hasn't detected any serial ports on your machine. You may have a serial port on your machine but one of the reasons it isn't recognized by your OS might be because it is actually a serial-to-USB adapter, and is being recognized as an USB port.

If you are on Linux, serial ports usually look like this:

ls /dev/ttyS*

outputs:

/dev/ttyS0
/dev/ttyS1
/dev/ttyS2

the adapted port might look like this:

/dev/ttyUSB0

If you can see some output on your serial attached device (e.g. POS printer or LCD display) you can test it like this:

echo 'hello' > /dev/ttyUSB0

and the device should show the 'hello' string if it is attached to that port and everything is working properly.

However, I would definitely recommend Java simple serial connector library over RxTx. We have tried both in an commercial POS application (>1M tickets at this time).

RxTx is being used for sequential printing successfully. In the print scenario the RxTx library was called upon sequentially and used only to send the data to the port. Only some serial flags were red the detect to buissiness of the device.

But because of its limitations we simply could not use it for reading input from a serially connected IButton. In the iButton scenario the data is expected to be received asynchronously from the port. There were constant bugs and hangs when we tried to implement it with RxTx, but with JSSC it was implemented almost immediatley.

Sunday, October 23, 2022
 
clef
 
2

The first workable solution I have is to use a powershell script. It takes in parameters from Lua including the COM port, Baud Rate, and a string to write.

First off, here the the Lua Script.

writeThenReadCOMinLua.lua

local comPort = "COM2"
local baud = "9600"
local dataToWrite = "Hello. Is Anyone There?"
--run the powershell script with supplied params. Spaces are important.
local file = io.popen("powershell.exe -file ./liblocal/psLibs/writeAndReadCOM.ps1 
"..comPort.. " " .. baud .. " " .. dataToWrite)

--Wait for a reply (indefinitely)
local rslt = file:read("*a")
print("Response: " .. rslt)

And, the powershell script to write then wait for reply.

writeAndReadCOM.ps1

$nargs = $args.Count #args is the list of input arguments
$comPortName=$args[0] #This is the com port. It has zero spaces
$baud = $args[1] #this is the numberical baud rate
#the remainder of the arguments are processed below


#Combine argument 2,3,...,n with a space because of command prompt shortfalls to pass arguments with spaces
$dataToWrite = ""
For ($i=2; $i -le $nargs ; $i++) {
    $dataToWrite = "$($dataToWrite) $($args[$i])"
}

#$port= new-Object System.IO.Ports.SerialPort COM2,9600,None,8,one
$port= new-Object System.IO.Ports.SerialPort $comPortName,$baud,None,8,one

#open port if it's not yet open
IF ($port.IsOpen) {
    #already open
} ELSE {
    #open port
    $port.Open()
}

#write the data
$port.WriteLine($dataToWrite)

#wait for a response (must end in newline). This removes the need to have a hard coded delay
$line = $port.ReadLine()
Write-Host $line #send read data out

#if the response was multiple lines, then read the rest of the buffer. If the port was just opened.
while ($port.BytesToRead -ne 0) {
    $dataReturned = 1
    $line = $port.ReadLine()
    Write-Host $line #send read data out for the remainder of the buffer
}

$port.Close()

#IF ($dataReturned -eq 0) {'PS_NO_BYTES_TO_READ'}

There are a few things going on here. First, the serial data sent by lua may have spaces. Unfortunately, these all get separated into multiple args by the terminal, so powershell then goes and regroups them into a single string. Second, the port must be opened to read or write data. If any serial data is sent before it is opened, that data is lost.

Issue Remaining: I can't leave the port open then go do stuff in Lua and periodically check the port for new data. This is unfortunate because the hardware I am using sometimes sends data without a request, or takes a long time to reply with all the data (in the case of an iterative level calibration). Additionally, each time I open the port, the hardware restarts. At this point, I have no good solution.

Here was my attempt at a fix: Create three separate powershell scripts #1) open the port #2) read the port and return nil within 500mS if no data exists otherwise reply with all the data and #3)close it. Unfortunately, #2 throws an error about the port being closed even after #1 is run. I'd love to hear some thoughts, and will gladly update this answer with any solutions.

Many thanks to Egor for all the help so far.

Monday, December 26, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 

Browse Other Code Languages