blob: 973b933abc9408d5c654ffdc6d36d15a6c0aa360 [file] [log] [blame]
cliechti80a0ed12003-10-03 23:53:42 +00001#!/usr/bin/env python
Chris Liechtifbdd8a02015-08-09 02:37:45 +02002#
3# A simple terminal application with wxPython.
4#
5# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
6#
7# SPDX-License-Identifier: BSD-3-Clause
cliechti80a0ed12003-10-03 23:53:42 +00008
cliechtid5d51982008-04-10 23:48:55 +00009#from wxPython.wx import *
10import wx
cliechti80a0ed12003-10-03 23:53:42 +000011import wxSerialConfigDialog
12import serial
13import threading
14
cliechti40d71f62004-07-09 22:14:17 +000015#----------------------------------------------------------------------
16# Create an own event type, so that GUI updates can be delegated
17# this is required as on some platforms only the main thread can
18# access the GUI without crashing. wxMutexGuiEnter/wxMutexGuiLeave
19# could be used too, but an event is more elegant.
20
cliechtid5d51982008-04-10 23:48:55 +000021SERIALRX = wx.NewEventType()
cliechtibc318d42004-11-13 03:13:12 +000022# bind to serial data receive events
cliechtid5d51982008-04-10 23:48:55 +000023EVT_SERIALRX = wx.PyEventBinder(SERIALRX, 0)
cliechti40d71f62004-07-09 22:14:17 +000024
cliechtid5d51982008-04-10 23:48:55 +000025class SerialRxEvent(wx.PyCommandEvent):
cliechti40d71f62004-07-09 22:14:17 +000026 eventType = SERIALRX
27 def __init__(self, windowID, data):
cliechtid5d51982008-04-10 23:48:55 +000028 wx.PyCommandEvent.__init__(self, self.eventType, windowID)
cliechti40d71f62004-07-09 22:14:17 +000029 self.data = data
30
31 def Clone(self):
32 self.__class__(self.GetId(), self.data)
33
34#----------------------------------------------------------------------
35
cliechtid5d51982008-04-10 23:48:55 +000036ID_CLEAR = wx.NewId()
37ID_SAVEAS = wx.NewId()
38ID_SETTINGS = wx.NewId()
39ID_TERM = wx.NewId()
40ID_EXIT = wx.NewId()
Chris Liechtibe00ee92015-09-12 02:02:04 +020041ID_RTS = wx.NewId()
42ID_DTR = wx.NewId()
cliechti80a0ed12003-10-03 23:53:42 +000043
44NEWLINE_CR = 0
45NEWLINE_LF = 1
46NEWLINE_CRLF = 2
47
48class TerminalSetup:
cliechti0eb86712003-10-04 00:49:04 +000049 """Placeholder for various terminal settings. Used to pass the
50 options to the TerminalSettingsDialog."""
cliechti80a0ed12003-10-03 23:53:42 +000051 def __init__(self):
52 self.echo = False
53 self.unprintable = False
54 self.newline = NEWLINE_CRLF
55
cliechtid5d51982008-04-10 23:48:55 +000056class TerminalSettingsDialog(wx.Dialog):
cliechti0eb86712003-10-04 00:49:04 +000057 """Simple dialog with common terminal settings like echo, newline mode."""
Chris Liechti4caf6a52015-08-04 01:07:45 +020058
cliechti80a0ed12003-10-03 23:53:42 +000059 def __init__(self, *args, **kwds):
60 self.settings = kwds['settings']
61 del kwds['settings']
62 # begin wxGlade: TerminalSettingsDialog.__init__
cliechtid5d51982008-04-10 23:48:55 +000063 kwds["style"] = wx.DEFAULT_DIALOG_STYLE
64 wx.Dialog.__init__(self, *args, **kwds)
65 self.checkbox_echo = wx.CheckBox(self, -1, "Local Echo")
66 self.checkbox_unprintable = wx.CheckBox(self, -1, "Show unprintable characters")
67 self.radio_box_newline = wx.RadioBox(self, -1, "Newline Handling", choices=["CR only", "LF only", "CR+LF"], majorDimension=0, style=wx.RA_SPECIFY_ROWS)
Chris Liechtibe00ee92015-09-12 02:02:04 +020068 self.sizer_4_staticbox = wx.StaticBox(self, -1, "Input/Output")
cliechtid5d51982008-04-10 23:48:55 +000069 self.button_ok = wx.Button(self, -1, "OK")
70 self.button_cancel = wx.Button(self, -1, "Cancel")
cliechti80a0ed12003-10-03 23:53:42 +000071
72 self.__set_properties()
73 self.__do_layout()
74 # end wxGlade
75 self.__attach_events()
76 self.checkbox_echo.SetValue(self.settings.echo)
77 self.checkbox_unprintable.SetValue(self.settings.unprintable)
78 self.radio_box_newline.SetSelection(self.settings.newline)
79
80 def __set_properties(self):
81 # begin wxGlade: TerminalSettingsDialog.__set_properties
82 self.SetTitle("Terminal Settings")
83 self.radio_box_newline.SetSelection(0)
84 self.button_ok.SetDefault()
85 # end wxGlade
86
87 def __do_layout(self):
88 # begin wxGlade: TerminalSettingsDialog.__do_layout
cliechtid5d51982008-04-10 23:48:55 +000089 sizer_2 = wx.BoxSizer(wx.VERTICAL)
90 sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
Chris Liechtibe00ee92015-09-12 02:02:04 +020091 self.sizer_4_staticbox.Lower()
92 sizer_4 = wx.StaticBoxSizer(self.sizer_4_staticbox, wx.VERTICAL)
cliechtid5d51982008-04-10 23:48:55 +000093 sizer_4.Add(self.checkbox_echo, 0, wx.ALL, 4)
94 sizer_4.Add(self.checkbox_unprintable, 0, wx.ALL, 4)
cliechti80a0ed12003-10-03 23:53:42 +000095 sizer_4.Add(self.radio_box_newline, 0, 0, 0)
cliechtid5d51982008-04-10 23:48:55 +000096 sizer_2.Add(sizer_4, 0, wx.EXPAND, 0)
cliechti80a0ed12003-10-03 23:53:42 +000097 sizer_3.Add(self.button_ok, 0, 0, 0)
98 sizer_3.Add(self.button_cancel, 0, 0, 0)
Chris Liechtibe00ee92015-09-12 02:02:04 +020099 sizer_2.Add(sizer_3, 0, wx.ALL | wx.ALIGN_RIGHT, 4)
cliechti80a0ed12003-10-03 23:53:42 +0000100 self.SetSizer(sizer_2)
101 sizer_2.Fit(self)
cliechti80a0ed12003-10-03 23:53:42 +0000102 self.Layout()
103 # end wxGlade
104
105 def __attach_events(self):
cliechtid5d51982008-04-10 23:48:55 +0000106 self.Bind(wx.EVT_BUTTON, self.OnOK, id = self.button_ok.GetId())
107 self.Bind(wx.EVT_BUTTON, self.OnCancel, id = self.button_cancel.GetId())
Chris Liechti4caf6a52015-08-04 01:07:45 +0200108
cliechti80a0ed12003-10-03 23:53:42 +0000109 def OnOK(self, events):
cliechti0eb86712003-10-04 00:49:04 +0000110 """Update data wil new values and close dialog."""
cliechti80a0ed12003-10-03 23:53:42 +0000111 self.settings.echo = self.checkbox_echo.GetValue()
112 self.settings.unprintable = self.checkbox_unprintable.GetValue()
113 self.settings.newline = self.radio_box_newline.GetSelection()
cliechtid5d51982008-04-10 23:48:55 +0000114 self.EndModal(wx.ID_OK)
Chris Liechti4caf6a52015-08-04 01:07:45 +0200115
cliechti80a0ed12003-10-03 23:53:42 +0000116 def OnCancel(self, events):
cliechti0eb86712003-10-04 00:49:04 +0000117 """Do not update data but close dialog."""
cliechtid5d51982008-04-10 23:48:55 +0000118 self.EndModal(wx.ID_CANCEL)
cliechti80a0ed12003-10-03 23:53:42 +0000119
120# end of class TerminalSettingsDialog
121
122
cliechtid5d51982008-04-10 23:48:55 +0000123class TerminalFrame(wx.Frame):
cliechti80a0ed12003-10-03 23:53:42 +0000124 """Simple terminal program for wxPython"""
Chris Liechti4caf6a52015-08-04 01:07:45 +0200125
cliechti80a0ed12003-10-03 23:53:42 +0000126 def __init__(self, *args, **kwds):
127 self.serial = serial.Serial()
cliechtibc318d42004-11-13 03:13:12 +0000128 self.serial.timeout = 0.5 #make sure that the alive event can be checked from time to time
cliechti0eb86712003-10-04 00:49:04 +0000129 self.settings = TerminalSetup() #placeholder for the settings
cliechti80a0ed12003-10-03 23:53:42 +0000130 self.thread = None
Chris Liechti4caf6a52015-08-04 01:07:45 +0200131 self.alive = threading.Event()
cliechti80a0ed12003-10-03 23:53:42 +0000132 # begin wxGlade: TerminalFrame.__init__
cliechtid5d51982008-04-10 23:48:55 +0000133 kwds["style"] = wx.DEFAULT_FRAME_STYLE
134 wx.Frame.__init__(self, *args, **kwds)
Chris Liechtibe00ee92015-09-12 02:02:04 +0200135
cliechti80a0ed12003-10-03 23:53:42 +0000136 # Menu Bar
cliechtid5d51982008-04-10 23:48:55 +0000137 self.frame_terminal_menubar = wx.MenuBar()
cliechtid5d51982008-04-10 23:48:55 +0000138 wxglade_tmp_menu = wx.Menu()
139 wxglade_tmp_menu.Append(ID_CLEAR, "&Clear", "", wx.ITEM_NORMAL)
140 wxglade_tmp_menu.Append(ID_SAVEAS, "&Save Text As...", "", wx.ITEM_NORMAL)
cliechti80a0ed12003-10-03 23:53:42 +0000141 wxglade_tmp_menu.AppendSeparator()
cliechtid5d51982008-04-10 23:48:55 +0000142 wxglade_tmp_menu.Append(ID_TERM, "&Terminal Settings...", "", wx.ITEM_NORMAL)
cliechti80a0ed12003-10-03 23:53:42 +0000143 wxglade_tmp_menu.AppendSeparator()
cliechtid5d51982008-04-10 23:48:55 +0000144 wxglade_tmp_menu.Append(ID_EXIT, "&Exit", "", wx.ITEM_NORMAL)
cliechti80a0ed12003-10-03 23:53:42 +0000145 self.frame_terminal_menubar.Append(wxglade_tmp_menu, "&File")
Chris Liechtibe00ee92015-09-12 02:02:04 +0200146 wxglade_tmp_menu = wx.Menu()
147 wxglade_tmp_menu.Append(ID_RTS, "RTS", "", wx.ITEM_CHECK)
148 wxglade_tmp_menu.Append(ID_DTR, "&DTR", "", wx.ITEM_CHECK)
149 wxglade_tmp_menu.Append(ID_SETTINGS, "&Port Settings...", "", wx.ITEM_NORMAL)
150 self.frame_terminal_menubar.Append(wxglade_tmp_menu, "Serial Port")
151 self.SetMenuBar(self.frame_terminal_menubar)
cliechti80a0ed12003-10-03 23:53:42 +0000152 # Menu Bar end
Chris Liechtibe00ee92015-09-12 02:02:04 +0200153 self.text_ctrl_output = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
cliechti80a0ed12003-10-03 23:53:42 +0000154
155 self.__set_properties()
156 self.__do_layout()
Chris Liechtibe00ee92015-09-12 02:02:04 +0200157
158 self.Bind(wx.EVT_MENU, self.OnClear, id=ID_CLEAR)
159 self.Bind(wx.EVT_MENU, self.OnSaveAs, id=ID_SAVEAS)
160 self.Bind(wx.EVT_MENU, self.OnTermSettings, id=ID_TERM)
161 self.Bind(wx.EVT_MENU, self.OnExit, id=ID_EXIT)
162 self.Bind(wx.EVT_MENU, self.OnRTS, id=ID_RTS)
163 self.Bind(wx.EVT_MENU, self.OnDTR, id=ID_DTR)
164 self.Bind(wx.EVT_MENU, self.OnPortSettings, id=ID_SETTINGS)
cliechti80a0ed12003-10-03 23:53:42 +0000165 # end wxGlade
cliechti0eb86712003-10-04 00:49:04 +0000166 self.__attach_events() #register events
cliechti80a0ed12003-10-03 23:53:42 +0000167 self.OnPortSettings(None) #call setup dialog on startup, opens port
cliechtibc318d42004-11-13 03:13:12 +0000168 if not self.alive.isSet():
cliechti0eb86712003-10-04 00:49:04 +0000169 self.Close()
cliechti80a0ed12003-10-03 23:53:42 +0000170
171 def StartThread(self):
cliechtibc318d42004-11-13 03:13:12 +0000172 """Start the receiver thread"""
cliechti80a0ed12003-10-03 23:53:42 +0000173 self.thread = threading.Thread(target=self.ComPortThread)
174 self.thread.setDaemon(1)
cliechtibc318d42004-11-13 03:13:12 +0000175 self.alive.set()
cliechtif7776692005-10-02 21:51:42 +0000176 self.thread.start()
Chris Liechtibe00ee92015-09-12 02:02:04 +0200177 self.serial.rts = True
178 self.serial.dtr = True
179 self.frame_terminal_menubar.Check(ID_RTS, self.serial.rts)
180 self.frame_terminal_menubar.Check(ID_DTR, self.serial.dtr)
cliechti80a0ed12003-10-03 23:53:42 +0000181
182 def StopThread(self):
cliechti0eb86712003-10-04 00:49:04 +0000183 """Stop the receiver thread, wait util it's finished."""
cliechti80a0ed12003-10-03 23:53:42 +0000184 if self.thread is not None:
cliechtibc318d42004-11-13 03:13:12 +0000185 self.alive.clear() #clear alive event for thread
cliechti80a0ed12003-10-03 23:53:42 +0000186 self.thread.join() #wait until thread has finished
187 self.thread = None
Chris Liechti4caf6a52015-08-04 01:07:45 +0200188
cliechti80a0ed12003-10-03 23:53:42 +0000189 def __set_properties(self):
190 # begin wxGlade: TerminalFrame.__set_properties
191 self.SetTitle("Serial Terminal")
192 self.SetSize((546, 383))
Chris Liechtibe00ee92015-09-12 02:02:04 +0200193 self.text_ctrl_output.SetFont(wx.Font(9, wx.MODERN, wx.NORMAL, wx.NORMAL, 0, ""))
cliechti80a0ed12003-10-03 23:53:42 +0000194 # end wxGlade
195
196 def __do_layout(self):
197 # begin wxGlade: TerminalFrame.__do_layout
cliechtid5d51982008-04-10 23:48:55 +0000198 sizer_1 = wx.BoxSizer(wx.VERTICAL)
199 sizer_1.Add(self.text_ctrl_output, 1, wx.EXPAND, 0)
cliechti80a0ed12003-10-03 23:53:42 +0000200 self.SetSizer(sizer_1)
201 self.Layout()
202 # end wxGlade
203
204 def __attach_events(self):
cliechti0eb86712003-10-04 00:49:04 +0000205 #register events at the controls
cliechtid5d51982008-04-10 23:48:55 +0000206 self.Bind(wx.EVT_MENU, self.OnClear, id = ID_CLEAR)
207 self.Bind(wx.EVT_MENU, self.OnSaveAs, id = ID_SAVEAS)
208 self.Bind(wx.EVT_MENU, self.OnExit, id = ID_EXIT)
209 self.Bind(wx.EVT_MENU, self.OnPortSettings, id = ID_SETTINGS)
210 self.Bind(wx.EVT_MENU, self.OnTermSettings, id = ID_TERM)
211 self.text_ctrl_output.Bind(wx.EVT_CHAR, self.OnKey)
cliechtibc318d42004-11-13 03:13:12 +0000212 self.Bind(EVT_SERIALRX, self.OnSerialRead)
cliechtid5d51982008-04-10 23:48:55 +0000213 self.Bind(wx.EVT_CLOSE, self.OnClose)
cliechti80a0ed12003-10-03 23:53:42 +0000214
Chris Liechtibe00ee92015-09-12 02:02:04 +0200215 def OnExit(self, event): # wxGlade: TerminalFrame.<event_handler>
cliechti80a0ed12003-10-03 23:53:42 +0000216 """Menu point Exit"""
217 self.Close()
218
219 def OnClose(self, event):
cliechti0eb86712003-10-04 00:49:04 +0000220 """Called on application shutdown."""
Chris Liechtibe00ee92015-09-12 02:02:04 +0200221 self.StopThread() # stop reader thread
222 self.serial.close() # cleanup
223 self.Destroy() # close windows, exit app
cliechti80a0ed12003-10-03 23:53:42 +0000224
Chris Liechtibe00ee92015-09-12 02:02:04 +0200225 def OnSaveAs(self, event): # wxGlade: TerminalFrame.<event_handler>
cliechti80a0ed12003-10-03 23:53:42 +0000226 """Save contents of output window."""
227 filename = None
Chris Liechtibe00ee92015-09-12 02:02:04 +0200228 with wx.FileDialog(
229 None,
230 "Save Text As...",
231 ".",
232 "",
233 "Text File|*.txt|All Files|*",
234 wx.SAVE) as dlg:
235 if dlg.ShowModal() == wx.ID_OK:
236 filename = dlg.GetPath()
cliechti80a0ed12003-10-03 23:53:42 +0000237
238 if filename is not None:
Chris Liechtibe00ee92015-09-12 02:02:04 +0200239 with file(filename, 'w') as f:
240 text = self.text_ctrl_output.GetValue()
241 if type(text) == unicode:
242 text = text.encode("latin1") # hm, is that a good asumption?
243 f.write(text)
cliechti80a0ed12003-10-03 23:53:42 +0000244
Chris Liechtibe00ee92015-09-12 02:02:04 +0200245 def OnClear(self, event): # wxGlade: TerminalFrame.<event_handler>
cliechti80a0ed12003-10-03 23:53:42 +0000246 """Clear contents of output window."""
247 self.text_ctrl_output.Clear()
248
Chris Liechtibe00ee92015-09-12 02:02:04 +0200249 def OnPortSettings(self, event): # wxGlade: TerminalFrame.<event_handler>
cliechti0eb86712003-10-04 00:49:04 +0000250 """Show the portsettings dialog. The reader thread is stopped for the
251 settings change."""
Chris Liechtibe00ee92015-09-12 02:02:04 +0200252 if event is not None: # will be none when called on startup
cliechti0eb86712003-10-04 00:49:04 +0000253 self.StopThread()
254 self.serial.close()
255 ok = False
256 while not ok:
Chris Liechtibe00ee92015-09-12 02:02:04 +0200257 with wxSerialConfigDialog.SerialConfigDialog(
258 None,
259 -1,
260 "",
261 show=wxSerialConfigDialog.SHOW_BAUDRATE|wxSerialConfigDialog.SHOW_FORMAT|wxSerialConfigDialog.SHOW_FLOW,
262 serial=self.serial) as dialog_serial_cfg:
263 result = dialog_serial_cfg.ShowModal()
264 # open port if not called on startup, open it on startup and OK too
cliechtid5d51982008-04-10 23:48:55 +0000265 if result == wx.ID_OK or event is not None:
cliechti0eb86712003-10-04 00:49:04 +0000266 try:
267 self.serial.open()
Chris Liechti4caf6a52015-08-04 01:07:45 +0200268 except serial.SerialException as e:
Chris Liechtibe00ee92015-09-12 02:02:04 +0200269 with wx.MessageDialog(None, str(e), "Serial Port Error", wx.OK | wx.ICON_ERROR)as dlg:
270 dlg.ShowModal()
cliechti0eb86712003-10-04 00:49:04 +0000271 else:
272 self.StartThread()
273 self.SetTitle("Serial Terminal on %s [%s, %s%s%s%s%s]" % (
Chris Liechtibe00ee92015-09-12 02:02:04 +0200274 self.serial.portstr,
275 self.serial.baudrate,
276 self.serial.bytesize,
277 self.serial.parity,
278 self.serial.stopbits,
279 ' RTS/CTS' if self.serial.rtscts else '',
280 ' Xon/Xoff' if self.serial.xonxoff else '',
281 ))
cliechti0eb86712003-10-04 00:49:04 +0000282 ok = True
283 else:
Chris Liechtibe00ee92015-09-12 02:02:04 +0200284 # on startup, dialog aborted
cliechtibc318d42004-11-13 03:13:12 +0000285 self.alive.clear()
cliechti0eb86712003-10-04 00:49:04 +0000286 ok = True
cliechti80a0ed12003-10-03 23:53:42 +0000287
Chris Liechtibe00ee92015-09-12 02:02:04 +0200288 def OnTermSettings(self, event): # wxGlade: TerminalFrame.<event_handler>
289 """\
290 Menu point Terminal Settings. Show the settings dialog
291 with the current terminal settings.
292 """
cliechti80a0ed12003-10-03 23:53:42 +0000293 dialog = TerminalSettingsDialog(None, -1, "", settings=self.settings)
294 result = dialog.ShowModal()
295 dialog.Destroy()
Chris Liechti4caf6a52015-08-04 01:07:45 +0200296
cliechti80a0ed12003-10-03 23:53:42 +0000297 def OnKey(self, event):
Chris Liechtibe00ee92015-09-12 02:02:04 +0200298 """\
299 Key event handler. if the key is in the ASCII range, write it to the
300 serial port. Newline handling and local echo is also done here.
301 """
cliechti80a0ed12003-10-03 23:53:42 +0000302 code = event.GetKeyCode()
Chris Liechtibe00ee92015-09-12 02:02:04 +0200303 if code < 256: # is it printable?
304 if code == 13: # is it a newline? (check for CR which is the RETURN key)
305 if self.settings.echo: # do echo if needed
cliechti80a0ed12003-10-03 23:53:42 +0000306 self.text_ctrl_output.AppendText('\n')
307 if self.settings.newline == NEWLINE_CR:
Chris Liechtibe00ee92015-09-12 02:02:04 +0200308 self.serial.write('\r') # send CR
cliechti80a0ed12003-10-03 23:53:42 +0000309 elif self.settings.newline == NEWLINE_LF:
Chris Liechtibe00ee92015-09-12 02:02:04 +0200310 self.serial.write('\n') # send LF
cliechti80a0ed12003-10-03 23:53:42 +0000311 elif self.settings.newline == NEWLINE_CRLF:
Chris Liechtibe00ee92015-09-12 02:02:04 +0200312 self.serial.write('\r\n') # send CR+LF
cliechti80a0ed12003-10-03 23:53:42 +0000313 else:
314 char = chr(code)
Chris Liechtibe00ee92015-09-12 02:02:04 +0200315 if self.settings.echo: # do echo if needed
cliechti80a0ed12003-10-03 23:53:42 +0000316 self.text_ctrl_output.WriteText(char)
Chris Liechtibe00ee92015-09-12 02:02:04 +0200317 self.serial.write(char) # send the charcater
cliechti0eb86712003-10-04 00:49:04 +0000318 else:
Chris Liechti4caf6a52015-08-04 01:07:45 +0200319 print("Extra Key:", code)
cliechti80a0ed12003-10-03 23:53:42 +0000320
cliechti40d71f62004-07-09 22:14:17 +0000321 def OnSerialRead(self, event):
cliechti0eb86712003-10-04 00:49:04 +0000322 """Handle input from the serial port."""
cliechti40d71f62004-07-09 22:14:17 +0000323 text = event.data
cliechti80a0ed12003-10-03 23:53:42 +0000324 if self.settings.unprintable:
325 text = ''.join([(c >= ' ') and c or '<%d>' % ord(c) for c in text])
326 self.text_ctrl_output.AppendText(text)
327
328 def ComPortThread(self):
Chris Liechtibe00ee92015-09-12 02:02:04 +0200329 """\
330 Thread that handles the incomming traffic. Does the basic input
331 transformation (newlines) and generates an SerialRxEvent
332 """
333 while self.alive.isSet():
334 b = self.serial.read(self.serial.in_waiting or 1)
335 if b:
336 # newline transformation
cliechti80a0ed12003-10-03 23:53:42 +0000337 if self.settings.newline == NEWLINE_CR:
Chris Liechtibe00ee92015-09-12 02:02:04 +0200338 b = b.replace('\r', '\n')
cliechti80a0ed12003-10-03 23:53:42 +0000339 elif self.settings.newline == NEWLINE_LF:
340 pass
341 elif self.settings.newline == NEWLINE_CRLF:
Chris Liechtibe00ee92015-09-12 02:02:04 +0200342 b = b.replace('\r\n', '\n')
343 event = SerialRxEvent(self.GetId(), b)
cliechti40d71f62004-07-09 22:14:17 +0000344 self.GetEventHandler().AddPendingEvent(event)
Chris Liechtibe00ee92015-09-12 02:02:04 +0200345 #~ self.OnSerialRead(text) # output text in window
346
347 def OnRTS(self, event): # wxGlade: TerminalFrame.<event_handler>
348 self.serial.rts = event.IsChecked()
349
350 def OnDTR(self, event): # wxGlade: TerminalFrame.<event_handler>
351 self.serial.dtr = event.Checked()
Chris Liechti4caf6a52015-08-04 01:07:45 +0200352
cliechti80a0ed12003-10-03 23:53:42 +0000353# end of class TerminalFrame
354
355
cliechtid5d51982008-04-10 23:48:55 +0000356class MyApp(wx.App):
cliechti80a0ed12003-10-03 23:53:42 +0000357 def OnInit(self):
cliechtid5d51982008-04-10 23:48:55 +0000358 wx.InitAllImageHandlers()
cliechti80a0ed12003-10-03 23:53:42 +0000359 frame_terminal = TerminalFrame(None, -1, "")
360 self.SetTopWindow(frame_terminal)
Chris Liechtibe00ee92015-09-12 02:02:04 +0200361 frame_terminal.Show(True)
cliechti80a0ed12003-10-03 23:53:42 +0000362 return 1
363
364# end of class MyApp
365
366if __name__ == "__main__":
367 app = MyApp(0)
368 app.MainLoop()