blob: ee34208f2e2931e0ce6306fe7383922448ad6e83 [file]
#!/usr/bin/env python
#
# Serial port enumeration. Console tool and backend selection.
#
# This file is part of pySerial. https://github.com/pyserial/pyserial
# (C) 2011-2015 Chris Liechti <cliechti@gmx.net>
#
# SPDX-License-Identifier: BSD-3-Clause
"""\
This module will provide a function called comports that returns an
iterable (generator or list) that will enumerate available com ports. Note that
on some systems non-existent ports may be listed.
Additionally a grep function is supplied that can be used to search for ports
based on their descriptions or hardware ID.
"""
from __future__ import absolute_import
import sys
import os
import re
# chose an implementation, depending on os
#~ if sys.platform == 'cli':
#~ else:
if os.name == 'nt': # sys.platform == 'win32': # pragma: no cover
from serial.tools.list_ports_windows import comports
elif os.name == 'posix': # pragma: no cover
from serial.tools.list_ports_posix import comports
else: # pragma: no cover
raise ImportError("Sorry: no implementation for your platform ('{}') available".format(os.name))
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def grep(regexp, include_links=False):
"""\
Search for ports using a regular expression. Port name, description and
hardware ID are searched. The function returns an iterable that returns the
same tuples as comport() would do.
"""
r = re.compile(regexp, re.I)
for info in comports(include_links):
port, desc, hwid = info
if r.search(port) or r.search(desc) or r.search(hwid):
yield info
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def main():
import argparse
parser = argparse.ArgumentParser(description='Serial port enumeration')
parser.add_argument(
'regexp',
nargs='?',
help='only show ports that match this regex')
parser.add_argument(
'-v', '--verbose',
action='store_true',
help='show more messages')
parser.add_argument(
'-q', '--quiet',
action='store_true',
help='suppress all messages')
parser.add_argument(
'-1', '--only-one',
action='store_true',
help='require exactly one matching entry, otherwise error')
parser.add_argument(
'-n',
type=int,
help='only output the N-th entry')
parser.add_argument(
'-s', '--include-links',
action='store_true',
help='include entries that are symlinks to real devices')
args = parser.parse_args()
# get list of ports
if args.regexp:
if not args.quiet:
sys.stderr.write("Filtered list with regexp: {!r}\n".format(args.regexp))
found = list(grep(args.regexp, include_links=args.include_links))
else:
found = list(comports(include_links=args.include_links))
found.sort()
# filter ports if specified
if args.only_one and len(found) != 1:
sys.stderr.write("Error: {} serial ports{}{}{}\n".format(
len(found) or "no",
" match {!r}".format(args.regexp) if args.regexp else "",
": {}, {}".format(found[0][0], found[1][0]) if found else "",
", ..." if len(found) > 2 else ""
))
sys.exit(1)
if args.n is not None:
found = [found[args.n - 1]] if 1 <= args.n <= len(found) else []
# list ports
for port, desc, hwid in found:
sys.stdout.write("{:20}\n".format(port))
if args.verbose:
sys.stdout.write(" desc: {}\n".format(desc))
sys.stdout.write(" hwid: {}\n".format(hwid))
if not args.quiet:
if found:
sys.stderr.write("{} ports found\n".format(len(found)))
else:
sys.stderr.write("no ports found\n")
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# test
if __name__ == '__main__': # pragma: no cover
main()