PHP - Reading COM Port from Windows

17,423

If you can guarantee that you're on Windows, I might recommend an interesting approach: Use either COM (as in, Microsoft's COM, not serial port) or .NET.

There's a free .NET class that I regularly use called CommStudio Express. I've found it to be very reliable, but you can always use the standard SerialPort class built into .NET if you don't need to worry about a USB-to-serial adapter getting unplugged randomly.

In any case, it's easy enough to get at a .NET class in PHP with the DOTNET class:

$serial = new DOTNET('system', 'System.IO.Ports.SerialPort');
$serial->PortName = 'COM3';
$serial->Open();

I haven't tested this code (not on Windows at the moment), but something like that should work just fine. You can then proceed to use all of the regular .NET methods within PHP.

Share:
17,423
StackOverflowNewbie
Author by

StackOverflowNewbie

Updated on June 28, 2022

Comments

  • StackOverflowNewbie
    StackOverflowNewbie almost 2 years

    The following is a library for serial communications via PHP: http://www.phpclasses.org/package/3679-PHP-Communicate-with-a-serial-port.html. The problem is that the method readPort is not fully implemented. It can read in a *nix environment, but apparently not in a Windows environment. The method:

    /**
     * Reads the port until no new datas are availible, then return the content.
     *
     * @pararm int $count number of characters to be read (will stop before
     *  if less characters are in the buffer)
     * @return string
     */
    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")
        {
            /* Do nohting : not implented yet */
        }
    
        trigger_error("Reading serial port is not implemented for Windows", E_USER_WARNING);
        return false;
    }
    

    The author states:

    ==> /!\ WARNING /!\ : it's working with linux for r/w, but with windows i've only been able to make write working. If you're a windows user, try to access the serial port through network with serproxy instead.

    The limitation of the PHP class library has been mentioned in SO several times already. I haven't found a decent solution. Reading is imperative for my application.

    Does anyone here know what to do?

  • StackOverflowNewbie
    StackOverflowNewbie about 12 years
    The solution needs to work on Windows, *Nix, etc. Seems like I should look into Java, but the web app is already being built on PHP. That's why I am hoping for a PHP solution. The .NET class to PHP solution sounds tempting, but is that a purely Windows solution? Would I be able to take advantage of a .NET class in *nix, Mac, etc. environment?
  • Brad
    Brad about 12 years
    No, the .NET and COM (again, Microsoft COM not serial port) solutions are Windows only. Short of abstracting this with different methods for different systems, I don't have a solution. It seems that there should definitely be a way though. There's no fairly standard way to fopen a device, is there? I'm very unfamiliar at the lower levels of PHP from this perspective.
  • scipilot
    scipilot over 8 years
    For what it's worth, you need to specify the full assembly details: $serial = new DOTNET('System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089', 'System.IO.Ports.SerialPort'); . However - the Open method is not COM visible (giving the error "com_exception: Failed to instantiate .Net object [Unwrapped, QI for IDispatch] [0x80004002] No such interface supported"), so... I don't think this will work without writing a .net wrapper to export it.