kopia lustrzana https://github.com/markqvist/reticulum
				
				
				
			Added auto reconnection for disconnected serial-based devices
							rodzic
							
								
									ba39a69175
								
							
						
					
					
						commit
						8be1acee0a
					
				|  | @ -58,6 +58,7 @@ class AX25KISSInterface(Interface): | |||
|         self.rxb = 0 | ||||
|         self.txb = 0 | ||||
|          | ||||
|         self.pyserial = serial | ||||
|         self.serial   = None | ||||
|         self.owner    = owner | ||||
|         self.name     = name | ||||
|  | @ -97,44 +98,48 @@ class AX25KISSInterface(Interface): | |||
|             self.parity = serial.PARITY_ODD | ||||
| 
 | ||||
|         try: | ||||
|             RNS.log("Opening serial port "+self.port+"...") | ||||
|             self.serial = serial.Serial( | ||||
|                 port = self.port, | ||||
|                 baudrate = self.speed, | ||||
|                 bytesize = self.databits, | ||||
|                 parity = self.parity, | ||||
|                 stopbits = self.stopbits, | ||||
|                 xonxoff = False, | ||||
|                 rtscts = False, | ||||
|                 timeout = 0, | ||||
|                 inter_byte_timeout = None, | ||||
|                 write_timeout = None, | ||||
|                 dsrdtr = False, | ||||
|             ) | ||||
|             self.open_port() | ||||
|         except Exception as e: | ||||
|             RNS.log("Could not open serial port for interface "+str(self), RNS.LOG_ERROR) | ||||
|             raise e | ||||
| 
 | ||||
|         if self.serial.is_open: | ||||
|             # Allow time for interface to initialise before config | ||||
|             sleep(2.0) | ||||
|             thread = threading.Thread(target=self.readLoop) | ||||
|             thread.setDaemon(True) | ||||
|             thread.start() | ||||
|             self.online = True | ||||
|             RNS.log("Serial port "+self.port+" is now open") | ||||
|             RNS.log("Configuring AX.25 KISS interface parameters...") | ||||
|             self.setPreamble(self.preamble) | ||||
|             self.setTxTail(self.txtail) | ||||
|             self.setPersistence(self.persistence) | ||||
|             self.setSlotTime(self.slottime) | ||||
|             self.setFlowControl(self.flow_control) | ||||
|             self.interface_ready = True | ||||
|             RNS.log("AX.25 KISS interface configured") | ||||
|             sleep(2) | ||||
|             self.configure_device() | ||||
|         else: | ||||
|             raise IOError("Could not open serial port") | ||||
| 
 | ||||
|     def open_port(self): | ||||
|         RNS.log("Opening serial port "+self.port+"...", RNS.LOG_VERBOSE) | ||||
|         self.serial = self.pyserial.Serial( | ||||
|             port = self.port, | ||||
|             baudrate = self.speed, | ||||
|             bytesize = self.databits, | ||||
|             parity = self.parity, | ||||
|             stopbits = self.stopbits, | ||||
|             xonxoff = False, | ||||
|             rtscts = False, | ||||
|             timeout = 0, | ||||
|             inter_byte_timeout = None, | ||||
|             write_timeout = None, | ||||
|             dsrdtr = False, | ||||
|         ) | ||||
| 
 | ||||
|     def configure_device(self): | ||||
|         # Allow time for interface to initialise before config | ||||
|         sleep(2.0) | ||||
|         thread = threading.Thread(target=self.readLoop) | ||||
|         thread.setDaemon(True) | ||||
|         thread.start() | ||||
|         self.online = True | ||||
|         RNS.log("Serial port "+self.port+" is now open") | ||||
|         RNS.log("Configuring AX.25 KISS interface parameters...") | ||||
|         self.setPreamble(self.preamble) | ||||
|         self.setTxTail(self.txtail) | ||||
|         self.setPersistence(self.persistence) | ||||
|         self.setSlotTime(self.slottime) | ||||
|         self.setFlowControl(self.flow_control) | ||||
|         self.interface_ready = True | ||||
|         RNS.log("AX.25 KISS interface configured") | ||||
| 
 | ||||
|     def setPreamble(self, preamble): | ||||
|         preamble_ms = preamble | ||||
|  | @ -315,10 +320,29 @@ class AX25KISSInterface(Interface): | |||
|         except Exception as e: | ||||
|             self.online = False | ||||
|             RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
|             RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is being torn down. Restart Reticulum to attempt to open this interface again.", RNS.LOG_ERROR) | ||||
| 
 | ||||
|             RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR) | ||||
|              | ||||
|             if RNS.Reticulum.panic_on_interface_error: | ||||
|                 RNS.panic() | ||||
| 
 | ||||
|             RNS.log("Reticulum will attempt to reconnect the interface periodically.", RNS.LOG_ERROR) | ||||
| 
 | ||||
|         self.online = False | ||||
|         self.serial.close() | ||||
|         self.reconnect_port() | ||||
| 
 | ||||
|     def reconnect_port(self): | ||||
|         while not self.online: | ||||
|             try: | ||||
|                 time.sleep(5) | ||||
|                 RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE) | ||||
|                 self.open_port() | ||||
|                 if self.serial.is_open: | ||||
|                     self.configure_device() | ||||
|             except Exception as e: | ||||
|                 RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
| 
 | ||||
|         RNS.log("Reconnected serial port for "+str(self)) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "AX25KISSInterface["+self.name+"]" | ||||
|  | @ -98,7 +98,7 @@ class KISSInterface(Interface): | |||
| 
 | ||||
| 
 | ||||
|     def open_port(self): | ||||
|         RNS.log("Opening serial port "+self.port+"...") | ||||
|         RNS.log("Opening serial port "+self.port+"...", RNS.LOG_VERBOSE) | ||||
|         self.serial = self.pyserial.Serial( | ||||
|             port = self.port, | ||||
|             baudrate = self.speed, | ||||
|  | @ -299,11 +299,13 @@ class KISSInterface(Interface): | |||
|         except Exception as e: | ||||
|             self.online = False | ||||
|             RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
|             RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is being torn down. Restart Reticulum to attempt to open this interface again.", RNS.LOG_ERROR) | ||||
| 
 | ||||
|             RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR) | ||||
|              | ||||
|             if RNS.Reticulum.panic_on_interface_error: | ||||
|                 RNS.panic() | ||||
| 
 | ||||
|             RNS.log("Reticulum will attempt to reconnect the interface periodically.", RNS.LOG_ERROR) | ||||
| 
 | ||||
|         self.online = False | ||||
|         self.serial.close() | ||||
|         self.reconnect_port() | ||||
|  | @ -312,12 +314,14 @@ class KISSInterface(Interface): | |||
|         while not self.online: | ||||
|             try: | ||||
|                 time.sleep(5) | ||||
|                 RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...") | ||||
|                 RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE) | ||||
|                 self.open_port() | ||||
|                 if self.serial.is_open: | ||||
|                     self.configure_device() | ||||
|             except Exception as e: | ||||
|                 RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
| 
 | ||||
|         RNS.log("Reconnected serial port for "+str(self)) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "KISSInterface["+self.name+"]" | ||||
|  | @ -82,6 +82,7 @@ class RNodeInterface(Interface): | |||
|         self.rxb = 0 | ||||
|         self.txb = 0 | ||||
|          | ||||
|         self.pyserial    = serial | ||||
|         self.serial      = None | ||||
|         self.owner       = owner | ||||
|         self.name        = name | ||||
|  | @ -157,46 +158,53 @@ class RNodeInterface(Interface): | |||
|             raise ValueError("The configuration for "+str(self)+" contains errors, interface is offline") | ||||
| 
 | ||||
|         try: | ||||
|             RNS.log("Opening serial port "+self.port+"...") | ||||
|             self.serial = serial.Serial( | ||||
|                 port = self.port, | ||||
|                 baudrate = self.speed, | ||||
|                 bytesize = self.databits, | ||||
|                 parity = self.parity, | ||||
|                 stopbits = self.stopbits, | ||||
|                 xonxoff = False, | ||||
|                 rtscts = False, | ||||
|                 timeout = 0, | ||||
|                 inter_byte_timeout = None, | ||||
|                 write_timeout = None, | ||||
|                 dsrdtr = False, | ||||
|             ) | ||||
|             self.open_port() | ||||
|         except Exception as e: | ||||
|             RNS.log("Could not open serial port for interface "+str(self), RNS.LOG_ERROR) | ||||
|             raise e | ||||
| 
 | ||||
|         if self.serial.is_open: | ||||
|             sleep(2.0) | ||||
|             thread = threading.Thread(target=self.readLoop) | ||||
|             thread.setDaemon(True) | ||||
|             thread.start() | ||||
|             self.online = True | ||||
|             RNS.log("Serial port "+self.port+" is now open") | ||||
|             RNS.log("Configuring RNode interface...", RNS.LOG_VERBOSE) | ||||
|             self.initRadio() | ||||
|             if (self.validateRadioState()): | ||||
|                 self.interface_ready = True | ||||
|                 RNS.log(str(self)+" is configured and powered up") | ||||
|                 sleep(1.0) | ||||
|             else: | ||||
|                 RNS.log("After configuring "+str(self)+", the reported radio parameters did not match your configuration.", RNS.LOG_ERROR) | ||||
|                 RNS.log("Make sure that your hardware actually supports the parameters specified in the configuration", RNS.LOG_ERROR) | ||||
|                 RNS.log("Aborting RNode startup", RNS.LOG_ERROR) | ||||
|                 self.serial.close() | ||||
|                 raise IOError("RNode interface did not pass validation") | ||||
|             self.configure_device() | ||||
|         else: | ||||
|             raise IOError("Could not open serial port") | ||||
| 
 | ||||
|     def open_port(self): | ||||
|         RNS.log("Opening serial port "+self.port+"...") | ||||
|         self.serial = self.pyserial.Serial( | ||||
|             port = self.port, | ||||
|             baudrate = self.speed, | ||||
|             bytesize = self.databits, | ||||
|             parity = self.parity, | ||||
|             stopbits = self.stopbits, | ||||
|             xonxoff = False, | ||||
|             rtscts = False, | ||||
|             timeout = 0, | ||||
|             inter_byte_timeout = None, | ||||
|             write_timeout = None, | ||||
|             dsrdtr = False, | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
|     def configure_device(self): | ||||
|         sleep(2.0) | ||||
|         thread = threading.Thread(target=self.readLoop) | ||||
|         thread.setDaemon(True) | ||||
|         thread.start() | ||||
|         self.online = True | ||||
|         RNS.log("Serial port "+self.port+" is now open") | ||||
|         RNS.log("Configuring RNode interface...", RNS.LOG_VERBOSE) | ||||
|         self.initRadio() | ||||
|         if (self.validateRadioState()): | ||||
|             self.interface_ready = True | ||||
|             RNS.log(str(self)+" is configured and powered up") | ||||
|             sleep(1.0) | ||||
|         else: | ||||
|             RNS.log("After configuring "+str(self)+", the reported radio parameters did not match your configuration.", RNS.LOG_ERROR) | ||||
|             RNS.log("Make sure that your hardware actually supports the parameters specified in the configuration", RNS.LOG_ERROR) | ||||
|             RNS.log("Aborting RNode startup", RNS.LOG_ERROR) | ||||
|             self.serial.close() | ||||
|             raise IOError("RNode interface did not pass validation") | ||||
|              | ||||
| 
 | ||||
|     def initRadio(self): | ||||
|         self.setFrequency() | ||||
|  | @ -478,11 +486,30 @@ class RNodeInterface(Interface): | |||
|         except Exception as e: | ||||
|             self.online = False | ||||
|             RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
|             RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is being torn down. Restart Reticulum to attempt to open this interface again.", RNS.LOG_ERROR) | ||||
| 
 | ||||
|             RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR) | ||||
|              | ||||
|             if RNS.Reticulum.panic_on_interface_error: | ||||
|                 RNS.panic() | ||||
| 
 | ||||
|             RNS.log("Reticulum will attempt to reconnect the interface periodically.", RNS.LOG_ERROR) | ||||
| 
 | ||||
|         self.online = False | ||||
|         self.serial.close() | ||||
|         self.reconnect_port() | ||||
| 
 | ||||
|     def reconnect_port(self): | ||||
|         while not self.online: | ||||
|             try: | ||||
|                 time.sleep(5) | ||||
|                 RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE) | ||||
|                 self.open_port() | ||||
|                 if self.serial.is_open: | ||||
|                     self.configure_device() | ||||
|             except Exception as e: | ||||
|                 RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
| 
 | ||||
|         RNS.log("Reconnected serial port for "+str(self)) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "RNodeInterface["+self.name+"]" | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ class SerialInterface(Interface): | |||
|         self.rxb = 0 | ||||
|         self.txb = 0 | ||||
|          | ||||
|         self.pyserial = serial | ||||
|         self.serial   = None | ||||
|         self.owner    = owner | ||||
|         self.name     = name | ||||
|  | @ -59,35 +60,43 @@ class SerialInterface(Interface): | |||
|             self.parity = serial.PARITY_ODD | ||||
| 
 | ||||
|         try: | ||||
|             RNS.log("Opening serial port "+self.port+"...") | ||||
|             self.serial = serial.Serial( | ||||
|                 port = self.port, | ||||
|                 baudrate = self.speed, | ||||
|                 bytesize = self.databits, | ||||
|                 parity = self.parity, | ||||
|                 stopbits = self.stopbits, | ||||
|                 xonxoff = False, | ||||
|                 rtscts = False, | ||||
|                 timeout = 0, | ||||
|                 inter_byte_timeout = None, | ||||
|                 write_timeout = None, | ||||
|                 dsrdtr = False, | ||||
|             ) | ||||
|             self.open_port() | ||||
|         except Exception as e: | ||||
|             RNS.log("Could not open serial port for interface "+str(self), RNS.LOG_ERROR) | ||||
|             raise e | ||||
| 
 | ||||
|         if self.serial.is_open: | ||||
|             sleep(0.5) | ||||
|             thread = threading.Thread(target=self.readLoop) | ||||
|             thread.setDaemon(True) | ||||
|             thread.start() | ||||
|             self.online = True | ||||
|             RNS.log("Serial port "+self.port+" is now open") | ||||
|             self.configure_device() | ||||
|         else: | ||||
|             raise IOError("Could not open serial port") | ||||
| 
 | ||||
| 
 | ||||
|     def open_port(self): | ||||
|         RNS.log("Opening serial port "+self.port+"...", RNS.LOG_VERBOSE) | ||||
|         self.serial = self.pyserial.Serial( | ||||
|             port = self.port, | ||||
|             baudrate = self.speed, | ||||
|             bytesize = self.databits, | ||||
|             parity = self.parity, | ||||
|             stopbits = self.stopbits, | ||||
|             xonxoff = False, | ||||
|             rtscts = False, | ||||
|             timeout = 0, | ||||
|             inter_byte_timeout = None, | ||||
|             write_timeout = None, | ||||
|             dsrdtr = False, | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
|     def configure_device(self): | ||||
|         sleep(0.5) | ||||
|         thread = threading.Thread(target=self.readLoop) | ||||
|         thread.setDaemon(True) | ||||
|         thread.start() | ||||
|         self.online = True | ||||
|         RNS.log("Serial port "+self.port+" is now open") | ||||
| 
 | ||||
| 
 | ||||
|     def processIncoming(self, data): | ||||
|         self.rxb += len(data)             | ||||
|         self.owner.inbound(data, self) | ||||
|  | @ -139,13 +148,33 @@ class SerialInterface(Interface): | |||
|                         in_frame = False | ||||
|                         escape = False | ||||
|                     sleep(0.08) | ||||
|                      | ||||
|         except Exception as e: | ||||
|             self.online = False | ||||
|             RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
|             RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is being torn down. Restart Reticulum to attempt to open this interface again.", RNS.LOG_ERROR) | ||||
| 
 | ||||
|             RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR) | ||||
|              | ||||
|             if RNS.Reticulum.panic_on_interface_error: | ||||
|                 RNS.panic() | ||||
| 
 | ||||
|             RNS.log("Reticulum will attempt to reconnect the interface periodically.", RNS.LOG_ERROR) | ||||
| 
 | ||||
|         self.online = False | ||||
|         self.serial.close() | ||||
|         self.reconnect_port() | ||||
| 
 | ||||
|     def reconnect_port(self): | ||||
|         while not self.online: | ||||
|             try: | ||||
|                 time.sleep(5) | ||||
|                 RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE) | ||||
|                 self.open_port() | ||||
|                 if self.serial.is_open: | ||||
|                     self.configure_device() | ||||
|             except Exception as e: | ||||
|                 RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
| 
 | ||||
|         RNS.log("Reconnected serial port for "+str(self)) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "SerialInterface["+self.name+"]" | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Mark Qvist
						Mark Qvist