def OpenRS232DaisyChain(self, comport, baudrate): """Open an RS-232 daisy chain connection. To get access to a daisy chain device you have to call ConnectDaisyChainDevice(). @param comport: Port to use as integer (1 means "COM1"). @param baudrate: Baudrate to use as integer. @return: Found devices as list of strings. """ debug('GCSDll.OpenRS232DaisyChain(comport=%s, baudrate=%s)', comport, baudrate) ccomport = ctypes.c_int(comport) cbaudrate = ctypes.c_int(baudrate) numdev = ctypes.byref(ctypes.c_int()) bufsize = 10000 bufstr = ctypes.create_string_buffer('\000'.encode(), bufsize + 2) self.__dcid = getattr(self.__handle, self.__prefix + 'OpenRS232DaisyChain')(ccomport, cbaudrate, numdev, bufstr, bufsize) if self.__dcid < 0: raise GCSError(self.__error) devlist = bufstr.value.decode().split('\n')[:-1] devlist = [item.strip() for item in devlist] debug('GCSDll.OpenRS232DaisyChain: %r', devlist) self.__ifdescription = 'RS-232 daisy chain at COM%s, %s Baud' % ( comport, baudrate) return devlist
def answersize(self): """Get the size of an answer of a GCS command as integer.""" size = ctypes.c_int() if not getattr(self.__handle, self.__prefix + 'GcsGetAnswerSize')( self.__id, ctypes.byref(size)): raise GCSError(self.__error) return size.value
def OpenTCPIPDaisyChain(self, ipaddress, ipport=50000): """Open a TCPIP daisy chain connection. To get access to a daisy chain device you have to call ConnectDaisyChainDevice(). @param ipaddress: IP address to connect to as string. @param ipport: Port to use as integer, defaults to 50000. @return: Found devices as list of strings. """ debug('GCSDll.OpenTCPIPDaisyChain(ipaddress=%r, ipport=%s)', ipaddress, ipport) cipaddress = ctypes.c_char_p(ipaddress.encode()) cipport = ctypes.c_int(ipport) numdev = ctypes.byref(ctypes.c_int()) bufsize = 10000 bufstr = ctypes.create_string_buffer('\000'.encode(), bufsize + 2) self.__dcid = getattr(self.__handle, self.__prefix + 'OpenTCPIPDaisyChain')(cipaddress, cipport, numdev, bufstr, bufsize) if self.__dcid < 0: raise GCSError(self.__error) devlist = bufstr.value.decode().split('\n')[:-1] devlist = [item.strip() for item in devlist] debug('GCSDll.OpenTCPIPDaisyChain: %r', devlist) self.__ifdescription = 'TCPIP daisy chain at %s:%s' % (ipaddress, ipport) return devlist
def GetAsyncBuffer(self, firstline=1, lastline=0, numtables=1): """Query all available data points, return list with 'numtables' columns. DEPRECATED: Use GCSMessages.bufdata instead. Buffer is used by qDRR(), qDDL(), qGWD(), qTWS(), qJLT() and qHIT(). @param firstline : Optional, but must be >= 1 and smaller than 'lastline'. @param lastline : Optional, defaults to query all available data points. @param numtables : Arrange data into 'numtables' columns, defaults to "1". @return: List of data points as float with 'numtables' columns. """ debug( 'DEPRECATED -- GcsDll.GetAsyncBuffer(id%d, firstline=%r, lastline=%r, numtables=%r)', self.__id, firstline, lastline, numtables) maxindex = lastline * numtables or self.__asyncbufferindex assert firstline >= 1, 'firstline must be 1 or larger' minindex = (firstline - 1) * numtables assert minindex <= maxindex, 'firstline must not be larger than lastline' cvalues = ctypes.byref(ctypes.c_float) if not getattr(self.__handle, self.__prefix + 'GetAsyncBuffer')( self.__id, cvalues): raise GCSError(self.__error) data = [[] for _ in range(numtables)] for i in range(minindex, maxindex): data[i % numtables].append(float(cvalues[i])) debug('DEPRECATED -- GCSDll.GetAsyncBuffer(id%d): %r', self.__id, data) return data
def send(self, command): """Send a GCS command to the device, do not query error from device. @param command : GCS command as string, with or without trailing line feed character. """ debug('GCSDll.send(id%d): %r', self.__id, command) command = ctypes.c_char_p(command.encode()) if not getattr(self.__handle, self.__prefix + 'GcsCommandset')( self.__id, command): raise GCSError(self.__error)
def __fillbuffer(self, answer): """Read answers and save them as float values into the data buffer. An answerline with invalid data (non-number, missing column) will be skipped and error flag is set. @param answer : String of already readout answer. """ numcolumns = len(self.__databuffer['data']) with self.__lock: while True: lines = answer.splitlines(True) # keep line endings answer = '' for line in lines: if '\n' not in line: answer = line break try: values = [float(x) for x in line.split()] assert numcolumns == len(values) except (AssertionError, ValueError): exc = GCSError(gcserror.E_1004_PI_UNEXPECTED_RESPONSE, line) self.__databuffer['error'] = exc error('GCSMessages: GCSError: %s', exc) else: for i in range(numcolumns): self.__databuffer['data'][i].append(values[i]) self.__databuffer['index'] += 1 if self.__endofdata(line): debug( 'GCSMessages: end background task to query GCS data' ) self.__databuffer['error'] = self.__checkerror( doraise=False) self.__databuffer['size'] = True return try: answer += self.__read(stopon=' \n') except: # No exception type(s) specified pylint: disable=W0702 exc = GCSError(gcserror.E_1090_PI_GCS_DATA_READ_ERROR, sys.exc_info()[1]) self.__databuffer['error'] = exc error('GCSMessages: end background task with GCSError: %s', exc) self.__databuffer['size'] = True return
def ConnectTCPIPByDescription(self, description): """Open a TCP/IP connection to the device using the device 'description'. @param description: One of the identification strings listed by EnumerateTCPIPDevices(). """ debug('GCSDll.ConnectTCPIPByDescription(description=%r)', description) cdescription = ctypes.c_char_p(description.encode()) self.__id = getattr(self.__handle, self.__prefix + 'ConnectTCPIPByDescription')(cdescription) if self.__id < 0: raise GCSError(self.__error) self.__ifdescription = 'TCPIP %r' % description
def InterfaceSetupDlg(self, key=''): """Open dialog to select the interface. @param key: Optional key name as string to store the settings in the Windows registry. """ debug('GCSDll.InterfaceSetupDlg(key=%r)', key) key = ctypes.c_char_p(key.encode()) self.__id = getattr(self.__handle, self.__prefix + 'InterfaceSetupDlg')(key) if self.__id < 0: raise GCSError(self.__error) self.__ifdescription = 'Interface Setup Dialog'
def __endofdata(self, line): """Verify 'line' and return True if 'line' is last line of device answer. @param line : One answer line of device with trailing line feed character. @return : True if 'line' is last line of device answer. """ if endofanswer(line) and self.__databuffer[ 'index'] < self.__databuffer['size']: msg = '%s expected, %d received' % (self.__databuffer['size'], self.__databuffer['index']) exc = GCSError(gcserror.E_1088_PI_TOO_FEW_GCS_DATA, msg) self.__databuffer['error'] = exc error('GCSMessages: GCSError: %s', exc) if self.__databuffer['size'] and self.__databuffer[ 'index'] > self.__databuffer['size']: msg = '%s expected, %d received' % (self.__databuffer['size'], self.__databuffer['index']) exc = GCSError(gcserror.E_1089_PI_TOO_MANY_GCS_DATA, msg) self.__databuffer['error'] = exc error('GCSMessages: GCSError: %s', exc) return endofanswer(line)
def RemoveStage(self, axis): """Remove a dataset of a user defined stage from the PI stages database. @param axis: Name of axis whose stage parameters should be removed as string. """ debug('GCSDll.RemoveStage(axis=%r)', axis) assert isinstance( axis, basestring), 'argument for RemoveStage must be string' axis = ctypes.c_char_p(axis.encode()) if not getattr(self.__handle, self.__prefix + 'RemoveStage')(self.__id, axis): raise GCSError(self.__error)
def ConnectUSB(self, serialnum): """Open an USB connection to a device. @param serialnum: Serial number of device or one of the identification strings listed by EnumerateUSB(). """ debug('GCSDll.ConnectUSB(serialnum=%r)', serialnum) cserialnum = ctypes.c_char_p(serialnum.encode()) self.__id = getattr(self.__handle, self.__prefix + 'ConnectUSB')(cserialnum) if self.__id < 0: raise GCSError(self.__error) self.__ifdescription = 'USB %r' % serialnum
def ConnectNIgpib(self, board, device): """Open a connection from a NI IEEE 488 board to the device. @param board: GPIB board ID as integer. @param device: The GPIB device ID of the device as integer. """ debug('GCSDll.ConnectNIgpib(board=%s, device=%s)', board, device) cboard = ctypes.c_int(board) cdevice = ctypes.c_int(device) self.__id = getattr(self.__handle, self.__prefix + 'ConnectNIgpib')(cboard, cdevice) if self.__id < 0: raise GCSError(self.__error) self.__ifdescription = 'GPIB board %s, device %s' % (board, device)
def __checkerror(self, senderr=True, doraise=True): """Query error from device and raise GCSError exception. @param senderr : If True send "ERR?\n" to the device. @param doraise : If True an error is raised, else the GCS error number is returned. @return : If doraise is False the GCS exception if an error occured else None. """ if not self.__errcheck: return 0 if senderr: self.__send('ERR?\n') answer = self.__read(stopon=None) exc = None try: err = int(answer) except ValueError: exc = GCSError(gcserror.E_1004_PI_UNEXPECTED_RESPONSE, answer) else: if err: exc = GCSError(err) if exc and doraise: raise exc # Raising NoneType while only classes or instances are allowed pylint: disable=E0702 return exc
def getanswer(self, bufsize): """Get the answer of a GCS command. @param bufsize : Size in characters of string buffer to store the answer as integer. @return : Answer as string. """ bufstr = ctypes.create_string_buffer('\000'.encode(), bufsize + 2) if not getattr(self.__handle, self.__prefix + 'GcsGetAnswer')( self.__id, bufstr, bufsize + 1): raise GCSError(self.__error) try: answer = bufstr.value.decode(encoding='cp1252') except UnicodeDecodeError: answer = bufstr.value debug('GCSDll.getanswer(id%d): %r', self.__id, answer) return answer
def ConnectPciBoard(self, board): """Open a PCI board connection. @param board : PCI board number as integer. """ debug('GCSDll.ConnectPciBoard(board=%s)', board) cboard = ctypes.c_int(board) if self.__prefix == 'C843_': self.__id = getattr(self.__handle, self.__prefix + 'Connect')(cboard) else: self.__id = getattr(self.__handle, self.__prefix + 'ConnectPciBoard')(cboard) if self.__id < 0: raise GCSError(self.__error) self.__ifdescription = 'PCI board %s' % board
def ConnectTCPIP(self, ipaddress, ipport=50000): """Open a TCP/IP connection to the device. @param ipaddress: IP address to connect to as string. @param ipport: Port to use as integer, defaults to 50000. """ debug('GCSDll.ConnectTCPIP(ipaddress=%s, ipport=%s)', ipaddress, ipport) cipaddress = ctypes.c_char_p(ipaddress.encode()) cipport = ctypes.c_int(ipport) self.__id = getattr(self.__handle, self.__prefix + 'ConnectTCPIP')(cipaddress, cipport) if self.__id < 0: raise GCSError(self.__error) self.__ifdescription = 'TCPIP %s:%s' % (ipaddress, ipport)
def EnumerateTCPIPDevices(self, mask=''): """Get identification strings of all TCP connected devices. @param mask: String to filter the results for certain text. @return: Found devices as list of strings. """ debug('GCSDll.EnumerateTCPIPDevices(mask=%r)', mask) mask = ctypes.c_char_p(mask.encode()) bufsize = 100000 bufstr = ctypes.create_string_buffer('\000'.encode(), bufsize + 2) if getattr(self.__handle, self.__prefix + 'EnumerateTCPIPDevices')( bufstr, bufsize, mask) < 0: raise GCSError(self.__error) devlist = bufstr.value.decode().split('\n')[:-1] devlist = [item.strip() for item in devlist] debug('GCSDll.EnumerateTCPIPDevices: %r', devlist) return devlist
def ConnectDaisyChainDevice(self, deviceid, daisychainid=None): """Connect device with 'deviceid' on the daisy chain 'daisychainid'. Daisy chain has to be connected before, see Open<interface>DaisyChain() functions. @param daisychainid : Daisy chain ID as int from the daisy chain master instance or None. @param deviceid : Device ID on the daisy chain as integer. """ debug('GCSDll.ConnectDaisyChainDevice(deviceid=%s, daisychainid=%s)', deviceid, daisychainid) if daisychainid is None: daisychainid = self.__dcid cdeviceid = ctypes.c_int(deviceid) cdaisychainid = ctypes.c_int(daisychainid) self.__id = getattr(self.__handle, self.__prefix + 'ConnectDaisyChainDevice')(cdaisychainid, cdeviceid) if self.__id < 0: raise GCSError(self.__error) if self.__ifdescription: self.__ifdescription += '; ' self.__ifdescription += 'daisy chain %d, device %s' % (daisychainid, deviceid)
def OpenUSBDaisyChain(self, description): """Open a USB daisy chain connection. To get access to a daisy chain device you have to call ConnectDaisyChainDevice(). @param description: Description of the device returned by EnumerateUSB(). @return: Found devices as list of strings. """ debug('GCSDll.OpenUSBDaisyChain(description=%r)', description) cdescription = ctypes.c_char_p(description.encode()) numdev = ctypes.byref(ctypes.c_int()) bufsize = 10000 bufstr = ctypes.create_string_buffer('\000'.encode(), bufsize + 2) self.__dcid = getattr(self.__handle, self.__prefix + 'OpenUSBDaisyChain')(cdescription, numdev, bufstr, bufsize) if self.__dcid < 0: raise GCSError(self.__error) devlist = bufstr.value.decode().split('\n')[:-1] devlist = [item.strip() for item in devlist] debug('GCSDll.OpenUSBDaisyChain: %r', devlist) self.__ifdescription = 'USB daisy chain at SN %r' % description return devlist
def read(self, tosend, gcsdata=0): """Send 'tosend' to device, read answer and check for error. @param tosend : String to send to device. @param gcsdata : Number of lines, if != 0 then GCS data will be read in background task. @return : Device answer as string. """ gcsdata = None if gcsdata < 0 else gcsdata stopon = None if 0 != gcsdata: stopon = '# END_HEADER' self.__databuffer['data'] = [] self.__databuffer['index'] = 0 self.__databuffer['error'] = None with self.__lock: while self.__interface.answersize: self.__interface.getanswer( self.__interface.answersize) # empty buffer self.__send(tosend) answer = self.__read(stopon) if 0 != gcsdata: splitpos = answer.upper().find(stopon) if splitpos < 0: self.__send('ERR?\n') err = int(self.__read(stopon=None).strip()) err = err or gcserror.E_1004_PI_UNEXPECTED_RESPONSE raise GCSError(err, answer) stopon += ' \n' splitpos += len(stopon) strbuf = answer[splitpos:] answer = answer[:splitpos] self.__databuffer['size'] = gcsdata if stopon in answer.upper( ): # "# END HEADER\n" will not start reading GCS data self.__readgcsdata(strbuf) else: self.__checkerror() return answer
def ConnectRS232(self, comport, baudrate): """Open an RS-232 connection to the device. @param comport: Port to use as integer (1 means "COM1") or name ("dev/ttys0") as string. @param baudrate: Baudrate to use as integer. """ cbaudrate = ctypes.c_int(baudrate) try: comport = int(comport) except ValueError: debug('GCSDll.ConnectRS232ByDevName(devname=%r, baudrate=%s)', comport, baudrate) cdevname = ctypes.c_char_p(comport.encode()) self.__id = getattr(self.__handle, self.__prefix + 'ConnectRS232ByDevName')(cdevname, cbaudrate) else: debug('GCSDll.ConnectRS232(comport=%s, baudrate=%s)', comport, baudrate) ccomport = ctypes.c_int(comport) self.__id = getattr(self.__handle, self.__prefix + 'ConnectRS232')(ccomport, cbaudrate) if self.__id < 0: raise GCSError(self.__error) self.__ifdescription = 'RS-232 port %s, %s Baud' % (comport, baudrate)
def __read(self, stopon): """Read answer from device until this ends with linefeed with no preceeding space. @param stopon: Addditional uppercase string that stops reading, too. @return : Received data as string. """ timeout = time() + self.__timeout / 1000. chunks = [] while True: if time() > timeout: raise GCSError(gcserror.E_7_COM_TIMEOUT) if self.__interface.answersize: timeout = time() + self.__timeout / 1000. received = self.__interface.getanswer( self.__interface.answersize) chunks.append(received) if endofanswer(chunks[-1]): break if stopon and stopon in chunks[-1].upper(): break try: answer = ''.join(chunks) except TypeError: answer = b''.join(chunks) return answer