blob: 243b560a24b023135ffb5339dbbc69467cea3544 [file] [log] [blame]
cliechti6fa19112011-08-19 01:50:49 +00001#! python
2#
cliechti6fa19112011-08-19 01:50:49 +00003# This module implements a special URL handler that uses the port listing to
4# find ports by searching the string descriptions.
5#
Chris Liechti3e02f702015-12-16 23:06:04 +01006# This file is part of pySerial. https://github.com/pyserial/pyserial
Chris Liechti5fe3bdd2015-08-07 00:02:44 +02007# (C) 2011-2015 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02008#
9# SPDX-License-Identifier: BSD-3-Clause
cliechti6fa19112011-08-19 01:50:49 +000010#
Chris Liechti757d3ed2015-12-22 22:30:10 +010011# URL format: hwgrep://<regexp>&<option>
12#
13# where <regexp> is a Python regexp according to the re module
14#
15# violating the normal definition for URLs, the charachter `&` is used to
16# separate parameters from the arguments (instead of `?`, but the question mark
17# is heavily used in regexp'es)
18#
19# options:
20# n=<N> pick the N'th entry instead of the first one (numbering starts at 1)
cliechti6fa19112011-08-19 01:50:49 +000021
22import serial
23import serial.tools.list_ports
24
Chris Liechti5fe3bdd2015-08-07 00:02:44 +020025try:
26 basestring
27except NameError:
28 basestring = str # python 3
cliechti6fa19112011-08-19 01:50:49 +000029
Chris Liechti033f17c2015-08-30 21:28:04 +020030
Chris Liechti5fe3bdd2015-08-07 00:02:44 +020031class Serial(serial.Serial):
32 """Just inherit the native Serial port implementation and patch the port property."""
33
34 @serial.Serial.port.setter
35 def port(self, value):
cliechti6fa19112011-08-19 01:50:49 +000036 """translate port name before storing it"""
cliechti9a3809e2011-08-19 23:43:10 +000037 if isinstance(value, basestring) and value.startswith('hwgrep://'):
Chris Liechti3ad62fb2015-08-29 21:53:32 +020038 serial.Serial.port.__set__(self, self.from_url(value))
cliechti6fa19112011-08-19 01:50:49 +000039 else:
Chris Liechti5fe3bdd2015-08-07 00:02:44 +020040 serial.Serial.port.__set__(self, value)
cliechti6fa19112011-08-19 01:50:49 +000041
Chris Liechti3ad62fb2015-08-29 21:53:32 +020042 def from_url(self, url):
cliechti6fa19112011-08-19 01:50:49 +000043 """extract host and port from an URL string"""
Chris Liechtifbdd8a02015-08-09 02:37:45 +020044 if url.lower().startswith("hwgrep://"):
45 url = url[9:]
Chris Liechti757d3ed2015-12-22 22:30:10 +010046 n = 0
47 args = url.split('&')
48 regexp = args.pop(0)
49 for arg in args:
50 if '=' in arg:
51 option, value = arg.split('=', 1)
52 else:
53 option = arg
54 value = None
55 if option == 'n':
56 # pick n'th element
57 n = int(value) - 1
58 if n < 1:
59 raise ValueError('option "n" expects a positive integer larger than 1: %r' % (value,))
60 else:
61 raise ValueError('unknown option: %r' % (option,))
cliechti6fa19112011-08-19 01:50:49 +000062 # use a for loop to get the 1st element from the generator
Chris Liechti757d3ed2015-12-22 22:30:10 +010063 for port, desc, hwid in sorted(serial.tools.list_ports.grep(regexp)):
64 if n:
65 n -= 1
66 continue
cliechti6fa19112011-08-19 01:50:49 +000067 return port
68 else:
cliechti9a3809e2011-08-19 23:43:10 +000069 raise serial.SerialException('no ports found matching regexp %r' % (url,))
cliechti6fa19112011-08-19 01:50:49 +000070
cliechti6fa19112011-08-19 01:50:49 +000071# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
72if __name__ == '__main__':
cliechti6fa19112011-08-19 01:50:49 +000073 s = Serial(None)
74 s.port = 'hwgrep://ttyS0'
Chris Liechti68340d72015-08-03 14:15:48 +020075 print(s)