blob: 3a2a83dd3eb5150a48bfd321131b100de447d3dd [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):
cliechti24c3a882014-08-01 03:36:27 +000022 """Serial Port configuration dialog, to be used with pySerial 2.0+
cliechti8f376e72003-10-03 00:16:11 +000023 When instantiating a class of this dialog, then the "serial" keyword
24 argument is mandatory. It is a reference to a serial.Serial instance.
25 the optional "show" keyword argument can be used to show/hide different
cliechti24c3a882014-08-01 03:36:27 +000026 settings. The default is SHOW_ALL which corresponds to
cliechti8f376e72003-10-03 00:16:11 +000027 SHOW_BAUDRATE|SHOW_FORMAT|SHOW_FLOW|SHOW_TIMEOUT. All constants can be
cliechti24c3a882014-08-01 03:36:27 +000028 found in this module (not the class)."""
29
cliechti8f376e72003-10-03 00:16:11 +000030 def __init__(self, *args, **kwds):
Chris Liechti4caf6a52015-08-04 01:07:45 +020031 # grab the serial keyword and remove it from the dict
cliechti8f376e72003-10-03 00:16:11 +000032 self.serial = kwds['serial']
33 del kwds['serial']
34 self.show = SHOW_ALL
35 if kwds.has_key('show'):
36 self.show = kwds['show']
37 del kwds['show']
38 # begin wxGlade: SerialConfigDialog.__init__
39 # end wxGlade
cliechtid5d51982008-04-10 23:48:55 +000040 kwds["style"] = wx.DEFAULT_DIALOG_STYLE
41 wx.Dialog.__init__(self, *args, **kwds)
42 self.label_2 = wx.StaticText(self, -1, "Port")
43 self.combo_box_port = wx.ComboBox(self, -1, choices=["dummy1", "dummy2", "dummy3", "dummy4", "dummy5"], style=wx.CB_DROPDOWN)
cliechti8f376e72003-10-03 00:16:11 +000044 if self.show & SHOW_BAUDRATE:
cliechtid5d51982008-04-10 23:48:55 +000045 self.label_1 = wx.StaticText(self, -1, "Baudrate")
46 self.choice_baudrate = wx.Choice(self, -1, choices=["choice 1"])
cliechti8f376e72003-10-03 00:16:11 +000047 if self.show & SHOW_FORMAT:
cliechtid5d51982008-04-10 23:48:55 +000048 self.label_3 = wx.StaticText(self, -1, "Data Bits")
49 self.choice_databits = wx.Choice(self, -1, choices=["choice 1"])
50 self.label_4 = wx.StaticText(self, -1, "Stop Bits")
51 self.choice_stopbits = wx.Choice(self, -1, choices=["choice 1"])
52 self.label_5 = wx.StaticText(self, -1, "Parity")
53 self.choice_parity = wx.Choice(self, -1, choices=["choice 1"])
cliechti8f376e72003-10-03 00:16:11 +000054 if self.show & SHOW_TIMEOUT:
cliechtid5d51982008-04-10 23:48:55 +000055 self.checkbox_timeout = wx.CheckBox(self, -1, "Use Timeout")
56 self.text_ctrl_timeout = wx.TextCtrl(self, -1, "")
57 self.label_6 = wx.StaticText(self, -1, "seconds")
cliechti8f376e72003-10-03 00:16:11 +000058 if self.show & SHOW_FLOW:
cliechtid5d51982008-04-10 23:48:55 +000059 self.checkbox_rtscts = wx.CheckBox(self, -1, "RTS/CTS")
60 self.checkbox_xonxoff = wx.CheckBox(self, -1, "Xon/Xoff")
61 self.button_ok = wx.Button(self, -1, "OK")
62 self.button_cancel = wx.Button(self, -1, "Cancel")
cliechti8f376e72003-10-03 00:16:11 +000063
64 self.__set_properties()
65 self.__do_layout()
cliechti24c3a882014-08-01 03:36:27 +000066 # fill in ports and select current setting
67 preferred_index = 0
cliechti8f376e72003-10-03 00:16:11 +000068 self.combo_box_port.Clear()
cliechti24c3a882014-08-01 03:36:27 +000069 self.ports = []
cliechtif2f8b532014-08-03 17:31:09 +000070 for n, (portname, desc, hwid) in enumerate(sorted(serial.tools.list_ports.comports())):
cliechti24c3a882014-08-01 03:36:27 +000071 self.combo_box_port.Append('%s (%s [%s])' % (portname, desc, hwid))
72 self.ports.append(portname)
cliechti8f376e72003-10-03 00:16:11 +000073 if self.serial.portstr == portname:
cliechti24c3a882014-08-01 03:36:27 +000074 preferred_index = n
75 self.combo_box_port.SetSelection(preferred_index)
cliechti8f376e72003-10-03 00:16:11 +000076 if self.show & SHOW_BAUDRATE:
Chris Liechti4caf6a52015-08-04 01:07:45 +020077 # fill in baud rates and select current setting
cliechti8f376e72003-10-03 00:16:11 +000078 self.choice_baudrate.Clear()
79 for n, baudrate in enumerate(self.serial.BAUDRATES):
80 self.choice_baudrate.Append(str(baudrate))
81 if self.serial.baudrate == baudrate:
82 index = n
83 self.choice_baudrate.SetSelection(index)
84 if self.show & SHOW_FORMAT:
Chris Liechti4caf6a52015-08-04 01:07:45 +020085 # fill in data bits and select current setting
cliechti8f376e72003-10-03 00:16:11 +000086 self.choice_databits.Clear()
87 for n, bytesize in enumerate(self.serial.BYTESIZES):
88 self.choice_databits.Append(str(bytesize))
89 if self.serial.bytesize == bytesize:
90 index = n
91 self.choice_databits.SetSelection(index)
Chris Liechti4caf6a52015-08-04 01:07:45 +020092 # fill in stop bits and select current setting
cliechti8f376e72003-10-03 00:16:11 +000093 self.choice_stopbits.Clear()
94 for n, stopbits in enumerate(self.serial.STOPBITS):
95 self.choice_stopbits.Append(str(stopbits))
96 if self.serial.stopbits == stopbits:
97 index = n
98 self.choice_stopbits.SetSelection(index)
Chris Liechti4caf6a52015-08-04 01:07:45 +020099 # fill in parities and select current setting
cliechti8f376e72003-10-03 00:16:11 +0000100 self.choice_parity.Clear()
101 for n, parity in enumerate(self.serial.PARITIES):
102 self.choice_parity.Append(str(serial.PARITY_NAMES[parity]))
103 if self.serial.parity == parity:
104 index = n
105 self.choice_parity.SetSelection(index)
106 if self.show & SHOW_TIMEOUT:
Chris Liechti4caf6a52015-08-04 01:07:45 +0200107 # set the timeout mode and value
cliechti8f376e72003-10-03 00:16:11 +0000108 if self.serial.timeout is None:
109 self.checkbox_timeout.SetValue(False)
110 self.text_ctrl_timeout.Enable(False)
111 else:
112 self.checkbox_timeout.SetValue(True)
113 self.text_ctrl_timeout.Enable(True)
114 self.text_ctrl_timeout.SetValue(str(self.serial.timeout))
115 if self.show & SHOW_FLOW:
Chris Liechti4caf6a52015-08-04 01:07:45 +0200116 # set the rtscts mode
cliechti8f376e72003-10-03 00:16:11 +0000117 self.checkbox_rtscts.SetValue(self.serial.rtscts)
Chris Liechti4caf6a52015-08-04 01:07:45 +0200118 # set the rtscts mode
cliechti8f376e72003-10-03 00:16:11 +0000119 self.checkbox_xonxoff.SetValue(self.serial.xonxoff)
Chris Liechti4caf6a52015-08-04 01:07:45 +0200120 # attach the event handlers
cliechti8f376e72003-10-03 00:16:11 +0000121 self.__attach_events()
122
123 def __set_properties(self):
124 # begin wxGlade: SerialConfigDialog.__set_properties
125 # end wxGlade
126 self.SetTitle("Serial Port Configuration")
127 if self.show & SHOW_TIMEOUT:
128 self.text_ctrl_timeout.Enable(0)
129 self.button_ok.SetDefault()
130
131 def __do_layout(self):
132 # begin wxGlade: SerialConfigDialog.__do_layout
133 # end wxGlade
cliechtid5d51982008-04-10 23:48:55 +0000134 sizer_2 = wx.BoxSizer(wx.VERTICAL)
135 sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
136 sizer_basics = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Basics"), wx.VERTICAL)
137 sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
138 sizer_5.Add(self.label_2, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
cliechti8f376e72003-10-03 00:16:11 +0000139 sizer_5.Add(self.combo_box_port, 1, 0, 0)
cliechtid5d51982008-04-10 23:48:55 +0000140 sizer_basics.Add(sizer_5, 0, wx.RIGHT|wx.EXPAND, 0)
cliechti8f376e72003-10-03 00:16:11 +0000141 if self.show & SHOW_BAUDRATE:
cliechtid5d51982008-04-10 23:48:55 +0000142 sizer_baudrate = wx.BoxSizer(wx.HORIZONTAL)
143 sizer_baudrate.Add(self.label_1, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
144 sizer_baudrate.Add(self.choice_baudrate, 1, wx.ALIGN_RIGHT, 0)
145 sizer_basics.Add(sizer_baudrate, 0, wx.EXPAND, 0)
146 sizer_2.Add(sizer_basics, 0, wx.EXPAND, 0)
cliechti8f376e72003-10-03 00:16:11 +0000147 if self.show & SHOW_FORMAT:
cliechtid5d51982008-04-10 23:48:55 +0000148 sizer_8 = wx.BoxSizer(wx.HORIZONTAL)
149 sizer_7 = wx.BoxSizer(wx.HORIZONTAL)
150 sizer_6 = wx.BoxSizer(wx.HORIZONTAL)
151 sizer_format = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Data Format"), wx.VERTICAL)
152 sizer_6.Add(self.label_3, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
153 sizer_6.Add(self.choice_databits, 1, wx.ALIGN_RIGHT, 0)
154 sizer_format.Add(sizer_6, 0, wx.EXPAND, 0)
155 sizer_7.Add(self.label_4, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
156 sizer_7.Add(self.choice_stopbits, 1, wx.ALIGN_RIGHT, 0)
157 sizer_format.Add(sizer_7, 0, wx.EXPAND, 0)
158 sizer_8.Add(self.label_5, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
159 sizer_8.Add(self.choice_parity, 1, wx.ALIGN_RIGHT, 0)
160 sizer_format.Add(sizer_8, 0, wx.EXPAND, 0)
161 sizer_2.Add(sizer_format, 0, wx.EXPAND, 0)
cliechti8f376e72003-10-03 00:16:11 +0000162 if self.show & SHOW_TIMEOUT:
cliechtid5d51982008-04-10 23:48:55 +0000163 sizer_timeout = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Timeout"), wx.HORIZONTAL)
164 sizer_timeout.Add(self.checkbox_timeout, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
cliechti8f376e72003-10-03 00:16:11 +0000165 sizer_timeout.Add(self.text_ctrl_timeout, 0, 0, 0)
cliechtid5d51982008-04-10 23:48:55 +0000166 sizer_timeout.Add(self.label_6, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
cliechti8f376e72003-10-03 00:16:11 +0000167 sizer_2.Add(sizer_timeout, 0, 0, 0)
168 if self.show & SHOW_FLOW:
cliechtid5d51982008-04-10 23:48:55 +0000169 sizer_flow = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Flow Control"), wx.HORIZONTAL)
170 sizer_flow.Add(self.checkbox_rtscts, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
171 sizer_flow.Add(self.checkbox_xonxoff, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
172 sizer_flow.Add((10,10), 1, wx.EXPAND, 0)
173 sizer_2.Add(sizer_flow, 0, wx.EXPAND, 0)
cliechti8f376e72003-10-03 00:16:11 +0000174 sizer_3.Add(self.button_ok, 0, 0, 0)
175 sizer_3.Add(self.button_cancel, 0, 0, 0)
cliechtid5d51982008-04-10 23:48:55 +0000176 sizer_2.Add(sizer_3, 0, wx.ALL|wx.ALIGN_RIGHT, 4)
cliechti8f376e72003-10-03 00:16:11 +0000177 self.SetAutoLayout(1)
178 self.SetSizer(sizer_2)
179 sizer_2.Fit(self)
180 sizer_2.SetSizeHints(self)
181 self.Layout()
182
183 def __attach_events(self):
cliechtid5d51982008-04-10 23:48:55 +0000184 wx.EVT_BUTTON(self, self.button_ok.GetId(), self.OnOK)
185 wx.EVT_BUTTON(self, self.button_cancel.GetId(), self.OnCancel)
cliechti8f376e72003-10-03 00:16:11 +0000186 if self.show & SHOW_TIMEOUT:
cliechtid5d51982008-04-10 23:48:55 +0000187 wx.EVT_CHECKBOX(self, self.checkbox_timeout.GetId(), self.OnTimeout)
cliechti8f376e72003-10-03 00:16:11 +0000188
189 def OnOK(self, events):
190 success = True
cliechti24c3a882014-08-01 03:36:27 +0000191 self.serial.port = self.ports[self.combo_box_port.GetSelection()]
cliechti8f376e72003-10-03 00:16:11 +0000192 if self.show & SHOW_BAUDRATE:
193 self.serial.baudrate = self.serial.BAUDRATES[self.choice_baudrate.GetSelection()]
194 if self.show & SHOW_FORMAT:
195 self.serial.bytesize = self.serial.BYTESIZES[self.choice_databits.GetSelection()]
196 self.serial.stopbits = self.serial.STOPBITS[self.choice_stopbits.GetSelection()]
197 self.serial.parity = self.serial.PARITIES[self.choice_parity.GetSelection()]
198 if self.show & SHOW_FLOW:
199 self.serial.rtscts = self.checkbox_rtscts.GetValue()
200 self.serial.xonxoff = self.checkbox_xonxoff.GetValue()
201 if self.show & SHOW_TIMEOUT:
202 if self.checkbox_timeout.GetValue():
203 try:
204 self.serial.timeout = float(self.text_ctrl_timeout.GetValue())
205 except ValueError:
cliechtid5d51982008-04-10 23:48:55 +0000206 dlg = wx.MessageDialog(self, 'Timeout must be a numeric value',
207 'Value Error', wx.OK | wx.ICON_ERROR)
cliechti8f376e72003-10-03 00:16:11 +0000208 dlg.ShowModal()
209 dlg.Destroy()
210 success = False
211 else:
212 self.serial.timeout = None
213 if success:
cliechtid5d51982008-04-10 23:48:55 +0000214 self.EndModal(wx.ID_OK)
cliechti8f376e72003-10-03 00:16:11 +0000215
216 def OnCancel(self, events):
cliechtid5d51982008-04-10 23:48:55 +0000217 self.EndModal(wx.ID_CANCEL)
cliechti8f376e72003-10-03 00:16:11 +0000218
219 def OnTimeout(self, events):
220 if self.checkbox_timeout.GetValue():
221 self.text_ctrl_timeout.Enable(True)
222 else:
223 self.text_ctrl_timeout.Enable(False)
224
225# end of class SerialConfigDialog
226
227
cliechtid5d51982008-04-10 23:48:55 +0000228class MyApp(wx.App):
cliechti8f376e72003-10-03 00:16:11 +0000229 """Test code"""
230 def OnInit(self):
cliechtid5d51982008-04-10 23:48:55 +0000231 wx.InitAllImageHandlers()
cliechti24c3a882014-08-01 03:36:27 +0000232
cliechti8f376e72003-10-03 00:16:11 +0000233 ser = serial.Serial()
Chris Liechti4caf6a52015-08-04 01:07:45 +0200234 print(ser)
235 # loop until cancel is pressed, old values are used as start for the next run
236 # show the different views, one after the other
237 # value are kept.
cliechti8f376e72003-10-03 00:16:11 +0000238 for flags in (SHOW_BAUDRATE, SHOW_FLOW, SHOW_FORMAT, SHOW_TIMEOUT, SHOW_ALL):
239 dialog_serial_cfg = SerialConfigDialog(None, -1, "", serial=ser, show=flags)
240 self.SetTopWindow(dialog_serial_cfg)
241 result = dialog_serial_cfg.ShowModal()
Chris Liechti4caf6a52015-08-04 01:07:45 +0200242 print(ser)
cliechtid5d51982008-04-10 23:48:55 +0000243 if result != wx.ID_OK:
cliechti8f376e72003-10-03 00:16:11 +0000244 break
Chris Liechti4caf6a52015-08-04 01:07:45 +0200245 # the user can play around with the values, CANCEL aborts the loop
cliechti8f376e72003-10-03 00:16:11 +0000246 while 1:
247 dialog_serial_cfg = SerialConfigDialog(None, -1, "", serial=ser)
248 self.SetTopWindow(dialog_serial_cfg)
249 result = dialog_serial_cfg.ShowModal()
Chris Liechti4caf6a52015-08-04 01:07:45 +0200250 print(ser)
cliechtid5d51982008-04-10 23:48:55 +0000251 if result != wx.ID_OK:
cliechti8f376e72003-10-03 00:16:11 +0000252 break
253 return 0
254
255# end of class MyApp
256
257if __name__ == "__main__":
258 app = MyApp(0)
259 app.MainLoop()