#! /usr/bin/python # generated by wxGlade 0.3.1 on Fri Oct 03 23:23:45 2003 #from wxPython.wx import * import wx import wxSerialConfigDialog import serial import threading import time #---------------------------------------------------------------------- # Create an own event type, so that GUI updates can be delegated # this is required as on some platforms only the main thread can # access the GUI without crashing. wxMutexGuiEnter/wxMutexGuiLeave # could be used too, but an event is more elegant. SERIALRX = wx.NewEventType() # bind to serial data receive events EVT_SERIALRX = wx.PyEventBinder(SERIALRX, 0) class SerialRxEvent(wx.PyCommandEvent): eventType = SERIALRX def __init__(self, windowID, data): wx.PyCommandEvent.__init__(self, self.eventType, windowID) self.data = data def Clone(self): self.__class__(self.GetId(), self.data) #---------------------------------------------------------------------- ID_CLEAR = wx.NewId() ID_SAVEAS = wx.NewId() ID_SETTINGS = wx.NewId() ID_TERM = wx.NewId() ID_EXIT = wx.NewId() NEWLINE_CR = 0 NEWLINE_LF = 1 NEWLINE_CRLF = 2 ################ DOMOTIKA MESSAGES ################# TERMINATOR='\xff' START_SERIAL_MESSAGE='\x15' SERIAL_PROTOCOL_VERSION_BYTE1='\x00' SERIAL_PROTOCOL_VERSION_BYTE2='\x00' SERIAL_PROTOCOL_VERSION_BYTE3='\x01' # PROTOCOL COMMANDS SP_SPECIAL_COMMAND='\x00' SP_CARD_TYPE='\x01' SP_PROTOCOL_VERSION='\x02' SP_SOFTWARE_VERSION='\x03' SP_IO_STATE='\x04' SP_IO_SET ='\x06' SP_INTERRUPT_EVENT='\x07' SP_IO_FULL_STATUS='\x08' # Special Commands SP_SPECIAL_MAGIK='\x00' SP_SPECIAL_ACKNACK='\x01' SP_ALARM='\xff\xff\xff\xff' # Magik words SP_MGK_REBOOT='\xde\xad' SP_MGK_BOOTLOADER='\xca\xfe' SP_MGK_ERASE_EEPROM='\xfa\x11' SP_MGK_ASK_INITIALIZE='\xb0\x01' SP_MGK_ASK_READY='\x15\xb0' SP_MGK_ISREADY='\xb0\xff' # ACK/NACK and so on SP_OK='\x00\x00' SP_KO='\x00\x01' SP_ACK='\x01\x00' SP_NACK='\x01\x01' SP_YES='\x02\x00' SP_NO='\x02\x01' # OTHERS SP_VALUE_DIGITAL0='\x00\x00' SP_VALUE_DIGITAL1='\xff\xff' # I/O types SP_IOTYPE_RELAY1='\xF0' SP_IOTYPE_RELAY2='\xF1' SP_IOTYPE_RELAY3='\xF2' SP_IOTYPE_RELAY4='\xF3' SP_IOTYPE_RELAY5='\xF4' SP_IOTYPE_RELAY6='\xF5' SP_IOTYPE_RELAY7='\xF6' SP_IOTYPE_RELAY8='\xF7' SP_IOTYPE_RELAY9='\xF8' SP_IOTYPE_RELAY10='\xF9' SP_IOTYPE_RELAY11='\xFA' SP_IOTYPE_RELAY12='\xFB' SP_IOTYPE_DIGITAL_INPUT1='\x00' SP_IOTYPE_DIGITAL_INPUT2='\x01' SP_IOTYPE_DIGITAL_INPUT3='\x02' SP_IOTYPE_DIGITAL_INPUT4='\x03' SP_IOTYPE_DIGITAL_INPUT5='\x04' SP_IOTYPE_DIGITAL_INPUT6='\x05' SP_IOTYPE_DIGITAL_INPUT7='\x06' SP_IOTYPE_DIGITAL_INPUT8='\x07' SP_IOTYPE_DIGITAL_INPUT9='\x08' SP_IOTYPE_DIGITAL_INPUT10='\x09' SP_IOTYPE_DIGITAL_INPUT11='\x0A' SP_IOTYPE_DIGITAL_INPUT12='\x0B' # INTERRUPTS SP_INTERRUPT_EXT_INPUT5='\x05' SP_INTERRUPT_EXT_INPUT6='\x06' SP_INTERRUPT_EXT_INPUT7='\x07' SP_INTERRUPT_EXT_INPUT8='\x08' #################################################### def hextobit(v): return list(bin(int(bytes(v), 16))[2:]) def bittohex(v): return hex(int("0b"+"".join(v), 2)) def checksum(b, word): # XXX Bisogna migliorare sto checksum, cosi' non ha senso a=ord(word[0])+ord(word[1])+ord(word[2])+ord(word[3]) #print ord(b), [b], a, ord(word[3]) #c=chr(int(a, 16)) #print hex(a), ord(b) if word[3]==b: return True # Will be changed! return True def parse(word): b1=word[0] b2=word[1] b3=word[2] b4=word[3] if b1 == SP_SPECIAL_COMMAND: if b2 == SP_SPECIAL_MAGIK: if b3+b4 == SP_MGK_REBOOT: return 'SPECIAL_COMMAND received (MAGICK REBOOT)' elif b3+b4 == SP_MGK_BOOTLOADER: return 'SPECIAL COMMAND (MAGICK BOOTLOADER)' elif b3+b4 == SP_MGK_ERASE_EEPROM: return 'SPECIAL COMMAND (MAGICK ERASE EEPROM)' elif b3+b4 == SP_MGK_ASK_INITIALIZE: return 'SPECIAL COMMAND (MAGICK ASK INITIALIZE)' elif b3+b4 == SP_MGK_ASK_READY: return 'SPECIAL COMMAND (MAGICK ASK READY)' elif b3+b4 == SP_MGK_ISREADY: return 'SPECIAL COMMAND (MAGICK IS READY)' elif b2 == SP_SPECIAL_ACKNACK: if b3+b4 == SP_ACK: return 'SPECIAL COMMAND (MAGICK ACK)' elif b3+b4 == SP_NACK: return 'SPECIAL COMMAND (MAGICK NACK)' elif b3+b4 == SP_YES: return 'SPECIAL COMMAND (MAGICK YES)' elif b3+b4 == SP_NO: return 'SPECIAL COMMAND (MAGICK NO)' elif b3+b4 == SP_OK: return 'SPECIAL COMMAND (MAGICK OK)' elif b3+b4 == SP_KO: return 'SPECIAL COMMAND (MAGICK KO)' elif b1 == SP_CARD_TYPE: return 'CARD TYPE received (%s)' % str([b2, b3, b4]) elif b1 == SP_PROTOCOL_VERSION: return 'PROTOCOL VERSION received (%s)' % str([b2, b3, b4]) elif b1 == SP_IO_STATE: if b3+b4 == SP_VALUE_DIGITAL0: val = "VALUE: 0" else: val = "VALUE: 1" if b2 == SP_IOTYPE_RELAY1: return 'IO STATE received, RELAY1 %s' % val elif b2 == SP_IOTYPE_RELAY2: return 'IO STATE received, RELAY2 %s' % val elif b2 == SP_IOTYPE_RELAY3: return 'IO STATE received, RELAY3 %s' % val elif b2 == SP_IOTYPE_RELAY4: return 'IO STATE received, RELAY4 %s' % val elif b2 == SP_IOTYPE_RELAY5: return 'IO STATE received, RELAY5 %s' % val elif b2 == SP_IOTYPE_RELAY6: return 'IO STATE received, RELAY6 %s' % val elif b2 == SP_IOTYPE_RELAY7: return 'IO STATE received, RELAY7 %s' % val elif b2 == SP_IOTYPE_RELAY8: return 'IO STATE received, RELAY8 %s' % val elif b2 == SP_IOTYPE_RELAY9: return 'IO STATE received, RELAY9 %s' % val elif b2 == SP_IOTYPE_RELAY10: return 'IO STATE received, RELAY10 %s' % val elif b2 == SP_IOTYPE_RELAY11: return 'IO STATE received, RELAY11 %s' % val elif b2 == SP_IOTYPE_RELAY12: return 'IO STATE received, RELAY12 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT1: return 'IO STATE received, INPUT1 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT12: return 'IO STATE received, INPUT12 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT2: return 'IO STATE received, INPUT2 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT3: return 'IO STATE received, INPUT3 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT4: return 'IO STATE received, INPUT4 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT5: return 'IO STATE received, INPUT5 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT6: return 'IO STATE received, INPUT6 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT7: return 'IO STATE received, INPUT7 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT8: return 'IO STATE received, INPUT8 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT9: return 'IO STATE received, INPUT9 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT10: return 'IO STATE received, INPUT10 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT11: return 'IO STATE received, INPUT11 %s' % val elif b1 == SP_IO_SET: if b3+b4 == SP_VALUE_DIGITAL0: val = "VALUE: 0" else: val = "VALUE: 1" if b2 == SP_IOTYPE_RELAY1: return 'IO SET received, RELAY1 %s' % val elif b2 == SP_IOTYPE_RELAY2: return 'IO SET received, RELAY2 %s' % val elif b2 == SP_IOTYPE_RELAY3: return 'IO SET received, RELAY3 %s' % val elif b2 == SP_IOTYPE_RELAY4: return 'IO SET received, RELAY4 %s' % val elif b2 == SP_IOTYPE_RELAY5: return 'IO SET received, RELAY5 %s' % val elif b2 == SP_IOTYPE_RELAY6: return 'IO SET received, RELAY6 %s' % val elif b2 == SP_IOTYPE_RELAY7: return 'IO SET received, RELAY7 %s' % val elif b2 == SP_IOTYPE_RELAY8: return 'IO SET received, RELAY8 %s' % val elif b2 == SP_IOTYPE_RELAY9: return 'IO SET received, RELAY9 %s' % val elif b2 == SP_IOTYPE_RELAY10: return 'IO SET received, RELAY10 %s' % val elif b2 == SP_IOTYPE_RELAY11: return 'IO SET received, RELAY11 %s' % val elif b2 == SP_IOTYPE_RELAY12: return 'IO SET received, RELAY12 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT1: return 'IO SET received, INPUT1 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT12: return 'IO SET received, INPUT12 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT2: return 'IO SET received, INPUT2 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT3: return 'IO SET received, INPUT3 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT4: return 'IO SET received, INPUT4 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT5: return 'IO SET received, INPUT5 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT6: return 'IO SET received, INPUT6 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT7: return 'IO SET received, INPUT7 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT8: return 'IO SET received, INPUT8 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT9: return 'IO SET received, INPUT9 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT10: return 'IO SET received, INPUT10 %s' % val elif b2 == SP_IOTYPE_DIGITAL_INPUT11: return 'IO SET received, INPUT11 %s' % val elif b1 == SP_INTERRUPT_EVENT: if b2 == SP_INTERRUPT_EXT_INPUT5: return 'EXT INTERRUPT INPUT5 received' if b2 == SP_INTERRUPT_EXT_INPUT6: return 'EXT INTERRUPT INPUT6 received' if b2 == SP_INTERRUPT_EXT_INPUT7: return 'EXT INTERRUPT INPUT7 received' if b2 == SP_INTERRUPT_EXT_INPUT8: return 'EXT INTERRUPT INPUT8 received' elif b1 == SP_IO_FULL_STATUS: #try: st=hextobit(hex(ord(b2)))+hextobit(hex(ord(b3)))+hextobit(hex(ord(b4))) #except: # print 'ERROR' # st = 'FULL STATUS ERROR' return 'FULL STATUS received (%s)' % str(st) elif b1+b2+b3+b4 == SP_ALARM: return 'ALARM!!!!!!!!' class TerminalSetup: """Placeholder for various terminal settings. Used to pass the options to the TerminalSettingsDialog.""" def __init__(self): self.echo = False self.unprintable = False self.newline = NEWLINE_CRLF class TerminalSettingsDialog(wx.Dialog): """Simple dialog with common terminal settings like echo, newline mode.""" def __init__(self, *args, **kwds): self.settings = kwds['settings'] del kwds['settings'] # begin wxGlade: TerminalSettingsDialog.__init__ kwds["style"] = wx.DEFAULT_DIALOG_STYLE wx.Dialog.__init__(self, *args, **kwds) self.checkbox_echo = wx.CheckBox(self, -1, "Local Echo") self.checkbox_unprintable = wx.CheckBox(self, -1, "Show unprintable characters") self.radio_box_newline = wx.RadioBox(self, -1, "Newline Handling", choices=["CR only", "LF only", "CR+LF"], majorDimension=0, style=wx.RA_SPECIFY_ROWS) self.button_ok = wx.Button(self, -1, "OK") self.button_cancel = wx.Button(self, -1, "Cancel") self.__set_properties() self.__do_layout() # end wxGlade self.__attach_events() self.checkbox_echo.SetValue(self.settings.echo) self.checkbox_unprintable.SetValue(self.settings.unprintable) self.radio_box_newline.SetSelection(self.settings.newline) def __set_properties(self): # begin wxGlade: TerminalSettingsDialog.__set_properties self.SetTitle("Terminal Settings") self.radio_box_newline.SetSelection(0) self.button_ok.SetDefault() # end wxGlade def __do_layout(self): # begin wxGlade: TerminalSettingsDialog.__do_layout sizer_2 = wx.BoxSizer(wx.VERTICAL) sizer_3 = wx.BoxSizer(wx.HORIZONTAL) sizer_4 = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Input/Output"), wx.VERTICAL) sizer_4.Add(self.checkbox_echo, 0, wx.ALL, 4) sizer_4.Add(self.checkbox_unprintable, 0, wx.ALL, 4) sizer_4.Add(self.radio_box_newline, 0, 0, 0) sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) sizer_3.Add(self.button_ok, 0, 0, 0) sizer_3.Add(self.button_cancel, 0, 0, 0) sizer_2.Add(sizer_3, 0, wx.ALL|wx.ALIGN_RIGHT, 4) self.SetAutoLayout(1) self.SetSizer(sizer_2) sizer_2.Fit(self) sizer_2.SetSizeHints(self) self.Layout() # end wxGlade def __attach_events(self): self.Bind(wx.EVT_BUTTON, self.OnOK, id = self.button_ok.GetId()) self.Bind(wx.EVT_BUTTON, self.OnCancel, id = self.button_cancel.GetId()) def OnOK(self, events): """Update data wil new values and close dialog.""" self.settings.echo = self.checkbox_echo.GetValue() self.settings.unprintable = self.checkbox_unprintable.GetValue() self.settings.newline = self.radio_box_newline.GetSelection() self.EndModal(wx.ID_OK) def OnCancel(self, events): """Do not update data but close dialog.""" self.EndModal(wx.ID_CANCEL) # end of class TerminalSettingsDialog class TerminalFrame(wx.Frame): """Simple terminal program for wxPython""" def __init__(self, *args, **kwds): self.serial = serial.Serial() self.serial.timeout = 0.5 #make sure that the alive event can be checked from time to time self.settings = TerminalSetup() #placeholder for the settings self.thread = None self.alive = threading.Event() # begin wxGlade: TerminalFrame.__init__ kwds["style"] = wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) self.text_ctrl_output = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY) # Menu Bar self.frame_terminal_menubar = wx.MenuBar() self.SetMenuBar(self.frame_terminal_menubar) wxglade_tmp_menu = wx.Menu() wxglade_tmp_menu.Append(ID_CLEAR, "&Clear", "", wx.ITEM_NORMAL) wxglade_tmp_menu.Append(ID_SAVEAS, "&Save Text As...", "", wx.ITEM_NORMAL) wxglade_tmp_menu.AppendSeparator() wxglade_tmp_menu.Append(ID_SETTINGS, "&Port Settings...", "", wx.ITEM_NORMAL) wxglade_tmp_menu.Append(ID_TERM, "&Terminal Settings...", "", wx.ITEM_NORMAL) wxglade_tmp_menu.AppendSeparator() wxglade_tmp_menu.Append(ID_EXIT, "&Exit", "", wx.ITEM_NORMAL) self.frame_terminal_menubar.Append(wxglade_tmp_menu, "&File") # Menu Bar end self.button_changeRelay1 = wx.Button(self, -1, "Relay1 (for master)") self.button_changeRelay2 = wx.Button(self, -1, "Relay1 (for slave)") self.button_changeInput1 = wx.Button(self, -1, "Input1 (for master)") self.button_loop = wx.Button(self, -1, "Loop") self.__set_properties() self.__do_layout() # end wxGlade self.__attach_events() #register events self.OnPortSettings(None) #call setup dialog on startup, opens port if not self.alive.isSet(): self.Close() def StartThread(self): """Start the receiver thread""" self.thread = threading.Thread(target=self.ComPortThread) self.thread.setDaemon(1) self.alive.set() self.thread.start() def StopThread(self): """Stop the receiver thread, wait util it's finished.""" if self.thread is not None: self.alive.clear() #clear alive event for thread self.thread.join() #wait until thread has finished self.thread = None def __set_properties(self): # begin wxGlade: TerminalFrame.__set_properties self.SetTitle("Serial Terminal") self.SetSize((546, 383)) # end wxGlade def __do_layout(self): # begin wxGlade: TerminalFrame.__do_layout sizer_1 = wx.BoxSizer(wx.VERTICAL) sizer_2 = wx.BoxSizer(wx.VERTICAL) sizer_3 = wx.BoxSizer(wx.HORIZONTAL) sizer_3.Add(self.button_changeRelay1, 1) sizer_3.Add(self.button_changeRelay2, 1) sizer_4 = wx.BoxSizer(wx.HORIZONTAL) sizer_4.Add(self.button_changeInput1, 1) sizer_4.Add(self.button_loop, 1) sizer_2.Add(sizer_3, 1, wx.EXPAND, 0) sizer_2.Add(sizer_4, 1, wx.EXPAND, 0) sizer_1.Add(sizer_2, 0, wx.EXPAND, 0) sizer_1.Add(self.text_ctrl_output, 1, wx.EXPAND, 0) self.SetAutoLayout(1) self.SetSizer(sizer_1) self.Layout() # end wxGlade def __attach_events(self): #register events at the controls self.Bind(wx.EVT_MENU, self.OnClear, id = ID_CLEAR) self.Bind(wx.EVT_MENU, self.OnSaveAs, id = ID_SAVEAS) self.Bind(wx.EVT_MENU, self.OnExit, id = ID_EXIT) self.Bind(wx.EVT_MENU, self.OnPortSettings, id = ID_SETTINGS) self.Bind(wx.EVT_MENU, self.OnTermSettings, id = ID_TERM) self.text_ctrl_output.Bind(wx.EVT_CHAR, self.OnKey) self.Bind(EVT_SERIALRX, self.OnSerialRead) self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_BUTTON, self.OnRelay1, id = self.button_changeRelay1.GetId()) self.Bind(wx.EVT_BUTTON, self.OnRelay2, id = self.button_changeRelay2.GetId()) self.Bind(wx.EVT_BUTTON, self.OnInput1, id = self.button_changeInput1.GetId()) self.Bind(wx.EVT_BUTTON, self.OnLoop, id = self.button_loop.GetId()) def OnLoop(self, events): try: if self.loop == 0: self.loop = 1 else: self.loop = 0 except: self.loop = 0 def OnRelay1(self, events): try: if self.relay1 == 0: self.sendRelay1_ON() self.relay1 = 1 else: self.sendRelay1_OFF() self.relay1 = 0 except: self.sendRelay1_OFF() self.relay1 = 0 def OnRelay2(self, events): try: if self.relay2 == 0: self.sendRelay2_ON() self.relay2 = 1 else: self.sendRelay2_OFF() self.relay2 = 0 except: self.sendRelay2_OFF() self.relay2 = 0 def OnInput1(self, events): try: if self.input1 == 0: self.sendInput1_ON() self.input1 = 1 else: self.sendInput1_OFF() self.input1 = 0 except: self.sendInput1_OFF() self.input1 = 0 def sendCommand(self, cmd): cmds = [START_SERIAL_MESSAGE, '\x00', cmd[0], cmd[1], cmd[2], cmd[3], '\x00', TERMINATOR] print 'SENT COMMAND: %s' % cmds self.serial.write(START_SERIAL_MESSAGE) self.serial.write('\x00') #self.serial.write(cmd) for i in list(cmd): self.serial.write(i) self.serial.write('\x00') self.serial.write(TERMINATOR) def sendRelay1_OFF(self): self.sendCommand(SP_IO_STATE+SP_IOTYPE_RELAY1+SP_VALUE_DIGITAL0) def sendRelay1_ON(self): self.sendCommand(SP_IO_STATE+SP_IOTYPE_RELAY1+SP_VALUE_DIGITAL1) def sendInput1_OFF(self): self.sendCommand(SP_IO_STATE+SP_IOTYPE_DIGITAL_INPUT1+SP_VALUE_DIGITAL0) def sendInput1_ON(self): self.sendCommand(SP_IO_STATE+SP_IOTYPE_DIGITAL_INPUT1+SP_VALUE_DIGITAL1) def sendRelay2_OFF(self): self.sendCommand(SP_IO_SET+SP_IOTYPE_RELAY1+SP_VALUE_DIGITAL0) def sendRelay2_ON(self): self.sendCommand(SP_IO_SET+SP_IOTYPE_RELAY1+SP_VALUE_DIGITAL1) def OnExit(self, event): """Menu point Exit""" self.Close() def OnClose(self, event): """Called on application shutdown.""" self.StopThread() #stop reader thread self.serial.close() #cleanup self.Destroy() #close windows, exit app def OnSaveAs(self, event): """Save contents of output window.""" filename = None dlg = wx.FileDialog(None, "Save Text As...", ".", "", "Text File|*.txt|All Files|*", wx.SAVE) if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() dlg.Destroy() if filename is not None: f = file(filename, 'w') text = self.text_ctrl_output.GetValue() if type(text) == unicode: text = text.encode("latin1") #hm, is that a good asumption? f.write(text) f.close() def OnClear(self, event): """Clear contents of output window.""" self.text_ctrl_output.Clear() def OnPortSettings(self, event=None): """Show the portsettings dialog. The reader thread is stopped for the settings change.""" if event is not None: #will be none when called on startup self.StopThread() self.serial.close() ok = False while not ok: dialog_serial_cfg = wxSerialConfigDialog.SerialConfigDialog(None, -1, "", show=wxSerialConfigDialog.SHOW_BAUDRATE|wxSerialConfigDialog.SHOW_FORMAT|wxSerialConfigDialog.SHOW_FLOW, serial=self.serial ) result = dialog_serial_cfg.ShowModal() dialog_serial_cfg.Destroy() #open port if not called on startup, open it on startup and OK too if result == wx.ID_OK or event is not None: try: self.serial.open() except serial.SerialException, e: dlg = wx.MessageDialog(None, str(e), "Serial Port Error", wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() else: self.StartThread() self.SetTitle("Serial Terminal on %s [%s, %s%s%s%s%s]" % ( self.serial.portstr, self.serial.baudrate, self.serial.bytesize, self.serial.parity, self.serial.stopbits, self.serial.rtscts and ' RTS/CTS' or '', self.serial.xonxoff and ' Xon/Xoff' or '', ) ) ok = True else: #on startup, dialog aborted self.alive.clear() ok = True def OnTermSettings(self, event): """Menu point Terminal Settings. Show the settings dialog with the current terminal settings""" dialog = TerminalSettingsDialog(None, -1, "", settings=self.settings) result = dialog.ShowModal() dialog.Destroy() def OnKey(self, event): """Key event handler. if the key is in the ASCII range, write it to the serial port. Newline handling and local echo is also done here.""" code = event.GetKeyCode() if code < 256: #is it printable? if code == 13: #is it a newline? (check for CR which is the RETURN key) if self.settings.echo: #do echo if needed self.text_ctrl_output.AppendText('\n') if self.settings.newline == NEWLINE_CR: self.serial.write('\r') #send CR elif self.settings.newline == NEWLINE_LF: self.serial.write('\n') #send LF elif self.settings.newline == NEWLINE_CRLF: self.serial.write('\r\n') #send CR+LF else: char = chr(code) if self.settings.echo: #do echo if needed self.text_ctrl_output.WriteText(char) self.serial.write(char) #send the charcater else: print "Extra Key:", code def OnSerialRead(self, event): """Handle input from the serial port.""" text = event.data if self.settings.unprintable: text = ''.join([(c >= ' ') and c or '<%d>' % ord(c) for c in text]) self.text_ctrl_output.AppendText(text) def ComPortThread(self): """Thread that handles the incomming traffic. Does the basic input transformation (newlines) and generates an SerialRxEvent""" c=0 while self.alive.isSet(): #loop while alive event is true newbyte = self.serial.read(1) #read one, with timout if newbyte: print 'RECEIVED BYTE: ', [newbyte] try: if self.loop == 1: print 'REWRITING IN LOOP: ', [newbyte] self.serial.write(newbyte) except: pass if newbyte == START_SERIAL_MESSAGE and c==0: print 'possible start' c=c+1 word=[] elif c==1: # XXX Not used for the moment. c=c+1 elif c >= 2 and len(word) < 4: word.append(newbyte) c=c+1 elif c==6: print 'WORD', word chk=checksum(newbyte, word) if not chk: print 'checksum not valid' c=0 else: c=c+1 elif c==7: if newbyte==TERMINATOR: #print 'terminator received' res=parse(word) if res: event = SerialRxEvent(self.GetId(), str(time.time())+" -> "+res+"\n") self.GetEventHandler().AddPendingEvent(event) else: print 'terminator not valid' #print 'TERMINATOR', ord(TERMINATOR), ord(newbyte) c=0 else: #print 'FUORI CICLO' c=0 #print ord(newbyte) #print START_SERIAL_MESSAGE #newline transformation #if self.settings.newline == NEWLINE_CR: # text = text.replace('\r', '\n') #elif self.settings.newline == NEWLINE_LF: # pass #elif self.settings.newline == NEWLINE_CRLF: # text = text.replace('\r\n', '\n') #event = SerialRxEvent(self.GetId(), text) #self.GetEventHandler().AddPendingEvent(event) #NONO~ self.OnSerialRead(text) #output text in window # end of class TerminalFrame class MyApp(wx.App): def OnInit(self): wx.InitAllImageHandlers() frame_terminal = TerminalFrame(None, -1, "") self.SetTopWindow(frame_terminal) frame_terminal.Show(1) return 1 # end of class MyApp if __name__ == "__main__": app = MyApp(0) app.MainLoop()