Hardware::PortScanner - Scan serial ports to find hardware devices at various com ports, baud rates, and settings using request and expected reply message
$serial = Hardware::PortScanner->new(); $serial->scan_ports( BAUD => [ 4800, 9600 ], SETTING => [ '8N1', '7E1X' ], TEST_STRING => "V\n", VALID_REPLY_RE => '^UBW FW' ); $PortObj = $serial->connect_to_device(); OR $serial = Hardware::PortScanner->new(); $PortObj = $serial->connect_to_device(BAUD => 115200, COM => 'COM3');
This module provides methods to scan and connect to com ports for hardware removing the necessity of knowing the specific com port, baud rate and/or settings (e.g. 8N1, 7E1) of the particular device you want to connect. The module works by sending a command to available devices at a variety of baud rates, com ports and settings. If a message is received back that matches a regular expression, then the connection specifics are returned. Additionally, the module can connect to the device via Device::SerialPort or Win32::SerialPort depending upon the platform.
Unplug unused COM cables before installation (or afterword if you notice problems). See Bug/Issues below.
Run "manual_test.pl" for device specific tests
Returns an Hardware::PortScanner object.
MAX_PORT - Optional parameter to specify the high port number on your system. This will speed up the scans.
Example(s): MAX_PORT => 8 MAX_PORT => "Com5" Default if not specified: MAX_PORT => 5
This method will scan for devices at several com ports, baud rate and settings each which can be specified or defaulted. scan_port will stop scanning the current com port when a device is found and continue with the remaining com ports, baud rate and settings. Note that USB devices don't have the concept of baud and settings which is why scanning is stopped on a particular port if a device is found. Otherwise it would appear a device was found at several baud rates. scan_ports stores the results of a scan in this module's object.
Also, due the method of operation of this method, other devices that are connected to an available com port may be connected to and interrogated (e.g. sent the request message). It is assumed this will not cause undesirable behavior (doesn't for my stuff). Additionally, the device may be send the message several time since, at this time, a reply that does not match the VALID_REPLY_RE is treated as a non-response causing other setting and baud rate to be attempted.
COM - Specifies the COM ports to be searched. Can be either a com number or a string like "COM8".
Example(s): COM => [ 1, 2, "COM3", "COM8" ] COM => "COM3" Default if not specified: COM => [ qw/1..20/ ]
BAUD - Specifies the BAUD rates ports to be configured. These baud rates are not limited to reasonable values but the Device::SerialPort or Win32::SerialPort modules used to connect may complain if it doesn't like the values. A warning in scan_logs will also occur if the baud rate is invalid. Bauds are always tested in fasted to slowest or to support USB virtual devices which will connect and multiple baud rates (not that it will matter functionally).
Example(s): BAUD => [ 1200, 2400 ] BAUD => 9600 Default if not specified: BAUD => [ qw/1200 2400 4800 9600 19200 38400 57600 115200/ ]
SETTING - String(s) matching the regular expression "/^([5678])([NEO])([12])([NRX])?$/" where the first digit is the databits (5, 6, 7 or 8), the second character is the parity (N = None, E = Even, O = Odd), the third digit is the stopbits (1 or 2 - no 1.5 since it doesn't seem to be supported) and finally the handshaking character (N= none, R = RTS and X = XOFF) which is optional and defaulted to "N".
Examples: SETTING => [ "8n1", "7E1" ] SETTING => "8N1" Default if not specified: SETTING => "8N1"
TEST_STRING - A string that will produce a response from the device that can be matched against a regular expression (VALID_REPLY_RE below) to confirm the device in desired has been found. This string must include any command terminators (newlines, carriage returns, etc) that are necessary to get the device to recognize the command. Often, a version request command works well as this string.
Examples: TEST_STRING => "V\n" # Version request for a UBW (USB Bit Whacker - UBW) TEST_STRING => "VER\r" # Version request for a SSC-32 servo controller No default and required parameter.
VALID_REPLY_RE - A regular expression that, if matched, indicates the desired device has been found.
VALID_REPLY_RE => '^UBW FW [CD] Version.* ' VALID_REPLY_RE => '^SSC[-]32'
MAX_WAIT - The maximum number of seconds, as a float, to wait for the expected reply after writing/sending the TEST_STRING to the serial port being tested. This can slow down the scan_port process depending upon MAX_WAIT value, number of available ports and options (BAUDS, SETTINGS, etc). Set this to say 5 seconds if your device is not detected. Then, assuming it is now detected, print a scan report to see the number of seconds before the response was recieved. Set MAX_WAIT to a figure higher than this.
This feature was added when my SSC-32 Servo controller failed to respond quickly enough to a version request to get detected (but only on Ubuntu strangly). Default is around .1 seconds which is the minimum even if set to 0.
MAX_WAIT => 2 MAX_WAIT => 0.23
This method will connect to a com port as specified by the parameters and return a standard *::SerialPort object if successful. If no parameters are given, then connect_to_device will attempt to connect to the device found by the previous scan_port. A errror will be given if no device was found (or scan_port was not invoked) or more than one device was found.
COM - Specifies the COM ports to be searched. Can be either as a com number or in with a string like "COM8".
Example(s): COM => 1 COM => "COM3"
Example(s): BAUD => 9600
Examples: SETTING => "7E1" SETTING => "8N1" Default if not specified: SETTING => "8N1"
DEVICE - A Hardware::PortScanner::Device object returned from found_devices(). This option will pull the need connection parameters from the device specified and is incompatible with the other options.
Examples: DEVICE => ($serial->found_devices)[0] # Use the first device found DEVICE => $device_obj
This method will return the number of devices successfully found by the previous scan_port()
This method will return an array of devices objects (Hardware::PortScanner::Device objects) successfully found by the previous scan_port()
Returns the *::SerialPort connection from the connect_to_device() method (see above). Additional *::SerialPort methods could be done against this object.
scan_log returns an array of info/debug messages to assist the end user in identify device not found issues. As an example, the code below was used to search for a USB Bit Whacker (UBW). An example of its use:
scan_log
$serial = Hardware::PortScanner->new(); $serial->scan_ports( COM => [ 3, 11 ], BAUD => [ 4800, 9600 ], SETTING => [ '8N1', '7E1X' ], TEST_STRING => "V\n", VALID_REPLY_RE => '^UBW FW' ); foreach ($serial->scan_log) { print "$_\n"; } Generated the following output: Scan Ports Request ================== Scan Port COM3 @ /dev/ttyS2 Checking with baudrate of 9600 Checking with setting of 7E1X Sending test string "V\n" Received back from device "" Checking with setting of 8N1 Sending test string "V\n" Received back from device "" Checking with baudrate of 4800 Checking with setting of 7E1X Sending test string "V\n" Received back from device "" Checking with setting of 8N1 Sending test string "V\n" Received back from device "" Scan Port COM11 @ /dev/ttyS10 Checking with baudrate of 9600 Checking with setting of 7E1X Sending test string "V\n" Received back from device "UBW FW D Version 1.4.3" Matched valid reply RE so returning
Convenience method to print out the scan_log (see above). Functionally equivalent to the following code:
foreach ($serial->scan_log) { print "$_\n"; }
These methods provide connection information for a device objects as returned from found_devices().
Returns the com number of the provided device.
Returns the baud rate of the provided device.
Returns the databits of the provided device.
Returns the parity of the provided device.
Returns the stopbits of the provided device.
Returns the handshake of the provided device.
Returns the port name of the provided device. Which is suitable for the PortName parameter in the *::SerialPort new command.
Below is an example from Device::SerialPort where the port name is used as "$PortName".
$PortObj = new Device::SerialPort ($PortName, $quiet, $lockfile) || die "Can't open $PortName: $!\n";
Attempts were made to minimize the dependencies in case this module is being deployed on a minimal embedded system. However, some are required for proper functioning.
Device::SerialPort from CPAN if using a Linux based system (including Cygwin)
Win32::SerialPort from CPAN if using Windows
Carp
Cygwin, Windows (but least tested) and Ubuntu
Strange behavior (e.g. lock ups, odd low level errors, etc) occurs sometimes when some COM cables are plugged in but not attached to anything. Only seen this happen when testing on Windows.
Have seen Device::SerialPort freeze (never return) when configuring certain handshaking settings (5N1R) on particular com ports. Don't know if this was due to Device::SerialPort, Windows, Cygwin (which I was using at the time) or the COM hardware. I backed off the handshaking tests in the test scripts because of this.
Under certain circumstances the *::SerialPort warning of "can't getattr: Bad file descriptor" or "can't getattr: Input/Output ...: occurs. This always occured on a particular port when a particular device I had on that port had a low battery or a particular unconnect cable. This has been mitigated a bit by ignoring these errors during a connect attempt. They do show up however in a scan_report.
Add a write then read method to wrap the lower level *::SerialPort commands of write and read. This would also use the MAX_WAIT parameter provided to the new() or provided as a option to this command.
Complete and improve documentation
Consider any features upon request
Add more tests during installation
John Dennis <jdennis30064@galileotech.com>
Copyright (C) 2009 by John Dennis This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.1 or, at your option, any later version of Perl 5 you may have available.
To install Hardware::PortScanner, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Hardware::PortScanner
CPAN shell
perl -MCPAN -e shell install Hardware::PortScanner
For more information on module installation, please visit the detailed CPAN module installation guide.