From a277463931bfe172483db47537a3be5945d71087 Mon Sep 17 00:00:00 2001 From: sven Date: Sun, 24 Nov 2019 10:16:36 +0100 Subject: [PATCH] Added support for serial port fixing. --- pyswap/requirements.txt | 2 + pyswap/swap/SwapServer.py | 152 +++++++++++++------------- pyswap/swap/modem/SerialModem.py | 86 ++++++++------- pyswap/swap/modem/list_serial_port.py | 95 ++++++++++++++++ pyswap/swap/xmltools/XmlSerial.py | 29 +++-- swapdmt-cmd/swapdmt.py | 21 ++-- swapdmt/SerialDialog.py | 5 +- swapdmt/config/serial.xml | 1 + 8 files changed, 254 insertions(+), 137 deletions(-) create mode 100644 pyswap/requirements.txt create mode 100644 pyswap/swap/modem/list_serial_port.py diff --git a/pyswap/requirements.txt b/pyswap/requirements.txt new file mode 100644 index 0000000..362b989 --- /dev/null +++ b/pyswap/requirements.txt @@ -0,0 +1,2 @@ +pyserial +prettytable diff --git a/pyswap/swap/SwapServer.py b/pyswap/swap/SwapServer.py index 322ccb6..b8b6969 100644 --- a/pyswap/swap/SwapServer.py +++ b/pyswap/swap/SwapServer.py @@ -3,22 +3,22 @@ # SwapServer # # Copyright (c) 2011 panStamp -# +# # This file is part of the panStamp project. -# +# # panStamp is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 3 of the License, or # any later version. -# +# # panStamp is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. -# +# # You should have received a copy of the GNU Lesser General Public License # along with panStamp; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA # ######################################################################### @@ -56,27 +56,29 @@ class SwapServer(threading.Thread): # Max tries for any SWAP command _MAX_SWAP_COMMAND_TRIES = 3 - + def run(self): """ Start SWAP server thread - """ + """ try: # Network configuration settings self._xmlnetwork = XmlNetwork(self._xmlSettings.network_file) self.devaddress = self._xmlnetwork.devaddress self.security = self._xmlnetwork.security self.password = Password(self._xmlnetwork.password) - + # Serial configuration settings self._xmlserial = XmlSerial(self._xmlSettings.serial_file) - + # Create and start serial modem object - self.modem = SerialModem(self._xmlserial.port, self._xmlserial.speed, self.verbose) + self.modem = SerialModem(self._xmlserial.port, + self._xmlserial.portfix, + self._xmlserial.speed, self.verbose) # Declare receiving callback function self.modem.setRxCallback(self._ccPacketReceived) - + # Set modem configuration from _xmlnetwork param_changed = False # Device address @@ -100,46 +102,46 @@ def run(self): raise SwapException("Unable to set modem's frequency channel to " + self._xmlnetwork.freq_channel) else: param_changed = True - + # Return to data mode if necessary if param_changed == True: self.modem.goToDataMode() - + self.is_running = True - + # Notify parent about the start of the server self._eventHandler.swapServerStarted() - + # Discover motes in the current SWAP network self._discoverMotes() except SwapException as ex: threading.Thread.__init__(self) # Report error to SwapInterface self._eventHandler.swapServerError(ex) - - threading.Thread.__init__(self) - + + threading.Thread.__init__(self) + def stop(self): """ Stop SWAP server """ - + print "Stopping SWAP server..." - + # Stop modem if self.modem is not None: self.modem.stop() self.is_running = False - + # Save network data print "Saving network data..." - + try: self.network.save() except SwapException: raise - + threading.Thread.__init__(self) @@ -150,21 +152,21 @@ def resetNetwork(self): # Clear network data self.network.read() - + def _ccPacketReceived(self, ccPacket): """ CcPacket received - - @param ccPacket: CcPacket received + + @param ccPacket: CcPacket received """ try: # Convert CcPacket into SwapPacket swPacket = SwapPacket(ccPacket) # Notify event - self._eventHandler.swapPacketReceived(swPacket) + self._eventHandler.swapPacketReceived(swPacket) except SwapException: return - + # Check function code # STATUS packet received if swPacket.function == SwapFunction.STATUS: @@ -228,15 +230,15 @@ def _ccPacketReceived(self, ccPacket): if mote.nonce != swPacket.nonce: # Nonce missmatch. Transmit correct nonce self.send_nonce() - return + return # Send command packet to target mote self.setMoteRegister(mote, swPacket.regId, swPacket.value, sendack=True) - + def _checkMote(self, mote): """ Check SWAP mote from against the current list - + @param mote: to be searched in the list """ # Add mote to the network @@ -252,21 +254,21 @@ def _checkMote(self, mote): for endp in reg.parameters: if self._eventHandler.newEndpointDetected is not None: self._eventHandler.newEndpointDetected(endp) - + if self._poll_regular_regs: # Query all individual registers owned by this mote if mote.regular_registers is not None: for reg in mote.regular_registers: reg.sendSwapQuery() - - + + def _updateMoteAddress(self, oldAddr, newAddr): """ Update new mote address in list - + @param oldAddr: Old address @param newAddr: New address - + @return True if the value changed. False otherwise """ # Has the address really changed? @@ -279,7 +281,7 @@ def _updateMoteAddress(self, oldAddr, newAddr): # Notify address change to event handler if self._eventHandler.moteAddressChanged is not None: self._eventHandler.moteAddressChanged(mote) - + return True return False @@ -289,7 +291,7 @@ def _updateMoteState(self, packet): Update mote state in list @param packet: SWAP packet to extract the information from - + @return True if the value changed. False otherwise """ # New system state @@ -304,21 +306,21 @@ def _updateMoteState(self, packet): # Update mote's state mote.update_state(state) - + # Notify state change to event handler if self._eventHandler.moteStateChanged is not None: self._eventHandler.moteStateChanged(mote) return True return False - + def _updateMoteTxInterval(self, packet): """ Update mote Tx interval in list @param packet: SWAP packet to extract the information from - + @return True if the value changed. False otherwise """ # New periodic Tx interval (in seconds) @@ -333,11 +335,11 @@ def _updateMoteTxInterval(self, packet): # Update system state in the list mote.txinterval = interval - + return True return False - - + + def _updateRegisterValue(self, packet): """ Update register value in the list of motes @@ -406,7 +408,7 @@ def _checkStatus(self, status): if (self._expectedAck is not None) and (status.function == SwapFunction.STATUS): if status.regAddress == self._expectedAck.regAddress: if status.regId == self._expectedAck.regId: - self._packetAcked = self._expectedAck.value.isEqual(status.value) + self._packetAcked = self._expectedAck.value.isEqual(status.value) # Check possible response to a precedent query self._valueReceived = None @@ -417,19 +419,19 @@ def _checkStatus(self, status): # Update security option and nonce in list mote = self.network.get_mote(address=status.srcAddress) - - if mote is not None: + + if mote is not None: # Check nonce? if self._xmlnetwork.security & 0x01: # Discard status packet in case of incorrect nonce if mote.nonce > 0 and status.nonce != 1: lower_limit = mote.nonce upper_limit = mote.nonce + 5 - - + + if upper_limit > 0xFF: upper_limit -= 0x100 - + if not (lower_limit < status.nonce <= upper_limit): if (lower_limit > upper_limit): if not (lower_limit < status.nonce <= 0xFF): @@ -437,10 +439,10 @@ def _checkStatus(self, status): raise SwapException("Mote " + str(mote.address) + ": anti-playback nonce missmatch. Possible attack!") else: raise SwapException("Mote " + str(mote.address) + ": anti-playback nonce missmatch. Possible attack!") - + mote.security = status.security mote.nonce = status.nonce - + def _discoverMotes(self): """ @@ -478,7 +480,7 @@ def send_status(self, mote, regid): if self.nonce > 0xFF: self.nonce = 0 status.nonce = self.nonce - status.send(self) + status.send(self) def send_nonce(self): @@ -510,7 +512,7 @@ def setMoteRegister(self, mote, regid, value, sendack=False): """ # Send command multiple times if necessary for i in range(SwapServer._MAX_SWAP_COMMAND_TRIES): - # Send command + # Send command ack = mote.cmdRegister(regid, value) # Wait for aknowledgement from mote if self._waitForAck(ack, SwapServer._MAX_WAITTIME_ACK): @@ -532,7 +534,7 @@ def setEndpointValue(self, endpoint, value): """ # Send command multiple times if necessary for i in range(SwapServer._MAX_SWAP_COMMAND_TRIES): - # Send command + # Send command ack = endpoint.sendSwapCmd(value) # Wait for aknowledgement from mote if self._waitForAck(ack, SwapServer._MAX_WAITTIME_ACK): @@ -544,10 +546,10 @@ def queryMoteRegister(self, mote, regId): """ Query mote register, wait for response and return value Non re-entrant method!! - + @param mote: Mote containing the register @param regId: Register ID - + @return register value """ # Queried register @@ -570,20 +572,20 @@ def _waitForAck(self, ackpacket, wait_time): @param ackpacket: SWAP status packet to expect as a valid ACK @param wait_time: Max waiting time in milliseconds - + @return True if the ACK is received. False otherwise """ self._packetAcked = False # Expected ACK packet (SWAP status) self._expectedAck = ackpacket - + #loops = wait_time / 10 start = time.time() while not self._packetAcked: time.sleep(0.1) if (time.time() - start)*1000 >= wait_time: break - + res = self._packetAcked self._expectedAck = None self._packetAcked = False @@ -594,10 +596,10 @@ def _waitForReg(self, register, waitTime): """ Wait for ACK (SWAP status packet) Non re-entrant method!! - + @param register: Expected register to be informed about @param waitTime: Max waiting time in milliseconds - + @return True if the ACK is received. False otherwise """ # Expected ACK packet (SWAP status) @@ -619,7 +621,7 @@ def _waitForReg(self, register, waitTime): def getNetId(self): """ Get current network ID - + @return Network ID """ return self.modem.syncword @@ -635,8 +637,8 @@ def update_definition_files(self): try: os.stat(local_dir) except: - os.mkdir(local_dir) - + os.mkdir(local_dir) + try: local_file = XmlSettings.device_localdir + os.sep + "devices.xml" remote_file = XmlSettings.device_remote + "/devices.xml" @@ -648,7 +650,7 @@ def update_definition_files(self): print "Unable to download devices.xml from remote server" device_info = XmlDeviceDir() - + # Create developer folders for developer in device_info.developers: developer_dir = local_dir + os.sep + developer.name @@ -657,7 +659,7 @@ def update_definition_files(self): os.stat(developer_dir) except: os.mkdir(developer_dir) - + try: # Download device definition files for each developer folder for device in developer.devices: @@ -672,27 +674,27 @@ def update_definition_files(self): except Exception as e: print "Unable to update Device Definition File " + device_name + ".xml" - + """ local_tar = XmlSettings.device_localdir + ".tar" - + try: remote = urllib2.urlopen(XmlSettings.device_remote) local = open(local_tar, 'wb') local.write(remote.read()) local.close() - + tar = tarfile.open(local_tar) direc = os.path.dirname(XmlSettings.device_localdir) tar.extractall(path=direc) tar.close() - + os.remove(local_tar) except: print "Unable to update Device Definition Files" """ - - + + def __init__(self, eventHandler, settings=None, start=True): """ Class constructor @@ -753,10 +755,10 @@ def __init__(self, eventHandler, settings=None, start=True): ## Tells us if the server is running self.is_running = False - + ## Poll regular registers whenever a product code packet is received self._poll_regular_regs = False - + # Start server if start: self.start() diff --git a/pyswap/swap/modem/SerialModem.py b/pyswap/swap/modem/SerialModem.py index d29f5b1..6112d2f 100644 --- a/pyswap/swap/modem/SerialModem.py +++ b/pyswap/swap/modem/SerialModem.py @@ -3,22 +3,22 @@ # SerialModem # # Copyright (c) 2011 panStamp -# +# # This file is part of the panStamp project. -# +# # panStamp is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 3 of the License, or # any later version. -# +# # panStamp is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. -# +# # You should have received a copy of the GNU Lesser General Public License # along with panStamp; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA # ######################################################################### @@ -31,6 +31,7 @@ from SerialPort import SerialPort from CcPacket import CcPacket from swap.SwapException import SwapException +from list_serial_port import resolve_portname class SerialModem: """ @@ -57,9 +58,9 @@ def _serialPacketReceived(self, buf): """ Serial packet received. This is a callback function called from the SerialPort object - + @param buf: Serial packet received in String format - """ + """ # If modem in command mode if self._sermode == SerialModem.Mode.COMMAND: self._atresponse = buf @@ -82,28 +83,28 @@ def _serialPacketReceived(self, buf): def setRxCallback(self, cbFunct): """ Set callback reception function. Notify new CcPacket reception - + @param cbFunct: Definition of custom Callback function for the reception of packets """ self._ccpacket_received = cbFunct - + def goToCommandMode(self): """ Enter command mode (for AT commands) - + @return True if the serial gateway does enter Command Mode. Return false otherwise """ if self._sermode == SerialModem.Mode.COMMAND: return True - + self._sermode = SerialModem.Mode.COMMAND response = self.runAtCommand("+++", 5000) if response is not None: if response[:2] == "OK": return True - + self._sermode = SerialModem.Mode.DATA return False @@ -111,52 +112,52 @@ def goToCommandMode(self): def goToDataMode(self): """ Enter data mode (for Rx/Tx operations) - + @return True if the serial gateway does enter Data Mode. Return false otherwise """ if self._sermode == SerialModem.Mode.DATA: return True - + response = self.runAtCommand("ATO\r") - + if response is not None: if response[0:2] == "OK": self._sermode = SerialModem.Mode.DATA; return True; - + return False; - + def reset(self): """ Reset serial gateway - + @return True if the serial gateway is successfully restarted """ # Switch to command mode if necessary if self._sermode == SerialModem.Mode.DATA: self.goToCommandMode() - + # Default state after reset self._sermode = SerialModem.Mode.DATA # Run AT command response = self.runAtCommand("ATZ\r") if response is None: return False - + if "ready" in response or response[0:2] == "OK": return True - + return False def runAtCommand(self, cmd="AT\r", timeout=1000): """ Run AT command on the serial gateway - + @param cmd: AT command to be run @param timeout: Period after which the function should timeout - + @return Response received from gateway or None in case of lack of response (timeout) """ self.__atresponse_received = False @@ -168,7 +169,7 @@ def runAtCommand(self, cmd="AT\r", timeout=1000): self._atresponse = "(" # Send serial packet self._serport.send(cmd) - + # Wait for response from modem while len(self._atresponse) == 0 or self._atresponse[0] == '(': if not self._waitForResponse(timeout): @@ -180,17 +181,17 @@ def runAtCommand(self, cmd="AT\r", timeout=1000): def sendCcPacket(self, packet): """ Send wireless CcPacket through the serial gateway - + @param packet: CcPacket to be transmitted """ strBuf = packet.toString() + "\r" self._serport.send(strBuf) - + def setFreqChannel(self, value): """ Set frequency channel for the wireless gateway - + @param value: New frequency channel """ # Check format @@ -212,7 +213,7 @@ def setFreqChannel(self, value): def setSyncWord(self, value): """ Set synchronization word for the wireless gateway - + @param value: New synchronization word """ # Check format @@ -235,7 +236,7 @@ def setSyncWord(self, value): def setDevAddress(self, value): """ Set device address for the serial gateway - + @param value: New device address """ # Check format @@ -253,11 +254,11 @@ def setDevAddress(self, value): return True else: return False - + def _waitForResponse(self, millis): """ Wait a given amount of milliseconds for a response from the serial modem - + @param millis: Amount of milliseconds to wait for a response """ loops = millis / 10 @@ -269,10 +270,10 @@ def _waitForResponse(self, millis): return True - def __init__(self, portname="/dev/ttyUSB0", speed=38400, verbose=False): + def __init__(self, portname="/dev/ttyUSB0", portfix=0, speed=38400, verbose=False): """ Class constructor - + @param portname: Name/path of the serial port @param speed: Serial baudrate in bps @param verbose: Print out SWAP traffic (True or False) @@ -287,6 +288,8 @@ def __init__(self, portname="/dev/ttyUSB0", speed=38400, verbose=False): self._ccpacket_received = None ## Name(path) of the serial port self.portname = portname + ## Portfix specifier for Name(path) + self.portfix = int(portfix) ## Speed of the serial port in bps self.portspeed = speed ## Hardware version of the serial modem @@ -296,12 +299,13 @@ def __init__(self, portname="/dev/ttyUSB0", speed=38400, verbose=False): try: # Open serial port - self._serport = SerialPort(self.portname, self.portspeed, verbose) + port_specifier = resolve_portname(self.portname, self.portfix) + self._serport = SerialPort(port_specifier, self.portspeed, verbose) # Define callback function for incoming serial packets self._serport.setRxCallback(self._serialPacketReceived) # Run serial port thread self._serport.start() - + # This flags switches to True when the serial modem is ready self._wait_modem_start = False start = time.time() @@ -318,40 +322,40 @@ def __init__(self, portname="/dev/ttyUSB0", speed=38400, verbose=False): # Switch to command mode if not self.goToCommandMode(): raise SwapException("Modem is unable to enter command mode") - + # Hardware version response = self.runAtCommand("ATHV?\r") if response is None: raise SwapException("Unable to retrieve Hardware Version from serial modem") self.hwversion = long(response, 16) - + # Firmware version response = self.runAtCommand("ATFV?\r") if response is None: raise SwapException("Unable to retrieve Firmware Version from serial modem") self.fwversion = long(response, 16) - + # Frequency channel response = self.runAtCommand("ATCH?\r") if response is None: raise SwapException("Unable to retrieve Frequency Channel from serial modem") ## Frequency channel of the serial gateway self.freq_channel = int(response, 16) - + # Synchronization word response = self.runAtCommand("ATSW?\r") if response is None: raise SwapException("Unable to retrieve Synchronization Word from serial modem") ## Synchronization word of the serial gateway self.syncword = int(response, 16) - + # Device address response = self.runAtCommand("ATDA?\r") if response is None: raise SwapException("Unable to retrieve Device Address from serial modem") ## Device address of the serial gateway self.devaddress = int(response, 16) - + # Switch to data mode self.goToDataMode() except: diff --git a/pyswap/swap/modem/list_serial_port.py b/pyswap/swap/modem/list_serial_port.py new file mode 100644 index 0000000..dae9c19 --- /dev/null +++ b/pyswap/swap/modem/list_serial_port.py @@ -0,0 +1,95 @@ +''' +Created on 02.05.2019 + +@author: Sven Schlender +''' + +from serial.tools import list_ports + +from swap.SwapException import SwapException + + +def resolve_portname(port_name, port_fix, ports=None): # pylint: disable=R0912 + """Helper function for resolving given portname to COM or /dev/ttyx style + address. + """ + if not port_name: + raise SwapException(_("No portname given!")) + + if not ports: + ports = list_ports.comports() + + if not ports: + raise SwapException(_("No ports in device list.")) + + if port_fix == 0: + # Fixed by port name + matches = [x.device for x in ports] + if port_name in matches: + return str(port_name) + + elif port_fix == 1: + # Fixed by hwid + matches = [x.hwid for x in ports] + try: + found_idx = matches.index(port_name) + return str(ports[found_idx].device) + except ValueError: + pass + + elif port_fix == 2: + # Fixed by USB parameters VID, PID, serial and manufacturer + try: + vid, pid, serial_number, manu = port_name.split(',') + vid = int(vid, 16) + pid = int(pid, 16) + except ValueError: + pass + else: + for port in ports: + if (port.vid == vid and port.pid == pid and + port.serial_number == serial_number and + port.manufacturer == manu): + return str(port.device) + + elif port_fix == 3: + # Fixed by USB VID and USB PID + vid, pid = port_name.split(',') + try: + vid = int(vid, 16) + pid = int(pid, 16) + except ValueError: + pass + else: + for port in ports: + if port.vid == vid and port.pid == pid: + return str(port.device) + + msg = "Did not find matching port device name for '%s'!" % port_name + raise SwapException(msg) + +def main(): + """The main function for testing this module and to get a list of + available serial ports. + """ + from prettytable import PrettyTable + + print("Scanning ports...") + + ports = list_ports.comports() + tab = PrettyTable() + tab.field_names = ["portfix 0", "portfix 1", "portfix 2", "portfix 3"] + tab.align = 'l' + table_rows = [] + table_row_width = [1,1,1,1] + # Get column sizes. + for port in ports: + pid_vid = "%04X,%04X" % (port.vid, port.pid) + manu = "%s,%s,%s" % (pid_vid, port.serial_number, port.manufacturer) + tab.add_row([port.device, port.hwid, manu, pid_vid]) + + print(tab) + +if __name__ == '__main__': + main() + diff --git a/pyswap/swap/xmltools/XmlSerial.py b/pyswap/swap/xmltools/XmlSerial.py index c9713c4..8da11a7 100644 --- a/pyswap/swap/xmltools/XmlSerial.py +++ b/pyswap/swap/xmltools/XmlSerial.py @@ -3,22 +3,22 @@ # XmlSerial # # Copyright (c) 2011 panStamp -# +# # This file is part of the panStamp project. -# +# # panStamp is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 3 of the License, or # any later version. -# +# # panStamp is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. -# +# # You should have received a copy of the GNU Lesser General Public License # along with panStamp; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA # ######################################################################### @@ -35,7 +35,7 @@ class XmlSerial(object): Serial configuration settings """ def read(self): - """ + """ Read configuration file """ # Parse XML file @@ -48,11 +48,15 @@ def read(self): elem = root.find("port") if elem is not None: self.port = elem.text + # Get serial port fix (what port specifies) + elem = root.find("portfix") + if elem is not None: + self.portfix = elem.text # Get serial speed elem = root.find("speed") if elem is not None: self.speed = int(elem.text) - + def save(self): """ Save serial port settings in disk @@ -62,25 +66,28 @@ def save(self): f.write("\n") f.write("\n") f.write("\t" + self.port + "\n") + f.write("\t" + self.portfix + "\n") f.write("\t" + str(self.speed) + "\n") f.write("\n") f.close() except: raise SwapException("Unable to save " + self.file_name) - + def __init__(self, file_name = "serial.xml"): """ Class constructor - + @param filename: Path to the serial configuration file """ ## Name/path of the current configuration file self.file_name = file_name ## Name/path of the serial port self.port = "/dev/ttyUSB0" + ## What specifies the port? + self.portfix = 0 ## Speed of the serial port in bps - self.speed = 9600 + self.speed = 38400 # Read XML file self.read() - + diff --git a/swapdmt-cmd/swapdmt.py b/swapdmt-cmd/swapdmt.py index 3514883..f400788 100755 --- a/swapdmt-cmd/swapdmt.py +++ b/swapdmt-cmd/swapdmt.py @@ -51,10 +51,12 @@ def signal_handler(signal, frame): if __name__ == '__main__': - + # Parse arguments parser = argparse.ArgumentParser() parser.add_argument('--port', help="Serial port connected to modem") + parser.add_argument('--portfix', help="Specifies what port parameter is", + default=0) parser.add_argument('--speed', help="Serial baud rate (bps)") parser.add_argument('--channel', help="RF channel") parser.add_argument('--netid', help="Network ID") @@ -65,7 +67,7 @@ def signal_handler(signal, frame): direc = os.path.join(os.path.dirname(sys.argv[0]), "config") settings = os.path.join(direc, "settings.xml") - + # General settings general_cfg = XmlSettings(settings) # Serial settings @@ -77,6 +79,7 @@ def signal_handler(signal, frame): # Save serial parameters if opts.port is not None: serial_cfg.port = opts.port + serial_cfg.portfix = opts.portfix save_file = True if opts.speed is not None: serial_cfg.speed = SwapManager.str_to_int(opts.speed) @@ -107,14 +110,14 @@ def signal_handler(signal, frame): if secu is not None: network_cfg.security = secu save_file = True - + if save_file: network_cfg.save() # Catch possible SIGINT signals signal.signal(signal.SIGINT, signal_handler) - try: + try: # SWAP manager swap_manager = SwapManager(settings) except SwapException as ex: @@ -123,18 +126,18 @@ def signal_handler(signal, frame): while True: if swap_manager.server_started == True and swap_manager.prog_address is None: - + # Launch Macro - if opts.macro is not None: + if opts.macro is not None: swap_manager.dispatch_macro(opts.macro) opts.macro = None - + cmd = raw_input(">> ") - + command = [] for item in cmd.split(" "): command.append(item.strip()) - + swap_manager.dispatch_user_command(command) signal.pause() diff --git a/swapdmt/SerialDialog.py b/swapdmt/SerialDialog.py index 5f7050e..d12a616 100644 --- a/swapdmt/SerialDialog.py +++ b/swapdmt/SerialDialog.py @@ -44,9 +44,10 @@ def _createControls(self): """ # Add controls to the layout self.addToLayout(wx.TextCtrl(self, validator=TextValidator(self, "portname"), size=(200, 26)), "Serial port") + self.addToLayout(wx.TextCtrl(self, validator=TextValidator(self, "portfix"), size=(200, 26)), "Port fix") self.addToLayout(wx.TextCtrl(self, validator=TextValidator(self, "portspeed")), "Serial baud rate (bps)") self.addOkCancelButtons() - + def _save(self): """ @@ -70,6 +71,8 @@ def __init__(self, parent=None): self.config = XmlSerial(XmlSettings.serial_file) # Name/path of the serial port self.portname = self.config.port + # Says what the port name specifies + self.portfix = self.config.portfix # Serial port baud rate (in bps) self.portspeed = self.config.speed # Create widgets diff --git a/swapdmt/config/serial.xml b/swapdmt/config/serial.xml index 7cee009..e5d9097 100644 --- a/swapdmt/config/serial.xml +++ b/swapdmt/config/serial.xml @@ -1,5 +1,6 @@ /dev/ttyUSB0 + 0 38400