blob: 7ceecadecc23106c36be8bf6ef7b0ab96413cc9a [file] [log] [blame]
cliechti8f376e72003-10-03 00:16:11 +00001#!/usr/bin/env python
Chris Liechtifbdd8a02015-08-09 02:37:45 +02002#
3# A serial port configuration dialog for wxPython. A number of flags can
4# be used to cinfugure the fields that are displayed.
5#
6# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
7#
8# SPDX-License-Identifier: BSD-3-Clause
cliechti8f376e72003-10-03 00:16:11 +00009
cliechtid5d51982008-04-10 23:48:55 +000010import wx
cliechti8f376e72003-10-03 00:16:11 +000011import serial
cliechti24c3a882014-08-01 03:36:27 +000012import serial.tools.list_ports
cliechti8f376e72003-10-03 00:16:11 +000013
14SHOW_BAUDRATE = 1<<0
15SHOW_FORMAT = 1<<1
16SHOW_FLOW = 1<<2
17SHOW_TIMEOUT = 1<<3
18SHOW_ALL = SHOW_BAUDRATE|SHOW_FORMAT|SHOW_FLOW|SHOW_TIMEOUT
19
cliechti80a0ed12003-10-03 23:53:42 +000020
cliechtid5d51982008-04-10 23:48:55 +000021class SerialConfigDialog(wx.Dialog):
Chris Liechtibe00ee92015-09-12 02:02:04 +020022 """\
23 Serial Port configuration dialog, to be used with pySerial 2.0+
24 When instantiating a class of this dialog, then the "serial" keyword
25 argument is mandatory. It is a reference to a serial.Serial instance.
26 the optional "show" keyword argument can be used to show/hide different
27 settings. The default is SHOW_ALL which corresponds to
28 SHOW_BAUDRATE|SHOW_FORMAT|SHOW_FLOW|SHOW_TIMEOUT. All constants can be
29 found in this module (not the class).
30 """
cliechti24c3a882014-08-01 03:36:27 +000031
cliechti8f376e72003-10-03 00:16:11 +000032 def __init__(self, *args, **kwds):
Chris Liechti4caf6a52015-08-04 01:07:45 +020033 # grab the serial keyword and remove it from the dict
cliechti8f376e72003-10-03 00:16:11 +000034 self.serial = kwds['serial']
35 del kwds['serial']
36 self.show = SHOW_ALL
37 if kwds.has_key('show'):
38 self.show = kwds['show']
39 del kwds['show']
40 # begin wxGlade: SerialConfigDialog.__init__
cliechtid5d51982008-04-10 23:48:55 +000041 kwds["style"] = wx.DEFAULT_DIALOG_STYLE
42 wx.Dialog.__init__(self, *args, **kwds)
43 self.label_2 = wx.StaticText(self, -1, "Port")
Chris Liechtibe00ee92015-09-12 02:02:04 +020044 self.choice_port = wx.Choice(self, -1, choices=[])
45 self.label_1 = wx.StaticText(self, -1, "Baudrate")
46 self.choice_baudrate = wx.Choice(self, -1, choices=["choice 1"])
47 self.sizer_1_staticbox = wx.StaticBox(self, -1, "Basics")
48 self.panel_format = wx.Panel(self, -1)
49 self.label_3 = wx.StaticText(self.panel_format, -1, "Data Bits")
50 self.choice_databits = wx.Choice(self.panel_format, -1, choices=["choice 1"])
51 self.label_4 = wx.StaticText(self.panel_format, -1, "Stop Bits")
52 self.choice_stopbits = wx.Choice(self.panel_format, -1, choices=["choice 1"])
53 self.label_5 = wx.StaticText(self.panel_format, -1, "Parity")
54 self.choice_parity = wx.Choice(self.panel_format, -1, choices=["choice 1"])
55 self.sizer_format_staticbox = wx.StaticBox(self.panel_format, -1, "Data Format")
56 self.panel_timeout = wx.Panel(self, -1)
57 self.checkbox_timeout = wx.CheckBox(self.panel_timeout, -1, "Use Timeout")
58 self.text_ctrl_timeout = wx.TextCtrl(self.panel_timeout, -1, "")
59 self.label_6 = wx.StaticText(self.panel_timeout, -1, "seconds")
60 self.sizer_timeout_staticbox = wx.StaticBox(self.panel_timeout, -1, "Timeout")
61 self.panel_flow = wx.Panel(self, -1)
62 self.checkbox_rtscts = wx.CheckBox(self.panel_flow, -1, "RTS/CTS")
63 self.checkbox_xonxoff = wx.CheckBox(self.panel_flow, -1, "Xon/Xoff")
64 self.sizer_flow_staticbox = wx.StaticBox(self.panel_flow, -1, "Flow Control")
65 self.button_ok = wx.Button(self, wx.ID_OK, "")
66 self.button_cancel = wx.Button(self, wx.ID_CANCEL, "")
cliechti8f376e72003-10-03 00:16:11 +000067
68 self.__set_properties()
69 self.__do_layout()
Chris Liechtibe00ee92015-09-12 02:02:04 +020070 # end wxGlade
71 # attach the event handlers
72 self.__attach_events()
73
74 def __set_properties(self):
75 # begin wxGlade: SerialConfigDialog.__set_properties
76 self.SetTitle("Serial Port Configuration")
77 self.choice_baudrate.SetSelection(0)
78 self.choice_databits.SetSelection(0)
79 self.choice_stopbits.SetSelection(0)
80 self.choice_parity.SetSelection(0)
81 self.text_ctrl_timeout.Enable(False)
82 self.button_ok.SetDefault()
83 # end wxGlade
84 self.SetTitle("Serial Port Configuration")
85 if self.show & SHOW_TIMEOUT:
86 self.text_ctrl_timeout.Enable(0)
87 self.button_ok.SetDefault()
88
89 if not self.show & SHOW_BAUDRATE:
90 self.label_1.Hide()
91 self.choice_baudrate.Hide()
92 if not self.show & SHOW_FORMAT:
93 self.panel_format.Hide()
94 if not self.show & SHOW_TIMEOUT:
95 self.panel_timeout.Hide()
96 if not self.show & SHOW_FLOW:
97 self.panel_flow.Hide()
98
cliechti24c3a882014-08-01 03:36:27 +000099 # fill in ports and select current setting
100 preferred_index = 0
Chris Liechtibe00ee92015-09-12 02:02:04 +0200101 self.choice_port.Clear()
cliechti24c3a882014-08-01 03:36:27 +0000102 self.ports = []
cliechtif2f8b532014-08-03 17:31:09 +0000103 for n, (portname, desc, hwid) in enumerate(sorted(serial.tools.list_ports.comports())):
Chris Liechtibe00ee92015-09-12 02:02:04 +0200104 self.choice_port.Append('%s - %s' % (portname, desc))
cliechti24c3a882014-08-01 03:36:27 +0000105 self.ports.append(portname)
Chris Liechtibe00ee92015-09-12 02:02:04 +0200106 if self.serial.name == portname:
cliechti24c3a882014-08-01 03:36:27 +0000107 preferred_index = n
Chris Liechtibe00ee92015-09-12 02:02:04 +0200108 self.choice_port.SetSelection(preferred_index)
cliechti8f376e72003-10-03 00:16:11 +0000109 if self.show & SHOW_BAUDRATE:
Chris Liechti4caf6a52015-08-04 01:07:45 +0200110 # fill in baud rates and select current setting
cliechti8f376e72003-10-03 00:16:11 +0000111 self.choice_baudrate.Clear()
112 for n, baudrate in enumerate(self.serial.BAUDRATES):
113 self.choice_baudrate.Append(str(baudrate))
114 if self.serial.baudrate == baudrate:
115 index = n
116 self.choice_baudrate.SetSelection(index)
117 if self.show & SHOW_FORMAT:
Chris Liechti4caf6a52015-08-04 01:07:45 +0200118 # fill in data bits and select current setting
cliechti8f376e72003-10-03 00:16:11 +0000119 self.choice_databits.Clear()
120 for n, bytesize in enumerate(self.serial.BYTESIZES):
121 self.choice_databits.Append(str(bytesize))
122 if self.serial.bytesize == bytesize:
123 index = n
124 self.choice_databits.SetSelection(index)
Chris Liechti4caf6a52015-08-04 01:07:45 +0200125 # fill in stop bits and select current setting
cliechti8f376e72003-10-03 00:16:11 +0000126 self.choice_stopbits.Clear()
127 for n, stopbits in enumerate(self.serial.STOPBITS):
128 self.choice_stopbits.Append(str(stopbits))
129 if self.serial.stopbits == stopbits:
130 index = n
131 self.choice_stopbits.SetSelection(index)
Chris Liechti4caf6a52015-08-04 01:07:45 +0200132 # fill in parities and select current setting
cliechti8f376e72003-10-03 00:16:11 +0000133 self.choice_parity.Clear()
134 for n, parity in enumerate(self.serial.PARITIES):
135 self.choice_parity.Append(str(serial.PARITY_NAMES[parity]))
136 if self.serial.parity == parity:
137 index = n
138 self.choice_parity.SetSelection(index)
139 if self.show & SHOW_TIMEOUT:
Chris Liechti4caf6a52015-08-04 01:07:45 +0200140 # set the timeout mode and value
cliechti8f376e72003-10-03 00:16:11 +0000141 if self.serial.timeout is None:
142 self.checkbox_timeout.SetValue(False)
143 self.text_ctrl_timeout.Enable(False)
144 else:
145 self.checkbox_timeout.SetValue(True)
146 self.text_ctrl_timeout.Enable(True)
147 self.text_ctrl_timeout.SetValue(str(self.serial.timeout))
148 if self.show & SHOW_FLOW:
Chris Liechti4caf6a52015-08-04 01:07:45 +0200149 # set the rtscts mode
cliechti8f376e72003-10-03 00:16:11 +0000150 self.checkbox_rtscts.SetValue(self.serial.rtscts)
Chris Liechti4caf6a52015-08-04 01:07:45 +0200151 # set the rtscts mode
cliechti8f376e72003-10-03 00:16:11 +0000152 self.checkbox_xonxoff.SetValue(self.serial.xonxoff)
cliechti8f376e72003-10-03 00:16:11 +0000153
154 def __do_layout(self):
155 # begin wxGlade: SerialConfigDialog.__do_layout
cliechtid5d51982008-04-10 23:48:55 +0000156 sizer_2 = wx.BoxSizer(wx.VERTICAL)
157 sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
Chris Liechtibe00ee92015-09-12 02:02:04 +0200158 self.sizer_flow_staticbox.Lower()
159 sizer_flow = wx.StaticBoxSizer(self.sizer_flow_staticbox, wx.HORIZONTAL)
160 self.sizer_timeout_staticbox.Lower()
161 sizer_timeout = wx.StaticBoxSizer(self.sizer_timeout_staticbox, wx.HORIZONTAL)
162 self.sizer_format_staticbox.Lower()
163 sizer_format = wx.StaticBoxSizer(self.sizer_format_staticbox, wx.VERTICAL)
164 grid_sizer_1 = wx.FlexGridSizer(3, 2, 0, 0)
165 self.sizer_1_staticbox.Lower()
166 sizer_1 = wx.StaticBoxSizer(self.sizer_1_staticbox, wx.VERTICAL)
167 sizer_basics = wx.FlexGridSizer(3, 2, 0, 0)
168 sizer_basics.Add(self.label_2, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
169 sizer_basics.Add(self.choice_port, 0, wx.EXPAND, 0)
170 sizer_basics.Add(self.label_1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
171 sizer_basics.Add(self.choice_baudrate, 0, wx.EXPAND, 0)
172 sizer_basics.AddGrowableCol(1)
173 sizer_1.Add(sizer_basics, 0, wx.EXPAND, 0)
174 sizer_2.Add(sizer_1, 0, wx.EXPAND, 0)
175 grid_sizer_1.Add(self.label_3, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
176 grid_sizer_1.Add(self.choice_databits, 1, wx.EXPAND | wx.ALIGN_RIGHT, 0)
177 grid_sizer_1.Add(self.label_4, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
178 grid_sizer_1.Add(self.choice_stopbits, 1, wx.EXPAND | wx.ALIGN_RIGHT, 0)
179 grid_sizer_1.Add(self.label_5, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
180 grid_sizer_1.Add(self.choice_parity, 1, wx.EXPAND | wx.ALIGN_RIGHT, 0)
181 sizer_format.Add(grid_sizer_1, 1, wx.EXPAND, 0)
182 self.panel_format.SetSizer(sizer_format)
183 sizer_2.Add(self.panel_format, 0, wx.EXPAND, 0)
184 sizer_timeout.Add(self.checkbox_timeout, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
185 sizer_timeout.Add(self.text_ctrl_timeout, 0, 0, 0)
186 sizer_timeout.Add(self.label_6, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
187 self.panel_timeout.SetSizer(sizer_timeout)
188 sizer_2.Add(self.panel_timeout, 0, wx.EXPAND, 0)
189 sizer_flow.Add(self.checkbox_rtscts, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
190 sizer_flow.Add(self.checkbox_xonxoff, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
191 sizer_flow.Add((10, 10), 1, wx.EXPAND, 0)
192 self.panel_flow.SetSizer(sizer_flow)
193 sizer_2.Add(self.panel_flow, 0, wx.EXPAND, 0)
cliechti8f376e72003-10-03 00:16:11 +0000194 sizer_3.Add(self.button_ok, 0, 0, 0)
195 sizer_3.Add(self.button_cancel, 0, 0, 0)
Chris Liechtibe00ee92015-09-12 02:02:04 +0200196 sizer_2.Add(sizer_3, 0, wx.ALL | wx.ALIGN_RIGHT, 4)
cliechti8f376e72003-10-03 00:16:11 +0000197 self.SetSizer(sizer_2)
198 sizer_2.Fit(self)
cliechti8f376e72003-10-03 00:16:11 +0000199 self.Layout()
Chris Liechtibe00ee92015-09-12 02:02:04 +0200200 # end wxGlade
cliechti8f376e72003-10-03 00:16:11 +0000201
202 def __attach_events(self):
cliechtid5d51982008-04-10 23:48:55 +0000203 wx.EVT_BUTTON(self, self.button_ok.GetId(), self.OnOK)
204 wx.EVT_BUTTON(self, self.button_cancel.GetId(), self.OnCancel)
cliechti8f376e72003-10-03 00:16:11 +0000205 if self.show & SHOW_TIMEOUT:
cliechtid5d51982008-04-10 23:48:55 +0000206 wx.EVT_CHECKBOX(self, self.checkbox_timeout.GetId(), self.OnTimeout)
cliechti8f376e72003-10-03 00:16:11 +0000207
208 def OnOK(self, events):
209 success = True
Chris Liechtibe00ee92015-09-12 02:02:04 +0200210 self.serial.port = self.ports[self.choice_port.GetSelection()]
cliechti8f376e72003-10-03 00:16:11 +0000211 if self.show & SHOW_BAUDRATE:
212 self.serial.baudrate = self.serial.BAUDRATES[self.choice_baudrate.GetSelection()]
213 if self.show & SHOW_FORMAT:
214 self.serial.bytesize = self.serial.BYTESIZES[self.choice_databits.GetSelection()]
215 self.serial.stopbits = self.serial.STOPBITS[self.choice_stopbits.GetSelection()]
216 self.serial.parity = self.serial.PARITIES[self.choice_parity.GetSelection()]
217 if self.show & SHOW_FLOW:
218 self.serial.rtscts = self.checkbox_rtscts.GetValue()
219 self.serial.xonxoff = self.checkbox_xonxoff.GetValue()
220 if self.show & SHOW_TIMEOUT:
221 if self.checkbox_timeout.GetValue():
222 try:
223 self.serial.timeout = float(self.text_ctrl_timeout.GetValue())
224 except ValueError:
Chris Liechtibe00ee92015-09-12 02:02:04 +0200225 with wx.MessageDialog(
226 self,
227 'Timeout must be a numeric value',
228 'Value Error',
229 wx.OK | wx.ICON_ERROR) as dlg:
230 dlg.ShowModal()
cliechti8f376e72003-10-03 00:16:11 +0000231 success = False
232 else:
233 self.serial.timeout = None
234 if success:
cliechtid5d51982008-04-10 23:48:55 +0000235 self.EndModal(wx.ID_OK)
cliechti8f376e72003-10-03 00:16:11 +0000236
237 def OnCancel(self, events):
cliechtid5d51982008-04-10 23:48:55 +0000238 self.EndModal(wx.ID_CANCEL)
cliechti8f376e72003-10-03 00:16:11 +0000239
240 def OnTimeout(self, events):
241 if self.checkbox_timeout.GetValue():
242 self.text_ctrl_timeout.Enable(True)
243 else:
244 self.text_ctrl_timeout.Enable(False)
245
246# end of class SerialConfigDialog
247
248
cliechtid5d51982008-04-10 23:48:55 +0000249class MyApp(wx.App):
cliechti8f376e72003-10-03 00:16:11 +0000250 """Test code"""
251 def OnInit(self):
cliechtid5d51982008-04-10 23:48:55 +0000252 wx.InitAllImageHandlers()
cliechti24c3a882014-08-01 03:36:27 +0000253
cliechti8f376e72003-10-03 00:16:11 +0000254 ser = serial.Serial()
Chris Liechti4caf6a52015-08-04 01:07:45 +0200255 print(ser)
256 # loop until cancel is pressed, old values are used as start for the next run
257 # show the different views, one after the other
258 # value are kept.
cliechti8f376e72003-10-03 00:16:11 +0000259 for flags in (SHOW_BAUDRATE, SHOW_FLOW, SHOW_FORMAT, SHOW_TIMEOUT, SHOW_ALL):
260 dialog_serial_cfg = SerialConfigDialog(None, -1, "", serial=ser, show=flags)
261 self.SetTopWindow(dialog_serial_cfg)
262 result = dialog_serial_cfg.ShowModal()
Chris Liechti4caf6a52015-08-04 01:07:45 +0200263 print(ser)
cliechtid5d51982008-04-10 23:48:55 +0000264 if result != wx.ID_OK:
cliechti8f376e72003-10-03 00:16:11 +0000265 break
Chris Liechti4caf6a52015-08-04 01:07:45 +0200266 # the user can play around with the values, CANCEL aborts the loop
Chris Liechtibe00ee92015-09-12 02:02:04 +0200267 while True:
cliechti8f376e72003-10-03 00:16:11 +0000268 dialog_serial_cfg = SerialConfigDialog(None, -1, "", serial=ser)
269 self.SetTopWindow(dialog_serial_cfg)
270 result = dialog_serial_cfg.ShowModal()
Chris Liechti4caf6a52015-08-04 01:07:45 +0200271 print(ser)
cliechtid5d51982008-04-10 23:48:55 +0000272 if result != wx.ID_OK:
cliechti8f376e72003-10-03 00:16:11 +0000273 break
274 return 0
275
276# end of class MyApp
277
278if __name__ == "__main__":
279 app = MyApp(0)
280 app.MainLoop()