/src/LabJackPython.py
Python | 3579 lines | 3334 code | 92 blank | 153 comment | 24 complexity | 48d0b0c530feeeaea6134fb86703de43 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- """
- Multi-Platform Python wrapper that implements functions from the LabJack
- Windows UD Driver, and the Exodriver.
- This python wrapper is intended to make working with your LabJack device easy. The functions contained in this module are helper and device agnostic functions. This module provides the base Device class which the U3, U6, and UE9 classes inherit from.
- A typical user should start with their device's module, such as u3.py.
- """
- # We use the 'with' keyword to manage the thread-safe device lock. It's built-in on 2.6; 2.5 requires an import.
- from __future__ import with_statement
- import collections
- import ctypes
- import os
- import struct
- from decimal import Decimal
- import socket
- import Modbus
- import atexit # For auto-closing devices
- import threading # For a thread-safe device lock
- LABJACKPYTHON_VERSION = "10-22-2012"
- SOCKET_TIMEOUT = 3
- LJSOCKET_TIMEOUT = 62
- BROADCAST_SOCKET_TIMEOUT = 1
- MAX_USB_PACKET_LENGTH = 64
- NUMBER_OF_UNIQUE_LABJACK_PRODUCT_IDS = 5
- class LabJackException(Exception):
- """Custom Exception meant for dealing specifically with LabJack Exceptions.
- Error codes are either going to be a LabJackUD error code or a -1. The -1 implies
- a python wrapper specific error.
-
- WINDOWS ONLY
- If errorString is not specified then errorString is set by errorCode
- """
- def __init__(self, ec = 0, errorString = ''):
- self.errorCode = ec
- self.errorString = errorString
- if not self.errorString:
- try:
- pString = ctypes.create_string_buffer(256)
- staticLib.ErrorToString(ctypes.c_long(self.errorCode), ctypes.byref(pString))
- self.errorString = pString.value
- except:
- self.errorString = str(self.errorCode)
-
- def __str__(self):
- return self.errorString
- # Raised when a low-level command raises an error.
- class LowlevelErrorException(LabJackException): pass
- # Raised when the return value of OpenDevice is null.
- class NullHandleException(LabJackException):
- def __init__(self):
- self.errorString = "Couldn't open device. Please check that the device you are trying to open is connected."
- def errcheck(ret, func, args):
- """
- Whenever a function is called through ctypes, the return value is passed to
- this function to be checked for errors.
-
- Support for errno didn't come until 2.6, so Python 2.5 people should
- upgrade.
- """
- if ret == -1:
- try:
- ec = ctypes.get_errno()
- raise LabJackException(ec, "Exodriver returned error number %s" % ec)
- except AttributeError:
- raise LabJackException(-1, "Exodriver returned an error, but LabJackPython is unable to read the error code. Upgrade to Python 2.6 for this functionality.")
- else:
- return ret
- def _loadLinuxSo():
- """
- Attempts to load the liblabjackusb.so for Linux.
- """
- try:
- l = ctypes.CDLL("liblabjackusb.so", use_errno=True)
- except TypeError:
- l = ctypes.CDLL("liblabjackusb.so")
- l.LJUSB_Stream.errcheck = errcheck
- l.LJUSB_Read.errcheck = errcheck
- return l
- def _loadMacDylib():
- """
- Attempts to load the liblabjackusb.dylib for Mac OS X.
- """
- try:
- l = ctypes.CDLL("liblabjackusb.dylib", use_errno=True)
- except TypeError:
- l = ctypes.CDLL("liblabjackusb.dylib")
- l.LJUSB_Stream.errcheck = errcheck
- l.LJUSB_Read.errcheck = errcheck
- return l
- def _loadLibrary():
- """_loadLibrary()
- Returns a ctypes dll pointer to the library.
- """
- if(os.name == 'posix'):
- try:
- return _loadLinuxSo()
- except OSError, e:
- pass # We may be on Mac.
- except Exception, e:
- raise LabJackException("Could not load the Linux SO for some reason other than it not being installed. Ethernet connectivity only.\n\n The error was: %s" % e)
-
- try:
- return _loadMacDylib()
- except OSError, e:
- raise LabJackException("Could not load the Exodriver driver. Ethernet connectivity only.\n\nCheck that the Exodriver is installed, and the permissions are set correctly.\nThe error message was: %s" % e)
- except Exception, e:
- raise LabJackException("Could not load the Mac Dylib for some reason other than it not being installed. Ethernet connectivity only.\n\n The error was: %s" % e)
-
- if(os.name == 'nt'):
- try:
- return ctypes.windll.LoadLibrary("labjackud")
- except Exception, e:
- raise LabJackException("Could not load labjackud driver. Ethernet connectivity availability only.\n\n The error was: %s" % e)
- try:
- staticLib = _loadLibrary()
- except LabJackException, e:
- print "%s: %s" % ( type(e), e )
- staticLib = None
-
- # Attempt to load the windows Skymote library.
- try:
- skymoteLib = ctypes.windll.LoadLibrary("liblabjackusb")
- except:
- skymoteLib = None
- class Device(object):
- """Device(handle, localId = None, serialNumber = None, ipAddress = "", type = None)
-
- Creates a simple 0 with the following functions:
- write(writeBuffer) -- Writes a buffer.
- writeRegister(addr, value) -- Writes a value to a modbus register
- read(numBytes) -- Reads until a packet is received.
- readRegister(addr, numReg = None, format = None) -- Reads a modbus register.
- ping() -- Pings the device. Returns true if communication worked.
- close() -- Closes the device.
- reset() -- Resets the device.
- """
- def __init__(self, handle, localId = None, serialNumber = None, ipAddress = "", devType = None):
- # Not saving the handle as a void* causes many problems on 64-bit machines.
- if isinstance(handle, int):
- self.handle = ctypes.c_void_p(handle)
- else:
- self.handle = handle
- self.localId = localId
- self.serialNumber = serialNumber
- self.ipAddress = ipAddress
- self.devType = devType
- self.debug = False
- self.streamConfiged = False
- self.streamStarted = False
- self.streamPacketOffset = 0
- self._autoCloseSetup = False
- self.modbusPrependZeros = True
- self.deviceLock = threading.Lock()
- self.deviceName = "LabJack"
-
- def _writeToLJSocketHandle(self, writeBuffer, modbus):
- #if modbus is True and self.modbusPrependZeros:
- # writeBuffer = [ 0, 0 ] + writeBuffer
-
- packFormat = "B" * len(writeBuffer)
- tempString = struct.pack(packFormat, *writeBuffer)
-
- if modbus:
- self.handle.modbusSocket.send(tempString)
- else:
- self.handle.crSocket.send(tempString)
-
- return writeBuffer
- def _writeToUE9TCPHandle(self, writeBuffer, modbus):
- packFormat = "B" * len(writeBuffer)
- tempString = struct.pack(packFormat, *writeBuffer)
-
- if modbus is True:
- if self.handle.modbus is None:
- raise LabJackException("Modbus port is not available. Please upgrade to UE9 Comm firmware 1.43 or higher.")
- self.handle.modbus.send(tempString)
- else:
- self.handle.data.send(tempString)
-
- return writeBuffer
- def _writeToExodriver(self, writeBuffer, modbus):
- if modbus is True and self.modbusPrependZeros:
- writeBuffer = [ 0, 0 ] + writeBuffer
-
- newA = (ctypes.c_byte*len(writeBuffer))(0)
- for i in range(len(writeBuffer)):
- newA[i] = ctypes.c_byte(writeBuffer[i])
-
- writeBytes = staticLib.LJUSB_Write(self.handle, ctypes.byref(newA), len(writeBuffer))
-
- if(writeBytes != len(writeBuffer)):
- raise LabJackException( "Could only write %s of %s bytes." % (writeBytes, len(writeBuffer) ) )
-
- return writeBuffer
-
- def _writeToUDDriver(self, writeBuffer, modbus):
- if self.devType == 0x501:
- newA = (ctypes.c_byte*len(writeBuffer))(0)
- for i in range(len(writeBuffer)):
- newA[i] = ctypes.c_byte(writeBuffer[i])
-
- writeBytes = skymoteLib.LJUSB_IntWrite(self.handle, 1, ctypes.byref(newA), len(writeBuffer))
-
- if(writeBytes != len(writeBuffer)):
- raise LabJackException( "Could only write %s of %s bytes." % (writeBytes, len(writeBuffer) ) )
- else:
- if modbus is True and self.devType == 9:
- dataWords = len(writeBuffer)
- writeBuffer = [0, 0xF8, 0, 0x07, 0, 0] + writeBuffer #modbus low-level function
- if dataWords % 2 != 0:
- dataWords = (dataWords+1)/2
- writeBuffer.append(0)
- else:
- dataWords = dataWords/2
- writeBuffer[2] = dataWords
- setChecksum(writeBuffer)
- elif modbus is True and self.modbusPrependZeros:
- writeBuffer = [ 0, 0 ] + writeBuffer
-
- eGetRaw(self.handle, LJ_ioRAW_OUT, 0, len(writeBuffer), writeBuffer)
-
- return writeBuffer
- def write(self, writeBuffer, modbus = False, checksum = True):
- """write([writeBuffer], modbus = False)
-
- Writes the data contained in writeBuffer to the device. writeBuffer must be a list of
- bytes.
- """
- if self.handle is None:
- raise LabJackException("The device handle is None.")
- if checksum:
- setChecksum(writeBuffer)
- if(isinstance(self.handle, LJSocketHandle)):
- wb = self._writeToLJSocketHandle(writeBuffer, modbus)
- elif(isinstance(self.handle, UE9TCPHandle)):
- wb = self._writeToUE9TCPHandle(writeBuffer, modbus)
- else:
- if os.name == 'posix':
- wb = self._writeToExodriver(writeBuffer, modbus)
- elif os.name == 'nt':
- wb = self._writeToUDDriver(writeBuffer, modbus)
-
- if self.debug: print "Sent: ", hexWithoutQuotes(wb)
-
- def read(self, numBytes, stream = False, modbus = False):
- """read(numBytes, stream = False, modbus = False)
-
- Blocking read until a packet is received.
- """
- readBytes = 0
-
- if self.handle is None:
- raise LabJackException("The device handle is None.")
-
- if(isinstance(self.handle, LJSocketHandle)):
- return self._readFromLJSocketHandle(numBytes, modbus, stream)
-
- elif(isinstance(self.handle, UE9TCPHandle)):
- return self._readFromUE9TCPHandle(numBytes, stream, modbus)
- else:
- if(os.name == 'posix'):
- return self._readFromExodriver(numBytes, stream, modbus)
- elif os.name == 'nt':
- return self._readFromUDDriver(numBytes, stream, modbus)
-
- def _readFromLJSocketHandle(self, numBytes, modbus, spont = False):
- """
- Reads from LJSocket. Returns the result as a list.
- """
- if modbus:
- rcvString = self.handle.modbusSocket.recv(numBytes)
- elif spont:
- rcvString = self.handle.spontSocket.recv(numBytes)
- else:
- rcvString = self.handle.crSocket.recv(numBytes)
- readBytes = len(rcvString)
- packFormat = "B" * readBytes
- rcvDataBuff = struct.unpack(packFormat, rcvString)
- return list(rcvDataBuff)
- def _readFromUE9TCPHandle(self, numBytes, stream, modbus):
- if stream is True:
- rcvString = self.handle.stream.recv(numBytes)
- return rcvString
- else:
- if modbus is True:
- if self.handle.modbus is None:
- raise LabJackException("Modbus port is not available. Please upgrade to UE9 Comm firmware 1.43 or higher.")
- rcvString = self.handle.modbus.recv(numBytes)
- else:
- rcvString = self.handle.data.recv(numBytes)
- readBytes = len(rcvString)
- packFormat = "B" * readBytes
- rcvDataBuff = struct.unpack(packFormat, rcvString)
- return list(rcvDataBuff)
- def _readFromExodriver(self, numBytes, stream, modbus):
- newA = (ctypes.c_byte*numBytes)()
-
- if(stream):
- readBytes = staticLib.LJUSB_Stream(self.handle, ctypes.byref(newA), numBytes)
- if readBytes == 0:
- return ''
- # return the byte string in stream mode
- return struct.pack('b' * readBytes, *newA)
- else:
- readBytes = staticLib.LJUSB_Read(self.handle, ctypes.byref(newA), numBytes)
- # return a list of integers in command/response mode
- return [(newA[i] & 0xff) for i in range(readBytes)]
-
- def _readFromUDDriver(self, numBytes, stream, modbus):
- if self.devType == 0x501:
- newA = (ctypes.c_byte*numBytes)()
- readBytes = skymoteLib.LJUSB_IntRead(self.handle, 0x81, ctypes.byref(newA), numBytes)
- return [(newA[i] & 0xff) for i in range(readBytes)]
- else:
- if modbus is True and self.devType == 9:
- tempBuff = [0] * (8 + numBytes + numBytes%2)
- eGetBuff = list()
- eGetBuff = eGetRaw(self.handle, LJ_ioRAW_IN, 0, len(tempBuff), tempBuff)[1]
- #parse the modbus response out (reponse is the Modbus extended low=level function)
- retBuff = list()
- if len(eGetBuff) >= 9 and eGetBuff[1] == 0xF8 and eGetBuff[3] == 0x07:
- #figuring out the length of the modbus response
- mbSize = len(eGetBuff) - 8
- if len(eGetBuff) >= 14:
- mbSize = min(mbSize, eGetBuff[13] + 6)
- i = min(mbSize, numBytes)
- i = max(i, 0)
- retBuff = eGetBuff[8:8+i] #getting the response only
- return retBuff
- tempBuff = [0] * numBytes
- if stream:
- return eGetRaw(self.handle, LJ_ioRAW_IN, 1, numBytes, tempBuff)[1]
- return eGetRaw(self.handle, LJ_ioRAW_IN, 0, numBytes, tempBuff)[1]
-
- def readRegister(self, addr, numReg = None, format = None, unitId = None):
- """ Reads a specific register from the device and returns the value.
- Requires Modbus.py
-
- readHoldingRegister(addr, numReg = None, format = None)
- addr: The address you would like to read
- numReg: Number of consecutive addresses you would like to read
- format: the unpack format of the returned value ( '>f' or '>I')
-
- Modbus is supported for UE9s over USB from Comm Firmware 1.50 and above.
- """
-
- pkt, numBytes = self._buildReadRegisterPacket(addr, numReg, unitId)
-
- response = self._modbusWriteRead(pkt, numBytes)
-
- return self._parseReadRegisterResponse(response, numBytes, addr, format, numReg)
-
- def _buildReadRegisterPacket(self, addr, numReg, unitId):
- """
- self._buildReadRegisterPacket(addr, numReg)
- Builds a raw modbus "Read Register" packet to be written to a device
- returns a tuple:
- ( < Packet as a list >, < number of bytes to read > )
- """
- # Calculates the number of registers for that request, or if numReg is
- # specified, checks that it is a valid number.
- numReg = Modbus.calcNumberOfRegisters(addr, numReg = numReg)
-
- pkt = Modbus.readHoldingRegistersRequest(addr, numReg = numReg, unitId = unitId)
- pkt = [ ord(c) for c in pkt ]
-
- numBytes = 9 + (2 * int(numReg))
-
- return (pkt, numBytes)
-
- def _parseReadRegisterResponse(self, response, numBytes, addr, format, numReg = None):
- """
- self._parseReadRegisterReponse(reponse, numBytes, addr, format)
- Takes a "Read Register" response and converts it to a value
- returns the value
- """
- if len(response) != numBytes:
- raise LabJackException(9001, "Got incorrect number of bytes from device. Expected %s bytes, got %s bytes. The packet recieved was: %s" % (numBytes, len(response),response))
- if isinstance(response, list):
- packFormat = ">" + "B" * numBytes
- response = struct.pack(packFormat, *response)
- if format == None:
- format = Modbus.calcFormat(addr, numReg)
- value = Modbus.readHoldingRegistersResponse(response, payloadFormat=format)
- return value
-
- def writeRegister(self, addr, value, unitId = None):
- """
- Writes a value to a register. Returns the value to be written, if successful.
- Requires Modbus.py
-
- writeRegister(self, addr, value)
- addr: The address you want to write to.
- value: The value, or list of values, you want to write.
-
- if you cannot write to that register, a LabJackException is raised.
- Modbus is not supported for UE9's over USB. If you try it, a LabJackException is raised.
- """
-
- pkt, numBytes = self._buildWriteRegisterPacket(addr, value, unitId)
-
- response = self._modbusWriteRead(pkt, numBytes)
-
- return self._parseWriteRegisterResponse(response, pkt, value)
-
- def _buildWriteRegisterPacket(self, addr, value, unitId):
- """
- self._buildWriteRegisterPacket(addr, value)
- Builds a raw modbus "Write Register" packet to be written to a device
- returns a tuple:
- ( < Packet as a list >, < number of bytes to read > )
- """
- if type(value) is list:
- return self._buildWriteMultipleRegisters(addr, value, unitId)
- fmt = Modbus.calcFormat(addr)
- if fmt != '>H':
- return self._buildWriteFloatToRegister(addr, value, unitId, fmt)
- request = Modbus.writeRegisterRequest(addr, value, unitId)
- request = [ ord(c) for c in request ]
- numBytes = 12
- return request, numBytes
- def _buildWriteFloatToRegister(self, addr, value, unitId, fmt = '>f'):
- numReg = 2
- if not isinstance(value, int) and not isinstance(value, float):
- raise TypeError("Value must be a float or int.")
- # Function, Address, Num Regs, Byte count, Data
- payload = struct.pack('>BHHB', 0x10, addr, 0x02, 0x04) + struct.pack(fmt, value)
-
- request = Modbus._buildHeaderBytes(length = len(payload)+1, unitId = unitId)
- request += payload
- request = [ ord(c) for c in request ]
- numBytes = 12
- return (request, numBytes)
-
-
- def _buildWriteMultipleRegisters(self, startAddr, values, unitId = None):
- request = Modbus.writeRegistersRequest(startAddr, values, unitId)
- request = [ ord(c) for c in request ]
- numBytes = 12
- return (request, numBytes)
-
- def _parseWriteRegisterResponse(self, response, request, value):
- response = list(response)
- if request[2] != 0 and request[3] != 0:
- protoID = (request[2] << 8) + request[3]
- raise Modbus.ModbusException("Got an unexpected protocol ID: %s (expected 0). Please make sure that you have the latest firmware. UE9s need a Comm Firmware of 1.50 or greater.\n\nThe packet you received: %s" % (protoID, hexWithoutQuotes(response)))
-
- if request[7] != response[7]:
- raise LabJackException(9002, "Modbus error number %s raised while writing to register. Make sure you're writing to an address that allows writes.\n\nThe packet you received: %s" % (response[8], hexWithoutQuotes(response)))
- return value
-
- def setDIOState(self, IOnum, state):
- value = (int(state) & 0x01)
- self.writeRegister(6000+IOnum, value)
- return True
-
- def _modbusWriteRead(self, request, numBytes):
- with self.deviceLock:
- self.write(request, modbus = True, checksum = False)
- try:
- result = self.read(numBytes, modbus = True)
- if self.debug: print "Response: ", hexWithoutQuotes(result)
- return result
- except LabJackException:
- self.write(request, modbus = True, checksum = False)
- result = self.read(numBytes, modbus = True)
- if self.debug: print "Response: ", hexWithoutQuotes(result)
- return result
-
- def _checkCommandBytes(self, results, commandBytes):
- """
- Checks all the stuff from a command
- """
- size = len(commandBytes)
- if len(results) == 0:
- raise LabJackException("Got a zero length packet.")
- elif results[0] == 0xB8 and results[1] == 0xB8:
- raise LabJackException("Device detected a bad checksum.")
- elif results[1:(size+1)] != commandBytes:
- raise LabJackException("Got incorrect command bytes.\nExpected: %s\nGot: %s\nFull packet: %s" % (hexWithoutQuotes(commandBytes), hexWithoutQuotes(results[1:(size+1)]), hexWithoutQuotes(results)))
- elif not verifyChecksum(results):
- raise LabJackException("Checksum was incorrect.")
- elif results[6] != 0:
- raise LowlevelErrorException(results[6], "\nThe %s returned an error:\n %s" % (self.deviceName , lowlevelErrorToString(results[6])) )
-
- def _writeRead(self, command, readLen, commandBytes, checkBytes = True, stream=False, checksum = True):
-
- # Acquire the device lock.
- with self.deviceLock:
- self.write(command, checksum = checksum)
-
- result = self.read(readLen, stream=False)
- if self.debug: print "Response: ", hexWithoutQuotes(result)
- if checkBytes:
- self._checkCommandBytes(result, commandBytes)
-
- return result
-
-
- def ping(self):
- try:
- if self.devType == LJ_dtUE9:
- writeBuffer = [0x70, 0x70]
- self.write(writeBuffer)
- try:
- self.read(2)
- except LabJackException:
- self.write(writeBuffer)
- self.read(2)
- return True
-
- if self.devType == LJ_dtU3:
- writeBuffer = [0, 0xf8, 0x01, 0x2a, 0, 0, 0, 0]
- writeBuffer = setChecksum(writeBuffer)
- self.write(writeBuffer)
- self.read(40)
- return True
- return False
- except Exception, e:
- print e
- return False
-
- def open(self, devType, Ethernet=False, firstFound = True, serial = None, localId = None, devNumber = None, ipAddress = None, handleOnly = False, LJSocket = None):
- """
- Device.open(devType, Ethernet=False, firstFound = True, serial = None, localId = None, devNumber = None, ipAddress = None, handleOnly = False, LJSocket = None)
-
- Open a device of type devType.
- """
-
- if self.handle is not None:
- raise LabJackException(9000,"Open called on a device with a handle. Please close the device, and try again. Your device is probably already open.\nLook for lines of code that look like this:\nd = u3.U3()\nd.open() # Wrong! Device is already open.")
-
- ct = LJ_ctUSB
-
- if Ethernet:
- ct = LJ_ctETHERNET
-
- if LJSocket is not None:
- ct = LJ_ctLJSOCKET
-
- d = None
- if devNumber:
- d = openLabJack(devType, ct, firstFound = False, devNumber = devNumber, handleOnly = handleOnly, LJSocket = LJSocket)
- elif serial:
- d = openLabJack(devType, ct, firstFound = False, pAddress = serial, handleOnly = handleOnly, LJSocket = LJSocket)
- elif localId:
- d = openLabJack(devType, ct, firstFound = False, pAddress = localId, handleOnly = handleOnly, LJSocket = LJSocket)
- elif ipAddress:
- d = openLabJack(devType, ct, firstFound = False, pAddress = ipAddress, handleOnly = handleOnly, LJSocket = LJSocket)
- elif LJSocket:
- d = openLabJack(devType, ct, handleOnly = handleOnly, LJSocket = LJSocket)
- elif firstFound:
- d = openLabJack(devType, ct, firstFound = True, handleOnly = handleOnly, LJSocket = LJSocket)
- else:
- raise LabJackException("You must use first found, or give a localId, devNumber, or IP Address")
-
- self.handle = d.handle
-
- if not handleOnly:
- self._loadChangedIntoSelf(d)
-
- self._registerAtExitClose()
-
- def _loadChangedIntoSelf(self, d):
- for key, value in d.changed.items():
- self.__setattr__(key, value)
-
- def _registerAtExitClose(self):
- if not self._autoCloseSetup:
- # Only need to register auto-close once per device.
- atexit.register(self.close)
- self._autoCloseSetup = True
- def close(self):
- """close()
-
- This function is not specifically supported in the LabJackUD driver
- for Windows and so simply calls the UD function Close. For Mac and unix
- drivers, this function MUST be performed when finished with a device.
- The reason for this close is because there can not be more than one program
- with a given device open at a time. If a device is not closed before
- the program is finished it may still be held open and unable to be used
- by other programs until properly closed.
-
- For Windows, Linux, and Mac
- """
- if isinstance(self.handle, UE9TCPHandle) or isinstance(self.handle, LJSocketHandle):
- self.handle.close()
- elif os.name == 'posix':
- staticLib.LJUSB_CloseDevice(self.handle)
- elif self.devType == 0x501:
- skymoteLib.LJUSB_CloseDevice(self.handle)
-
- self.handle = None
- def reset(self):
- """Reset the LabJack device.
-
- For Windows, Linux, and Mac
-
- Sample Usage:
-
- >>> u3 = OpenLabJack(LJ_dtU3, LJ_ctUSB, "0", 1)
- >>> u3.reset()
-
- @type None
- @param Function takes no arguments
-
- @rtype: None
- @return: Function returns nothing.
-
- @raise LabJackException:
- """
-
- if os.name == 'nt':
- staticLib = ctypes.windll.LoadLibrary("labjackud")
- ec = staticLib.ResetLabJack(self.handle)
-
- if ec != 0: raise LabJackException(ec)
- elif os.name == 'posix':
- sndDataBuff = [0] * 4
-
- #Make the reset packet
- sndDataBuff[0] = 0x9B
- sndDataBuff[1] = 0x99
- sndDataBuff[2] = 0x02
-
- try:
- self.write(sndDataBuff)
- rcvDataBuff = self.read(4)
- if(len(rcvDataBuff) != 4):
- raise LabJackException(0, "Unable to reset labJack 2")
- except Exception, e:
- raise LabJackException(0, "Unable to reset labjack: %s" % str(e))
- def breakupPackets(self, packets, numBytesPerPacket):
- """
- Name: Device.breakupPackets
- Args: packets, a string or list of packets
- numBytesPerPacket, how big each packe is
- Desc: This function will break up a list into smaller chunks and return
- each chunk one at a time.
-
- >>> l = range(15)
- >>> for packet in d.breakupPackets(l, 5):
- ... print packet
- [ 0, 1, 2, 3, 4 ]
- [ 5, 6, 7, 8, 9 ]
- [ 10, 11, 12, 13, 14]
-
- """
- start, end = 0, numBytesPerPacket
- while end <= len(packets):
- yield packets[start:end]
- start, end = end, end + numBytesPerPacket
- def samplesFromPacket(self, packet):
- """
- Name: Device.samplesFromPacket
- Args: packet, a packet of stream data
- Desc: This function breaks a packet into all the two byte samples it
- contains and returns them one at a time.
-
- >>> packet = range(16) # fake packet with 1 sample in it
- >>> for sample in d.samplesFromPacket(packet):
- ... print sample
- [ 12, 13 ]
- """
- HEADER_SIZE = 12
- FOOTER_SIZE = 2
- BYTES_PER_PACKET = 2
- l = str(packet)
- l = l[HEADER_SIZE:]
- l = l[:-FOOTER_SIZE]
- while len(l) > 0:
- yield l[:BYTES_PER_PACKET]
- l = l[BYTES_PER_PACKET:]
-
- def streamStart(self):
- """
- Name: Device.streamStart()
- Args: None
- Desc: Starts streaming on the device.
- Note: You must call streamConfig() before calling this function.
- """
- if not self.streamConfiged:
- raise LabJackException("Stream must be configured before it can be started.")
-
- if self.streamStarted:
- raise LabJackException("Stream already started.")
-
- command = [ 0xA8, 0xA8 ]
- results = self._writeRead(command, 4, [], False, False, False)
-
- if results[2] != 0:
- raise LowlevelErrorException(results[2], "StreamStart returned an error:\n %s" % lowlevelErrorToString(results[2]) )
-
- self.streamStarted = True
-
- def streamData(self, convert=True):
- """
- Name: Device.streamData()
- Args: convert, should the packets be converted as they are read.
- set to False to get much faster speeds, but you will
- have to process the results later.
- Desc: Reads stream data from a LabJack device. See our stream example
- to get an idea of how this function should be called. The return
- value of streamData is a dictionary with the following keys:
- * errors: The number of errors in this block.
- * numPackets: The number of USB packets collected to return this
- block.
- * missed: The number of readings that were missed because of
- buffer overflow on the LabJack.
- * firstPacket: The PacketCounter value in the first USB packet.
- * result: The raw bytes returned from read(). The only way to get
- data if called with convert = False.
- * AINi, where i is an entry in the passed in PChannels. If called
- with convert = True, this is a list of all the readings
- in this block.
- Note: You must start the stream by calling streamStart() before calling
- this function.
- """
- if not self.streamStarted:
- raise LabJackException("Please start streaming before reading.")
- numBytes = 14 + (self.streamSamplesPerPacket * 2)
- while True:
-
- result = self.read(numBytes * self.packetsPerRequest, stream = True)
-
- if len(result) == 0:
- yield None
- continue
- numPackets = len(result) // numBytes
- errors = 0
- missed = 0
- firstPacket = ord(result[10])
- for i in range(numPackets):
- e = ord(result[11+(i*numBytes)])
- if e != 0:
- errors += 1
- if self.debug and e != 60 and e != 59: print e
- if e == 60:
- missed += struct.unpack('<I', result[6+(i*numBytes):10+(i*numBytes)] )[0]
-
- returnDict = dict(numPackets = numPackets, result = result, errors = errors, missed = missed, firstPacket = firstPacket )
-
- if convert:
- returnDict.update(self.processStreamData(result, numBytes = numBytes))
-
- yield returnDict
-
- def streamStop(self):
- """
- Name: Device.streamStop()
- Args: None
- Desc: Stops streaming on the device.
- """
- command = [ 0xB0, 0xB0 ]
- results = self._writeRead(command, 4, [], False, False, False)
-
- if results[2] != 0:
- raise LowlevelErrorException(results[2], "StreamStop returned an error:\n %s" % lowlevelErrorToString(results[2]) )
-
- self.streamStarted = False
- def getName(self):
- """
- Name: Device.getName()
- Args: None
- Desc: Returns the name of a device.
- Always returns a unicode string.
- Works as of the following firmware versions:
- U6 - 1.00
- U3 - 1.22
- UE9 - 2.00
-
- >>> d = u3.U3()
- >>> d.open()
- >>> d.getName()
- u'My LabJack U3'
- """
- name = list(self.readRegister(58000, format='B'*48, numReg = 24))
-
- if name[1] == 3:
- # Old style string
- name = "My %s" % self.deviceName
- if self.debug: print "Old UTF-16 name detected, replacing with %s" % name
- self.setName(name)
- name = name.decode("UTF-8")
- else:
- try:
- end = name.index(0x00)
- name = struct.pack("B"*end, *name[:end]).decode("UTF-8")
- except ValueError:
- name = "My %s" % self.deviceName
- if self.debug: print "Invalid name detected, replacing with %s" % name
- self.setName(name)
- name = name.decode("UTF-8")
-
- return name
-
- def setName(self, name = "My LabJack U3"):
- """
- Name: Device.setName(name = ""My LabJack U3")
- Args: name, the name you'd like to assign the the U3
- Desc: Writes a new name to the device.
- Names a limited to 30 characters or less.
- Works as of the following firmware versions:
- U6 - 1.00
- U3 - 1.22
- UE9 - 2.00
-
- >>> d = u3.U3()
- >>> d.open()
- >>> d.getName()
- u'My LabJack U3'
- >>> d.setName("Johann")
- >>> d.getName()
- u'Johann'
- """
- strLen = len(name)
-
- if strLen > 47:
- raise LabJackException("The name is too long, must be less than 48 characters.")
-
- newname = name.encode('UTF-8')
- bl = list(struct.unpack("B"*strLen, newname)) + [0x00]
- strLen += 1
-
- if strLen%2 != 0:
- bl = bl + [0x00]
- strLen += 1
-
- bl = struct.unpack(">"+"H"*(strLen/2), struct.pack("B" * strLen, *bl))
-
- self.writeRegister(58000, list(bl))
- name = property(getName, setName)
- def setDefaults(self, SetToFactoryDefaults = False):
- """
- Name: Device.setDefaults(SetToFactoryDefaults = False)
- Args: SetToFactoryDefaults, set to True reset to factory defaults.
- Desc: Executing this function causes the current or last used values
- (or the factory defaults) to be stored in flash as the power-up
- defaults.
-
- >>> myU6 = U6()
- >>> myU6.setDefaults()
- """
- command = [ 0 ] * 8
-
- #command[0] = Checksum8
- command[1] = 0xF8
- command[2] = 0x01
- command[3] = 0x0E
- #command[4] = Checksum16 (LSB)
- #command[5] = Checksum16 (MSB)
- command[6] = 0xBA
- command[7] = 0x26
-
- if SetToFactoryDefaults:
- command[6] = 0x82
- command[7] = 0xC7
-
- self._writeRead(command, 8, [ 0xF8, 0x01, 0x0E ] )
-
- def setToFactoryDefaults(self):
- return self.setDefaults(SetToFactoryDefaults = True)
-
- validDefaultBlocks = range(8)
- def readDefaults(self, BlockNum, ReadCurrent = False):
- """
- Name: Device.readDefaults(BlockNum)
- Args: BlockNum, which block to read. Must be 0-7.
- ReadCurrent, True = read current configuration
- Desc: Reads the power-up defaults from flash.
-
- >>> myU6 = U6()
- >>> myU6.readDefaults(0)
- [ 0, 0, ... , 0]
- """
- if BlockNum not in self.validDefaultBlocks:
- raise LabJackException("Defaults must be in range 0-7")
-
- byte7 = (int(bool(ReadCurrent)) << 7) + BlockNum
-
- command = [ 0, 0xF8, 0x01, 0x0E, 0, 0, 0, byte7 ]
-
- result = self._writeRead(command, 40, [ 0xF8, 0x11, 0x0E ])
-
- return result[8:]
-
- def readCurrent(self, BlockNum):
- self.readDefaults(BlockNum, ReadCurrent = True)
-
- def loadGenericDevice(self, device):
- """ Take a generic Device object, and loads it into the current object.
- The generic Device is consumed in the process.
- """
- self.handle = device.handle
-
- self._loadChangedIntoSelf(device)
-
- self._registerAtExitClose()
-
- device = None
- # --------------------- BEGIN LabJackPython ---------------------------------
- def setChecksum(command):
- """Returns a command with checksums places in the proper locations
- For Windows, Mac, and Linux
-
- Sample Usage:
-
- >>> from LabJackPython import *
- >>> command = [0] * 12
- >>> command[1] = 0xf8
- >>> command[2] = 0x03
- >>> command[3] = 0x0b
- >>> command = SetChecksum(command)
- >>> command
- [7, 248, 3, 11, 0, 0, 0, 0, 0, 0, 0, 0]
- @type command: List
- @param command: The command by which to calculate the checksum
-
- @rtype: List
- @return: A command list with checksums in the proper locations.
- """
-
- if len(command) < 8:
- raise LabJackException("Command does not contain enough bytes.")
-
- try:
- a = command[1]
-
- a = (a & 0x78) >> 3
-
- #Check if the command is an extended command
- if a == 15:
- command = setChecksum16(command)
- command = setChecksum8(command, 6)
- return command
- else:
- command = setChecksum8(command, len(command))
- return command
- except LabJackException, e:
- raise e
- except Exception, e:
- raise LabJackException("SetChecksum Exception:" + str(e))
- def verifyChecksum(buffer):
- """Verifies the checksum of a given buffer using the traditional U3/UE9 Command Structure.
- """
-
- buff0 = buffer[0]
- buff4 = buffer[4]
- buff5 = buffer[5]
- tempBuffer = setChecksum(buffer)
-
- if (buff0 == tempBuffer[0]) and (buff4 == tempBuffer[4]) \
- and (buff5 == tempBuffer[5]):
- return True
- return False
- # 1 = LJ_ctUSB
- def listAll(deviceType, connectionType = 1):
- """listAll(deviceType, connectionType) -> [[local ID, Serial Number, IP Address], ...]
-
- Searches for all devices of a given type over a given connection type and returns a list
- of all devices found.
-
- WORKS on WINDOWS, MAC, UNIX
- """
-
- if connectionType == LJ_ctLJSOCKET:
- ipAddress, port = deviceType.split(":")
- port = int(port)
-
- serverSocket = socket.socket()
- serverSocket.connect((ipAddress, port))
- serverSocket.settimeout(10)
-
- f = serverSocket.makefile(bufsize = 0)
- f.write("scan\r\n")
-
- l = f.readline().strip()
- try:
- status, numLines = l.split(' ')
- except ValueError:
- raise Exception("Got invalid line from server: %s" % l)
-
- if status.lower().startswith('ok'):
- lines = []
- marked = None
- for i in range(int(numLines)):
- l = f.readline().strip()
- dev = parseline(l)
- lines.append(dev)
-
- f.close()
- serverSocket.close()
-
- #print "Result of scan:"
- #print lines
- return lines
-
- if deviceType == 12:
- if U12DriverPresent():
- u12Driver = ctypes.windll.LoadLibrary("ljackuw")
-
- # Setup all the ctype arrays
- pSerialNumbers = (ctypes.c_long * 127)(0)
- pIDs = (ctypes.c_long * 127)(0)
- pProdID = (ctypes.c_long * 127)(0)
- pPowerList = (ctypes.c_long * 127)(0)
- pCalMatrix = (ctypes.c_long * 2540)(0)
- pNumFound = ctypes.c_long()
- pFcdd = ctypes.c_long(0)
- pHvc = ctypes.c_long(0)
-
- #Output dictionary
- deviceList = {}
-
- ec = u12Driver.ListAll(ctypes.cast(pProdID, ctypes.POINTER(ctypes.c_long)),
- ctypes.cast(pSerialNumbers, ctypes.POINTER(ctypes.c_long)),
- ctypes.cast(pIDs, ctypes.POINTER(ctypes.c_long)),
- ctypes.cast(pPowerList, ctypes.POINTER(ctypes.c_long)),
- ctypes.cast(pCalMatrix, ctypes.POINTER(ctypes.c_long)),
- ctypes.byref(pNumFound),
- ctypes.byref(pFcdd),
- ctypes.byref(pHvc))
- if ec != 0: raise LabJackException(ec)
- for i in range(pNumFound.value):
- deviceList[pSerialNumbers[i]] = { 'SerialNumber' : pSerialNumbers[i], 'Id' : pIDs[i], 'ProdId' : pProdID[i], 'powerList' : pPowerList[i] }
-
- return deviceList
-
-
- else:
- return {}
-
-
- if(os.name == 'nt'):
- if deviceType == 0x501:
- if skymoteLib is None:
- raise ImportError("Couldn't load liblabjackusb.dll. Please install, and try again.")
-
- num = skymoteLib.LJUSB_GetDevCount(0x501)
-
- deviceList = dict()
-
- for i in range(num):
- try:
- device = openLabJack(0x501, 1, firstFound = False, pAddress = None, devNumber = i+1)
- device.close()
- deviceList[str(device.serialNumber)] = device.__dict__
- except LabJackException:
- pass
-
- return deviceList
-
-
- pNumFound = ctypes.c_long()
- pSerialNumbers = (ctypes.c_long * 128)()
- pIDs = (ctypes.c_long * 128)()
- pAddresses = (ctypes.c_double * 128)()
-
- #The actual return variables so the user does not have to use ctypes
- serialNumbers = []
- ids = []
- addresses = []
-
- ec = staticLib.ListAll(deviceType, connectionType,
- ctypes.byref(pNumFound),
- ctypes.cast(pSerialNumbers, ctypes.POINTER(ctypes.c_long)),
- ctypes.cast(pIDs, ctypes.POINTER(ctypes.c_long)),
- ctypes.cast(pAddresses, ctypes.POINTER(ctypes.c_long)))
-
- if ec != 0 and ec != 1010: raise LabJackException(ec)
-
- deviceList = dict()
-
- for i in xrange(pNumFound.value):
- if pSerialNumbers[i] != 1010:
- deviceValue = dict(localId = pIDs[i], serialNumber = pSerialNumbers[i], ipAddress = DoubleToStringAddress(pAddresses[i]), devType = deviceType)
- deviceList[pSerialNumbers[i]] = deviceValue
-
- return deviceList
- if(os.name == 'posix'):
- if deviceType == LJ_dtUE9:
- return __listAllUE9Unix(connectionType)
-
- if deviceType == LJ_dtU3:
- return __listAllU3Unix()
-
- if deviceType == 6:
- return __listAllU6Unix()
-
- if deviceType == 0x501:
- return __listAllBridgesUnix()
- def isHandleValid(handle):
- if(os.name == 'nt'):
- return True
- else:
- return staticLib.LJUSB_IsHandleValid(handle)
- def deviceCount(devType = None):
- """Returns the number of devices connected. """
- if(os.name == 'nt'):
- if devType is None:
- numdev = len(listAll(3))
- numdev += len(listAll(9))
- numdev += len(listAll(6))
- if skymoteLib is not None:
- numdev += len(listAll(0x501))
- return numdev
- else:
- return len(listAll(devType))
- else:
- if devType == None:
- numdev = staticLib.LJUSB_GetDevCount(3)
- numdev += staticLib.LJUSB_GetDevCount(9)
- numdev += staticLib.LJUSB_GetDevCount(6)
- numdev += staticLib.LJUSB_GetDevCount(0x501)
- return numdev
- else:
- return staticLib.LJUSB_GetDevCount(devType)
- def getDevCounts():
- if os.name == "nt":
- # Right now there is no good way to count all the U12s on a Windows box
- return { 3 : len(listAll(3)), 6 : len(listAll(6)), 9 : len(listAll(9)), 1 : 0, 0x501 : len(listAll(0x501))}
- else:
- devCounts = (ctypes.c_uint*NUMBER_OF_UNIQUE_LABJACK_PRODUCT_IDS)()
- devIds = (ctypes.c_uint*NUMBER_OF_UNIQUE_LABJACK_PRODUCT_IDS)()
- n = ctypes.c_uint(NUMBER_OF_UNIQUE_LABJACK_PRODUCT_IDS)
- r = staticLib.LJUSB_GetDevCounts(ctypes.byref(devCounts), ctypes.byref(devIds), n)
-
- returnDict = dict()
-
- for i in range(NUMBER_OF_UNIQUE_LABJACK_PRODUCT_IDS):
- returnDict[int(devIds[i])] = int(devCounts[i])
-
- return returnDict
- def openAllLabJacks():
- if os.name == "nt":
- # Windows doesn't provide a nice way to open all the devices.
- devs = dict()
- devs[3] = listAll(3)
- devs[6] = listAll(6)
- devs[9] = listAll(9)
- devs[0x501] = listAll(0x501)
-
- devices = list()
- for prodId, numConnected in devs.items():
- for i, serial in enumerate(numConnected.keys()):
- d = Device(None, devType = prodId)
- if prodId == 0x501:
- d.open(prodId, devNumber = i)
- d = _makeDeviceFromHandle(d.handle, prodId)
- else:
- d.open(prodId, serial = serial)
- d = _makeDeviceFromHandle(d.handle, prodId)
-
- devices.append(d)
- else:
- maxHandles = 10
- devHandles = (ctypes.c_void_p*maxHandles)()
- devIds = (ctypes.c_uint*maxHandles)()
- n = ctypes.c_uint(maxHandles)
- numOpened = staticLib.LJUSB_OpenAllDevices(ctypes.byref(devHandles), ctypes.byref(devIds), n)
-
- devices = list()
-
- for i in range(numOpened):
- devices.append(_makeDeviceFromHandle(devHandles[i], int(devIds[i])))
-
-
- return devices
- def _openLabJackUsingLJSocket(deviceType, firstFound, pAddress, LJSocket, handleOnly ):
- if LJSocket is not '':
- ip, port = LJSocket.split(":")
- port = int(port)
- handle = LJSocketHandle(ip, port, deviceType, firstFound, pAddress)
- else:
- handle = LJSocketHandle('localhost', 6000, deviceType, firstFound, pAddress)
-
- return handle
- def _openLabJackUsingUDDriver(deviceType, connectionType, firstFound, pAddress, devNumber ):
- if devNumber is not None:
- devs = listAll(deviceType)
- pAddress = devs.keys()[(devNumber-1)]
-
- handle = ctypes.c_long()
- pAddress = str(pAddress)
- ec = staticLib.OpenLabJack(deviceType, connectionType,
- pAddress, firstFound, ctypes.byref(handle))
- if ec != 0: raise LabJackException(ec)
- devHandle = handle.value
-
- return devHandle
-
- def _openLabJackUsingExodriver(deviceType, firstFound, pAddress, devNumber):
- devType = ctypes.c_ulong(deviceType)
- openDev = staticLib.LJUSB_OpenDevice
- openDev.restype = ctypes.c_void_p
-
- if(devNumber != None):
- handle = openDev(devNumber, 0, devType)
- if handle <= 0:
- raise NullHandleException()
- return handle
- elif(firstFound):
- handle = openDev(1, 0, devType)
- if handle <= 0:
- print "handle: %s" % handle
- raise NullHandleException()
- return handle
- else:
- numDevices = staticLib.LJUSB_GetDevCount(deviceType)
-
- for i in range(numDevices):
- handle = openDev(i + 1, 0, devType)
-
- try:
- if handle <= 0:
- raise NullHandleException()
- device = _makeDeviceFromHandle(handle, deviceType)
- except:
- continue
-
- if device.localId == pAddress or device.serialNumber == pAddress or device.ipAddress == pAddress:
- return device
- else:
- device.close()
-
- raise LabJackException(LJE_LABJACK_NOT_FOUND)
- def _openUE9OverEthernet(firstFound, pAddress, devNumber):
- if firstFound is not True and pAddress is not None:
- #Check if valid IP address and attempt to get TCP handle
- try:
- socket.inet_aton(pAddress)
- return UE9TCPHandle(pAddress)
- except:
- pass
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
- s.settimeout(BROADCAST_SOCKET_TIMEOUT)
- sndDataBuff = [0] * 6
- sndDataBuff[0] = 0x22
- sndDataBuff[1] = 0x78
- sndDataBuff[3] = 0xa9
- outBuff = ""
- for item in sndDataBuff:
- outBuff += chr(item)
- s.sendto(outBuff, ("255.255.255.255", 52362))
- try:
- count = 1
- while True:
- rcvDataBuff = s.recv(128)
- rcvDataBuff = [ord(val) for val in rcvDataBuff]
- if verifyChecksum(rcvDataBuff):
- #Parse the packet
- macAddress = rcvDataBuff[28:34]
- macAddress…
Large files files are truncated, but you can click here to view the full file