Fixed ESI never timing out

This commit is contained in:
jtc42 2019-11-19 16:49:11 +00:00
parent edecc01ca1
commit a3ddaa69d3
2 changed files with 26 additions and 17 deletions

View file

@ -65,6 +65,7 @@ class ExtensibleSerialInstrument(object):
Set up the serial port and so on. Set up the serial port and so on.
""" """
logging.info("Updating ESI port settings") logging.info("Updating ESI port settings")
logging.debug(kwargs)
self.port_settings.update(kwargs) self.port_settings.update(kwargs)
logging.info("Opening ESI connection to port {}".format(port)) logging.info("Opening ESI connection to port {}".format(port))
self.open(port, False) # Eventually this shouldn't rely on init... self.open(port, False) # Eventually this shouldn't rely on init...
@ -86,7 +87,9 @@ class ExtensibleSerialInstrument(object):
assert ( assert (
port is not None port is not None
), "We don't have a serial port to open, meaning you didn't specify a valid port. Are you sure the instrument is connected?" ), "We don't have a serial port to open, meaning you didn't specify a valid port. Are you sure the instrument is connected?"
logging.info("Creating serial.Serial instance...")
self._ser = serial.Serial(port, **self.port_settings) self._ser = serial.Serial(port, **self.port_settings)
logging.info(f"Created {self._ser}")
# the block above wraps the serial IO layer with a text IO layer # the block above wraps the serial IO layer with a text IO layer
# this allows us to read/write in neat lines. NB the buffer size must # this allows us to read/write in neat lines. NB the buffer size must
# be set to 1 byte for maximum responsiveness. # be set to 1 byte for maximum responsiveness.
@ -130,11 +133,6 @@ class ExtensibleSerialInstrument(object):
assert ( assert (
self._ser.isOpen() self._ser.isOpen()
), "Attempted to write to the serial port before it was opened. Perhaps you need to call the 'open' method first?" ), "Attempted to write to the serial port before it was opened. Perhaps you need to call the 'open' method first?"
# TODO: Check if this code is needed and if not kill it
# try:
# if self._ser.outWaiting()>0: self._ser.flushOutput() #ensure there's nothing waiting
# except AttributeError:
# if self._ser.out_waiting>0: self._ser.flushOutput() #ensure there's nothing waiting
data = query_string + self.termination_character data = query_string + self.termination_character
data = data.encode() data = data.encode()
self._ser.write(data) self._ser.write(data)
@ -145,7 +143,7 @@ class ExtensibleSerialInstrument(object):
if self._ser.inWaiting() > 0: if self._ser.inWaiting() > 0:
self._ser.flushInput() self._ser.flushInput()
def readline(self, timeout=None): def readline(self):
"""Read one line from the serial port.""" """Read one line from the serial port."""
with self.communications_lock: with self.communications_lock:
return ( return (
@ -165,7 +163,7 @@ class ExtensibleSerialInstrument(object):
self._communications_lock = threading.RLock() self._communications_lock = threading.RLock()
return self._communications_lock return self._communications_lock
def read_multiline(self, termination_line=None, timeout=None): def read_multiline(self, termination_line=None):
"""Read one line from the underlying bus. Must be overriden. """Read one line from the underlying bus. Must be overriden.
This should not need to be reimplemented unless there's a more efficient This should not need to be reimplemented unless there's a more efficient
@ -181,11 +179,11 @@ class ExtensibleSerialInstrument(object):
while ( while (
termination_line not in last_line and len(last_line) > 0 termination_line not in last_line and len(last_line) > 0
): # read until we get the termination line. ): # read until we get the termination line.
last_line = self.readline(timeout) last_line = self.readline()
response += last_line response += last_line
return response return response
def query(self, queryString, multiline=False, termination_line=None, timeout=None): def query(self, queryString, multiline=False, termination_line=None):
""" """
Write a string to the stage controller and return its response. Write a string to the stage controller and return its response.
@ -193,12 +191,17 @@ class ExtensibleSerialInstrument(object):
will keep reading until a termination phrase is reached. will keep reading until a termination phrase is reached.
""" """
with self.communications_lock: with self.communications_lock:
logging.debug("Flushing input buffer...")
self.flush_input_buffer() self.flush_input_buffer()
logging.debug(f"Writing query: {queryString}")
self.write(queryString) self.write(queryString)
logging.debug("Query written")
if self.ignore_echo == True: # Needs Implementing for a multiline read! if self.ignore_echo == True: # Needs Implementing for a multiline read!
first_line = self.readline(timeout).strip() logging.debug("Reading first line...")
first_line = self.readline().strip()
logging.debug(f"Read finished. Got {first_line}")
if first_line == queryString: if first_line == queryString:
return self.readline(timeout).strip() return self.readline().strip()
else: else:
logging.info("This command did not echo!!!") logging.info("This command did not echo!!!")
return first_line return first_line
@ -206,11 +209,13 @@ class ExtensibleSerialInstrument(object):
if termination_line is not None: if termination_line is not None:
multiline = True multiline = True
if multiline: if multiline:
logging.debug("Reading multiline...")
return self.read_multiline(termination_line) return self.read_multiline(termination_line)
else: else:
return self.readline( logging.debug("Reading response...")
timeout line = self.readline().strip() # question: should we strip the final newline?
).strip() # question: should we strip the final newline? logging.debug(f"Read finished. Got {line}")
return line
def parsed_query( def parsed_query(
self, self,

View file

@ -90,7 +90,7 @@ class Sangaboard(ExtensibleSerialInstrument):
# Once initialised, `firmware` is a string that identifies the firmware version # Once initialised, `firmware` is a string that identifies the firmware version
firmware = None firmware = None
def __init__(self, port=None, **kwargs): def __init__(self, port=None, timeout: int = 2, **kwargs):
"""Create a sangaboard object. """Create a sangaboard object.
Arguments are passed to the constructor of Arguments are passed to the constructor of
@ -101,13 +101,16 @@ class Sangaboard(ExtensibleSerialInstrument):
""" """
# Initialise basic serial instrument with specified # Initialise basic serial instrument with specified
ExtensibleSerialInstrument.__init__(self, port, **kwargs) logging.info(f"Initialising ExtensibleSerialInstrument on port {port}")
ExtensibleSerialInstrument.__init__(self, port, timeout=timeout, **kwargs)
try: try:
# Make absolutely sure that whatever port we're on is valid # Make absolutely sure that whatever port we're on is valid
logging.info("Checking valid firmware...")
self.check_valid_firmware() self.check_valid_firmware()
# Bit messy: Defining all valid modules as not available, then overwriting with available information if available. # Bit messy: Defining all valid modules as not available, then overwriting with available information if available.
logging.info("Loading modules...")
self.light_sensor = LightSensor(False) self.light_sensor = LightSensor(False)
for module in self.list_modules(): for module in self.list_modules():
@ -145,10 +148,11 @@ class Sangaboard(ExtensibleSerialInstrument):
""" """
Overrides superclass, used in self.open(), and port scanning Overrides superclass, used in self.open(), and port scanning
""" """
logging.info("Testing communication to SangaBoard")
return self.check_valid_firmware() return self.check_valid_firmware()
def check_valid_firmware(self): def check_valid_firmware(self):
logging.debug("Running firmware checks") logging.info("Running firmware checks...")
# Request firmware version from the board # Request firmware version from the board
self.firmware = self.query("version", timeout=2).rstrip() self.firmware = self.query("version", timeout=2).rstrip()