def __init__(self, manager, resID, **kwargs): assert (isinstance(manager, labtronyx.InstrumentManager)) super(r_Serial, self).__init__(manager, resID, **kwargs) # Ensure resource doesn't already exist if len(manager.plugin_manager.searchPluginInstances(pluginType='resource', interfaceName='Serial', resID=resID)) > 0: raise labtronyx.InterfaceError("Resource already exists") try: self.instrument = serial.Serial(port=resID, timeout=0) self.logger.debug("Created Serial resource: %s", resID) # Serial port is immediately opened on object creation self.close() except (serial.SerialException, OSError) as e: if os.name == 'nt': # Windows implementation of PySerial does not set errno correctly import ctypes e.errno = ctypes.WinError().errno if e.errno in [errno.ENOENT, errno.EACCES, errno.EBUSY]: raise labtronyx.ResourceUnavailable('Serial resource error: %s' % resID) else: raise labtronyx.InterfaceError('Serial interface error [%i]: %s' % (e.errno, e.message))
def __init__(self, manager, resID, **kwargs): assert (isinstance(manager, labtronyx.InstrumentManager)) super(r_VISA, self).__init__(manager, resID, **kwargs) # Ensure dependency was resolved correctly if not isinstance(self.interface, i_VISA): raise labtronyx.InterfaceError("VISA Interface is not enabled") # Ensure resource doesn't already exist if len( manager.plugin_manager.searchPluginInstances( pluginType='resource', interfaceName='VISA', resID=resID)) > 0: raise labtronyx.InterfaceError("Resource already exists") try: self.instrument = self.interface.resource_manager.open_resource( resID) self.logger.debug("Created VISA resource: %s", resID) # Instance variables self._identity = [] self._conf = { # Default configuration 'read_termination': '\r', 'write_termination': '\r\n', 'timeout': 2000 } self._resourceType = self.RES_TYPES.get( self.instrument.interface_type, 'VISA') # Instrument is created in the open state, but we do not want to lock the VISA instrument self.close() # Set a flag to initialize the resource when it is used self.ready = False # except AttributeError: # raise labtronyx.ResourceUnavailable('Invalid VISA Resource Identifier: %s' % resID) except visa.VisaIOError as e: if e.abbreviation in [ "VI_ERROR_RSRC_BUSY", "VI_ERROR_RSRC_NFOUND", "VI_ERROR_TMO", "VI_ERROR_INV_RSRC_NAME" ]: # Returned by TekVISA raise labtronyx.ResourceUnavailable('VISA Resource Error: %s' % e.abbreviation) else: raise labtronyx.InterfaceError('VISA Interface Error: %s' % e.abbreviation)
def read_raw(self, size=None): """ Read Binary-encoded data from the instrument. No termination characters are stripped. :param size: Number of bytes to read :type size: int :returns: bytes :raises: ResourceNotOpen """ try: ret = bytes() if size is None: size = self.instrument.inWaiting() ret += self.instrument.read(size) if len(ret) != len(size): raise labtronyx.InterfaceTimeout("Timeout before requested bytes could be read") return ret except SerialException as e: if e == serial.portNotOpenError: raise labtronyx.ResourceNotOpen() else: raise labtronyx.InterfaceError(e.strerror)
def read(self, termination=None): """ Read string data from the instrument. Reading stops when the device stops sending, or the termination characters sequence was detected. All line-ending characters are stripped from the end of the string. :raises: ResourceNotOpen """ try: ret = '' if termination is None: bytes_waiting = self.instrument.inWaiting() ret += self.instrument.read(bytes_waiting) else: ret += self.instrument.read(1) while ret[-1] != self.termination[-1] or self.instrument.inWaiting() == 0: ret += self.instrument.read(1) ret = ret[:-len(self.termination)] return ret except SerialException as e: if e == serial.portNotOpenError: raise labtronyx.ResourceNotOpen() else: raise labtronyx.InterfaceError(e.strerror)
def write(self, data): """ Send ASCII-encoded data to the instrument. Includes termination character. Raises exception if the resource is not open :param data: Data to send :type data: str :raises: ResourceNotOpen :raises: InterfaceTimeout :raises: InterfaceError """ try: self.logger.debug("Serial Write: %s", data) self.instrument.write(data + self.termination) except SerialException as e: if e == serial.portNotOpenError: raise labtronyx.ResourceNotOpen() elif e == serial.writeTimeoutError: raise labtronyx.InterfaceTimeout() else: raise labtronyx.InterfaceError(e.strerror)
def query(self, data, delay=None): """ Retrieve ASCII-encoded data from the device given a prompt. A combination of write(data) and read() :param data: Data to send :type data: str :param delay: delay (in seconds) between write and read operations. :type delay: float :returns: str :raises: labtronyx.ResourceNotOpen :raises: labtronyx.InterfaceTimeout :raises: labtronyx.InterfaceError """ try: ret_data = self.instrument.query(data) self.logger.debug("VISA Query: %s returned: %s", data, ret_data) return ret_data except visa.InvalidSession: raise labtronyx.ResourceNotOpen except visa.VisaIOError as e: if e.abbreviation in ["VI_ERROR_TMO"]: raise labtronyx.InterfaceTimeout(e.description) else: raise labtronyx.InterfaceError(e.description)
def enumerate(self): """ Identify all devices known to the VISA driver and create resource objects for valid resources """ if self.__resource_manager is None: raise labtronyx.InterfaceError("Interface not open") self.logger.debug("Enumerating VISA interface") try: new_res_list = [ res for res in self.__resource_manager.list_resources() if res not in self.resources_by_id ] # Check for new resources for resID in new_res_list: try: self.openResource(resID) except labtronyx.ResourceUnavailable: pass except visa.VisaIOError as e: # Exception thrown when there are no resources self.logger.exception('VISA Exception during enumeration')
def read(self, termination=None, encoding=None): """ Read ASCII-formatted data from the instrument. Reading stops when the device stops sending, or the termination characters sequence was detected. All line-ending characters are stripped from the end of the string. :param termination: Line termination :type termination: str :param encoding: Encoding :type encoding: str :return: str :raises: labtronyx.ResourceNotOpen :raises: labtronyx.InterfaceTimeout :raises: labtronyx.InterfaceError """ try: data = self.instrument.read(termination, encoding) self.logger.debug("VISA Read: %s", data) return data except visa.InvalidSession: raise labtronyx.ResourceNotOpen() except visa.VisaIOError as e: if e.abbreviation in ["VI_ERROR_TMO"]: raise labtronyx.InterfaceTimeout(e.description) else: raise labtronyx.InterfaceError(e.description)
def flush(self): """ Flush the output buffer """ try: return self.instrument.flush() except serial.SerialException as e: raise labtronyx.InterfaceError(e.strerror)
def inWaiting(self): """ Return the number of bytes in the receive buffer :returns: int :raises: InterfaceError """ try: return self.instrument.inWaiting() except serial.SerialException as e: raise labtronyx.InterfaceError(e.strerror)
def getResource(self, resID): """ Attempt to open a Serial instrument. If successful, a serial resource is added to the list of known resources and the object is returned. :return: object :raises: ResourceUnavailable :raises: InterfaceError """ if resID in self.resources_by_id: raise labtronyx.InterfaceError("Resource instance already exists") try: instrument = serial.Serial(port=resID, timeout=0) res_obj = self.manager.plugin_manager.createPluginInstance(r_Serial.fqn, manager=self.manager, interface=self, resID=resID, instrument=instrument, logger=self.logger ) # Signal new resource event self.manager._publishEvent(labtronyx.EventCodes.resource.created, res_obj.uuid) return res_obj except (serial.SerialException, OSError) as e: if os.name == 'nt': # Windows implementation of PySerial does not set errno correctly import ctypes e.errno = ctypes.WinError().errno if e.errno in [errno.ENOENT, errno.EACCES, errno.EBUSY]: raise labtronyx.ResourceUnavailable('Serial resource error: %s' % resID) else: raise labtronyx.InterfaceError('Serial interface error [%i]: %s' % (e.errno, e.message))
def read_raw(self, size=None): """ Read Binary-encoded data directly from the instrument. :param size: Number of bytes to read :type size: int :raises: labtronyx.ResourceNotOpen :raises: labtronyx.InterfaceTimeout :raises: labtronyx.InterfaceError """ ret = bytes() try: if type(self.instrument ) == pyvisa.resources.serial.SerialInstrument: # There is a bug in PyVISA that forces a low-level call (hgrecco/pyvisa #93) with self.instrument.ignore_warning( pyvisa.constants.VI_SUCCESS_MAX_CNT): if size is None: num_bytes = self.instrument.bytes_in_buffer chunk, status = self.instrument.visalib.read( self.instrument.session, num_bytes) ret += chunk else: while len(ret) < size: chunk, status = self.instrument.visalib.read( self.instrument.session, size - len(ret)) ret += chunk return ret else: return self.instrument.read_raw() except visa.InvalidSession: raise labtronyx.ResourceNotOpen except visa.VisaIOError as e: if e.abbreviation in ["VI_ERROR_TMO"]: raise labtronyx.InterfaceTimeout(e.description) else: raise labtronyx.InterfaceError(e.description)
def write_raw(self, data): """ Send Binary-encoded data to the instrument without modification :param data: Data to send :type data: str :raises: labtronyx.ResourceNotOpen :raises: labtronyx.InterfaceError """ try: self.instrument.write_raw(data) self.logger.debug("VISA Write: %s", data) except visa.InvalidSession: raise labtronyx.ResourceNotOpen() except visa.VisaIOError as e: raise labtronyx.InterfaceError(e.description)
def write(self, data): """ Send ASCII-encoded data to the instrument. Termination character is appended automatically, according to `write_termination` property. :param data: Data to send :type data: str :raises: labtronyx.ResourceNotOpen :raises: labtronyx.InterfaceError """ try: self.instrument.write(data) self.logger.debug("VISA Write: %s", data) except visa.InvalidSession: raise labtronyx.ResourceNotOpen() except visa.VisaIOError as e: raise labtronyx.InterfaceError(e.description)
def write_raw(self, data): """ Send Binary-encoded data to the instrument. Termination character is not included :param data: Data to send :type data: str :raises: ResourceNotOpen :raises: InterfaceTimeout :raises: InterfaceError """ try: self.instrument.write(data) except SerialException as e: if e == serial.portNotOpenError: raise labtronyx.ResourceNotOpen() elif e == serial.writeTimeoutError: raise labtronyx.InterfaceTimeout() else: raise labtronyx.InterfaceError(e.strerror)
def prune(self): """ Close any resources that are no longer known to the VISA interface """ if self.__resource_manager is None: raise labtronyx.InterfaceError("Interface not open") try: # Get a fresh list of resources res_list = self.__resource_manager.list_resources() except visa.VisaIOError: # Exception thrown when there are no resources res_list = [] for res_uuid, res_obj in self.resources.items(): resID = res_obj.resID if resID not in res_list: res_obj.close() self.manager.plugin_manager.destroyPluginInstance(res_uuid) self.manager._publishEvent( labtronyx.EventCodes.resource.destroyed, res_obj.uuid)