From ec79631f5e8370cfefcc581f9e74a9e3898fc7af Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Thu, 02 Dec 2010 15:43:02 +0000 Subject: adding rfid support --- (limited to 'devices') diff --git a/devices/__init__.py b/devices/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/devices/__init__.py diff --git a/devices/__init__.pyc b/devices/__init__.pyc new file mode 100644 index 0000000..79806eb --- /dev/null +++ b/devices/__init__.pyc Binary files differ diff --git a/devices/device.py b/devices/device.py new file mode 100644 index 0000000..04a82b2 --- /dev/null +++ b/devices/device.py @@ -0,0 +1,61 @@ +import gobject + +class RFIDDevice(gobject.GObject): + """ + Ancestor class for every supported device. + The main class for the device driver must be called "RFIDReader". + """ + # signal "tag-read" has to be emitted when a tag has been read. + # The handler must receive the ISO-11784 hex value of the tag. + # signal "disconnected" has to be emitted when the device is + # unplugged or an error has been detected. + __gsignals__ = { + 'tag-read': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, + (gobject.TYPE_STRING,)), + 'disconnected': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, + (gobject.TYPE_STRING,)) + } + def __init__(self): + """ + Initializer. Subclasses must call this method. + """ + self.__gobject_init__() + + def get_present(self): + """ + This method must detect if the device is present, returning True if so, + or False otherwise. + """ + raise NotImplementedError + + def get_version(self): + """ + Returns a descriptive text of the device. + """ + raise NotImplementedError + + def do_connect(self): + """ + Connects to the device. + Must return True if successfull, False otherwise. + """ + raise NotImplementedError + + def do_disconnect(self): + """ + Disconnects from the device. + """ + raise NotImplementedError + + def read_tag(self): + """ + Returns the 64 bit data in hex format of the last read tag. + """ + raise NotImplementedError + + def write_tag(self, hex_val): + """ + Could be implemented if the device is capable of writing tags. + Receives the hex value (according to ISO 11784) to be written. + Returns True if successfull or False if something went wrong. + """ diff --git a/devices/device.pyc b/devices/device.pyc new file mode 100644 index 0000000..df471e1 --- /dev/null +++ b/devices/device.pyc Binary files differ diff --git a/devices/rfidrweusb.py b/devices/rfidrweusb.py new file mode 100644 index 0000000..bd12631 --- /dev/null +++ b/devices/rfidrweusb.py @@ -0,0 +1,200 @@ +from device import RFIDDevice +from serial import Serial +import dbus +from dbus.mainloop.glib import DBusGMainLoop +import gobject +from time import sleep +import utils + +HAL_SERVICE = 'org.freedesktop.Hal' +HAL_MGR_PATH = '/org/freedesktop/Hal/Manager' +HAL_MGR_IFACE = 'org.freedesktop.Hal.Manager' +HAL_DEV_IFACE = 'org.freedesktop.Hal.Device' +REGEXP_SERUSB = '\/org\/freedesktop\/Hal\/devices\/usb_device['\ + 'a-z,A-Z,0-9,_]*serial_usb_[0-9]' + +VERSIONS = ['301'] + +class RFIDReader(RFIDDevice): + """ + RFIDRW-E-W interface. + """ + + def __init__(self): + + RFIDDevice.__init__(self) + self.last_tag = "" + self.tags = [] + self.ser = Serial() + self.device = '' + self.device_path = '' + self._connected = False + + loop = DBusGMainLoop() + self.bus = dbus.SystemBus(mainloop=loop) + hmgr_iface = dbus.Interface(self.bus.get_object(HAL_SERVICE, + HAL_MGR_PATH), HAL_MGR_IFACE) + + hmgr_iface.connect_to_signal('DeviceRemoved', self._device_removed_cb) + + def get_present(self): + """ + Checks if RFID-RW-USB device is present. + Returns True if so, False otherwise. + """ + hmgr_if = dbus.Interface(self.bus.get_object(HAL_SERVICE, HAL_MGR_PATH), + HAL_MGR_IFACE) + serialusb_devices = set(hmgr_if.FindDeviceStringMatch('serial.type', + 'usb')) & set(hmgr_if.FindDeviceStringMatch( + 'info.subsystem', 'tty')) + for i in serialusb_devices: + serialusb_if = dbus.Interface(self.bus.get_object(HAL_SERVICE, i), + HAL_DEV_IFACE) + if serialusb_if.PropertyExists('info.parent'): + parent_udi = str(serialusb_if.GetProperty('info.parent')) + parent = dbus.Interface(self.bus.get_object(HAL_SERVICE, + parent_udi), HAL_DEV_IFACE) + if parent.PropertyExists('info.linux.driver') and \ + str(parent.GetProperty('info.linux.driver')) == 'ftdi_sio': + device = str(serialusb_if.GetProperty('linux.device_file')) + ser = Serial(device, 9600, timeout=0.1) + ser.read(100) + ser.write('v') + ser.write('e') + ser.write('r') + ser.write('\x0D') + resp = ser.read(4) + if resp[0:-1] in VERSIONS: + self.device = device + self.device_path = i + return True + return False + + def do_connect(self): + """ + Connects to the device. + Returns True if successfull, False otherwise. + """ + retval = False + if self.get_present(): + try: + self.ser = Serial(self.device, 9600, timeout=0.1) + self._connected = True + if self._select_animal_tag: + #gobject.idle_add(self._loop) + gobject.timeout_add(1000, self._loop) + retval = True + except: + self._connected = False + return retval + + def do_disconnect(self): + """ + Disconnect from the device. + """ + self.ser.close() + self._connected = False + + def read_tag(self): + """ + Returns the last read value. + """ + return self.last_tag + + def _select_animal_tag(self): + """ + Sends the "Select Tag 2" (animal tag) command to the device. + """ + self.ser.read(100) + self.ser.write('s') + self.ser.write('t') + self.ser.write('2') + self.ser.write('\x0d') + resp = self.ser.read(3)[0:-1] + if resp == 'OK': + return True + return False + + def get_version(self): + """ + Sends the version command to the device and returns + a string with the device version. + """ + #self.ser.flushInput() + ver = "???" + self.ser.read(100) + self.ser.write('v') + self.ser.write('e') + self.ser.write('r') + self.ser.write('\x0d') + resp = self.ser.read(4)[0:-1] + if resp in VERSIONS: + return "RFIDRW-E-USB " + resp + return ver + + def _device_removed_cb(self, path): + """ + Called when a device is removed. + Checks if the removed device is itself and emits the "disconnected" + signal if so. + """ + if path == self.device_path: + self.device_path = '' + self.ser.close() + self._connected = False + self.tags = [] + self.emit("disconnected","RFID-RW-USB") + + def _loop(self): + """ + Threaded loop for reading data from the device. + """ + if not self._connected: + return False + + self.ser.read(100) + self.ser.write('r') + self.ser.write('a') + self.ser.write('t') + self.ser.write('\x0d') + resp = self.ser.read(33)[0:-1].split('_') + if resp.__len__() is not 6 or resp in self.tags: + return True + + self.tags.append(resp) + anbit_bin = utils.dec2bin(int(resp[2])) + reserved_bin = '00000000000000' + databit_bin = utils.dec2bin(int(resp[3])) + country_bin = utils.dec2bin(int(resp[0])) + while country_bin.__len__() < 10: + country_bin = '0' + country_bin + id_bin = utils.dec2bin(int(resp[1])) + while id_bin.__len__() < 10: + id_bin = '0' + id_bin + + tag_bin = anbit_bin + reserved_bin + databit_bin + country_bin + id_bin + data = utils.bin2hex(tag_bin) + self.emit("tag-read", data) + self.last_tag = data + #sleep(1) + return True + +# Testing +#if __name__ == '__main__': +# def handler(device, idhex): +# """ +# Handler for "tag-read" signal. +# Prints the tag id. +# """ +# print "ID: ", idhex +# +# dev = RFIDReader() +# if dev.get_present(): +# print "SIPI!" +# dev.do_connect() +# dev.connect('tag-read', handler) +# else: +# print "Not connected" +# +# mloop = gobject.MainLoop() +# mloop.run() diff --git a/devices/rfidrweusb.pyc b/devices/rfidrweusb.pyc new file mode 100644 index 0000000..1e4bc6f --- /dev/null +++ b/devices/rfidrweusb.pyc Binary files differ diff --git a/devices/serial/.cvsignore b/devices/serial/.cvsignore new file mode 100644 index 0000000..7e99e36 --- /dev/null +++ b/devices/serial/.cvsignore @@ -0,0 +1 @@ +*.pyc \ No newline at end of file diff --git a/devices/serial/__init__.py b/devices/serial/__init__.py new file mode 100644 index 0000000..681ad5c --- /dev/null +++ b/devices/serial/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +#portable serial port access with python +#this is a wrapper module for different platform implementations +# +# (C)2001-2002 Chris Liechti +# this is distributed under a free software license, see license.txt + +VERSION = '2.4' + +import sys + +if sys.platform == 'cli': + from serialcli import * +else: + import os + #chose an implementation, depending on os + if os.name == 'nt': #sys.platform == 'win32': + from serialwin32 import * + elif os.name == 'posix': + from serialposix import * + elif os.name == 'java': + from serialjava import * + else: + raise Exception("Sorry: no implementation for your platform ('%s') available" % os.name) + diff --git a/devices/serial/__init__.pyc b/devices/serial/__init__.pyc new file mode 100644 index 0000000..a58bd97 --- /dev/null +++ b/devices/serial/__init__.pyc Binary files differ diff --git a/devices/serial/serialposix.py b/devices/serial/serialposix.py new file mode 100644 index 0000000..174e2f7 --- /dev/null +++ b/devices/serial/serialposix.py @@ -0,0 +1,492 @@ +#!/usr/bin/env python +# Python Serial Port Extension for Win32, Linux, BSD, Jython +# module for serial IO for POSIX compatible systems, like Linux +# see __init__.py +# +# (C) 2001-2008 Chris Liechti +# this is distributed under a free software license, see license.txt +# +# parts based on code from Grant B. Edwards : +# ftp://ftp.visi.com/users/grante/python/PosixSerial.py +# references: http://www.easysw.com/~mike/serial/serial.html + +import sys, os, fcntl, termios, struct, select, errno +from serialutil import * + +#Do check the Python version as some constants have moved. +if (sys.hexversion < 0x020100f0): + import TERMIOS +else: + TERMIOS = termios + +if (sys.hexversion < 0x020200f0): + import FCNTL +else: + FCNTL = fcntl + +#try to detect the os so that a device can be selected... +plat = sys.platform.lower() + +if plat[:5] == 'linux': #Linux (confirmed) + def device(port): + return '/dev/ttyS%d' % port + +elif plat == 'cygwin': #cywin/win32 (confirmed) + def device(port): + return '/dev/com%d' % (port + 1) + +elif plat == 'openbsd3': #BSD (confirmed) + def device(port): + return '/dev/ttyp%d' % port + +elif plat[:3] == 'bsd' or \ + plat[:7] == 'freebsd' or \ + plat[:7] == 'openbsd' or \ + plat[:6] == 'darwin': #BSD (confirmed for freebsd4: cuaa%d) + def device(port): + return '/dev/cuad%d' % port + +elif plat[:6] == 'netbsd': #NetBSD 1.6 testing by Erk + def device(port): + return '/dev/dty%02d' % port + +elif plat[:4] == 'irix': #IRIX (partialy tested) + def device(port): + return '/dev/ttyf%d' % (port+1) #XXX different device names depending on flow control + +elif plat[:2] == 'hp': #HP-UX (not tested) + def device(port): + return '/dev/tty%dp0' % (port+1) + +elif plat[:5] == 'sunos': #Solaris/SunOS (confirmed) + def device(port): + return '/dev/tty%c' % (ord('a')+port) + +elif plat[:3] == 'aix': #aix + def device(port): + return '/dev/tty%d' % (port) + +else: + #platform detection has failed... + print """don't know how to number ttys on this system. +! Use an explicit path (eg /dev/ttyS1) or send this information to +! the author of this module: + +sys.platform = %r +os.name = %r +serialposix.py version = %s + +also add the device name of the serial port and where the +counting starts for the first serial port. +e.g. 'first serial port: /dev/ttyS0' +and with a bit luck you can get this module running... +""" % (sys.platform, os.name, VERSION) + #no exception, just continue with a brave attempt to build a device name + #even if the device name is not correct for the platform it has chances + #to work using a string with the real device name as port paramter. + def device(portum): + return '/dev/ttyS%d' % portnum + #~ raise Exception, "this module does not run on this platform, sorry." + +#whats up with "aix", "beos", .... +#they should work, just need to know the device names. + + +#load some constants for later use. +#try to use values from TERMIOS, use defaults from linux otherwise +TIOCMGET = hasattr(TERMIOS, 'TIOCMGET') and TERMIOS.TIOCMGET or 0x5415 +TIOCMBIS = hasattr(TERMIOS, 'TIOCMBIS') and TERMIOS.TIOCMBIS or 0x5416 +TIOCMBIC = hasattr(TERMIOS, 'TIOCMBIC') and TERMIOS.TIOCMBIC or 0x5417 +TIOCMSET = hasattr(TERMIOS, 'TIOCMSET') and TERMIOS.TIOCMSET or 0x5418 + +#TIOCM_LE = hasattr(TERMIOS, 'TIOCM_LE') and TERMIOS.TIOCM_LE or 0x001 +TIOCM_DTR = hasattr(TERMIOS, 'TIOCM_DTR') and TERMIOS.TIOCM_DTR or 0x002 +TIOCM_RTS = hasattr(TERMIOS, 'TIOCM_RTS') and TERMIOS.TIOCM_RTS or 0x004 +#TIOCM_ST = hasattr(TERMIOS, 'TIOCM_ST') and TERMIOS.TIOCM_ST or 0x008 +#TIOCM_SR = hasattr(TERMIOS, 'TIOCM_SR') and TERMIOS.TIOCM_SR or 0x010 + +TIOCM_CTS = hasattr(TERMIOS, 'TIOCM_CTS') and TERMIOS.TIOCM_CTS or 0x020 +TIOCM_CAR = hasattr(TERMIOS, 'TIOCM_CAR') and TERMIOS.TIOCM_CAR or 0x040 +TIOCM_RNG = hasattr(TERMIOS, 'TIOCM_RNG') and TERMIOS.TIOCM_RNG or 0x080 +TIOCM_DSR = hasattr(TERMIOS, 'TIOCM_DSR') and TERMIOS.TIOCM_DSR or 0x100 +TIOCM_CD = hasattr(TERMIOS, 'TIOCM_CD') and TERMIOS.TIOCM_CD or TIOCM_CAR +TIOCM_RI = hasattr(TERMIOS, 'TIOCM_RI') and TERMIOS.TIOCM_RI or TIOCM_RNG +#TIOCM_OUT1 = hasattr(TERMIOS, 'TIOCM_OUT1') and TERMIOS.TIOCM_OUT1 or 0x2000 +#TIOCM_OUT2 = hasattr(TERMIOS, 'TIOCM_OUT2') and TERMIOS.TIOCM_OUT2 or 0x4000 +TIOCINQ = hasattr(TERMIOS, 'FIONREAD') and TERMIOS.FIONREAD or 0x541B + +TIOCM_zero_str = struct.pack('I', 0) +TIOCM_RTS_str = struct.pack('I', TIOCM_RTS) +TIOCM_DTR_str = struct.pack('I', TIOCM_DTR) + +TIOCSBRK = hasattr(TERMIOS, 'TIOCSBRK') and TERMIOS.TIOCSBRK or 0x5427 +TIOCCBRK = hasattr(TERMIOS, 'TIOCCBRK') and TERMIOS.TIOCCBRK or 0x5428 + +ASYNC_SPD_MASK = 0x1030 +ASYNC_SPD_CUST = 0x0030 + +baudrate_constants = { + 0: 0000000, # hang up + 50: 0000001, + 75: 0000002, + 110: 0000003, + 134: 0000004, + 150: 0000005, + 200: 0000006, + 300: 0000007, + 600: 0000010, + 1200: 0000011, + 1800: 0000012, + 2400: 0000013, + 4800: 0000014, + 9600: 0000015, + 19200: 0000016, + 38400: 0000017, + 57600: 0010001, + 115200: 0010002, + 230400: 0010003, + 460800: 0010004, + 500000: 0010005, + 576000: 0010006, + 921600: 0010007, + 1000000: 0010010, + 1152000: 0010011, + 1500000: 0010012, + 2000000: 0010013, + 2500000: 0010014, + 3000000: 0010015, + 3500000: 0010016, + 4000000: 0010017 +} + + +class Serial(SerialBase): + """Serial port class POSIX implementation. Serial port configuration is + done with termios and fcntl. Runs on Linux and many other Un*x like + systems.""" + + def open(self): + """Open port with current settings. This may throw a SerialException + if the port cannot be opened.""" + if self._port is None: + raise SerialException("Port must be configured before it can be used.") + self.fd = None + #open + try: + self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK) + except Exception, msg: + self.fd = None + raise SerialException("could not open port %s: %s" % (self._port, msg)) + #~ fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0) #set blocking + + try: + self._reconfigurePort() + except: + os.close(self.fd) + self.fd = None + else: + self._isOpen = True + #~ self.flushInput() + + + def _reconfigurePort(self): + """Set communication parameters on opened port.""" + if self.fd is None: + raise SerialException("Can only operate on a valid port handle") + custom_baud = None + + vmin = vtime = 0 #timeout is done via select + if self._interCharTimeout is not None: + vmin = 1 + vtime = int(self._interCharTimeout * 10) + try: + iflag, oflag, cflag, lflag, ispeed, ospeed, cc = termios.tcgetattr(self.fd) + except termios.error, msg: #if a port is nonexistent but has a /dev file, it'll fail here + raise SerialException("Could not configure port: %s" % msg) + #set up raw mode / no echo / binary + cflag |= (TERMIOS.CLOCAL|TERMIOS.CREAD) + lflag &= ~(TERMIOS.ICANON|TERMIOS.ECHO|TERMIOS.ECHOE|TERMIOS.ECHOK|TERMIOS.ECHONL| + TERMIOS.ISIG|TERMIOS.IEXTEN) #|TERMIOS.ECHOPRT + for flag in ('ECHOCTL', 'ECHOKE'): #netbsd workaround for Erk + if hasattr(TERMIOS, flag): + lflag &= ~getattr(TERMIOS, flag) + + oflag &= ~(TERMIOS.OPOST) + iflag &= ~(TERMIOS.INLCR|TERMIOS.IGNCR|TERMIOS.ICRNL|TERMIOS.IGNBRK) + if hasattr(TERMIOS, 'IUCLC'): + iflag &= ~TERMIOS.IUCLC + if hasattr(TERMIOS, 'PARMRK'): + iflag &= ~TERMIOS.PARMRK + + #setup baudrate + try: + ispeed = ospeed = getattr(TERMIOS,'B%s' % (self._baudrate)) + except AttributeError: + try: + ispeed = ospeed = baudrate_constants[self._baudrate] + except KeyError: + #~ raise ValueError('Invalid baud rate: %r' % self._baudrate) + # may need custom baud rate, it isnt in our list. + ispeed = ospeed = getattr(TERMIOS, 'B38400') + custom_baud = int(self._baudrate) # store for later + + #setup char len + cflag &= ~TERMIOS.CSIZE + if self._bytesize == 8: + cflag |= TERMIOS.CS8 + elif self._bytesize == 7: + cflag |= TERMIOS.CS7 + elif self._bytesize == 6: + cflag |= TERMIOS.CS6 + elif self._bytesize == 5: + cflag |= TERMIOS.CS5 + else: + raise ValueError('Invalid char len: %r' % self._bytesize) + #setup stopbits + if self._stopbits == STOPBITS_ONE: + cflag &= ~(TERMIOS.CSTOPB) + elif self._stopbits == STOPBITS_TWO: + cflag |= (TERMIOS.CSTOPB) + else: + raise ValueError('Invalid stopit specification: %r' % self._stopbits) + #setup parity + iflag &= ~(TERMIOS.INPCK|TERMIOS.ISTRIP) + if self._parity == PARITY_NONE: + cflag &= ~(TERMIOS.PARENB|TERMIOS.PARODD) + elif self._parity == PARITY_EVEN: + cflag &= ~(TERMIOS.PARODD) + cflag |= (TERMIOS.PARENB) + elif self._parity == PARITY_ODD: + cflag |= (TERMIOS.PARENB|TERMIOS.PARODD) + else: + raise ValueError('Invalid parity: %r' % self._parity) + #setup flow control + #xonxoff + if hasattr(TERMIOS, 'IXANY'): + if self._xonxoff: + iflag |= (TERMIOS.IXON|TERMIOS.IXOFF) #|TERMIOS.IXANY) + else: + iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY) + else: + if self._xonxoff: + iflag |= (TERMIOS.IXON|TERMIOS.IXOFF) + else: + iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF) + #rtscts + if hasattr(TERMIOS, 'CRTSCTS'): + if self._rtscts: + cflag |= (TERMIOS.CRTSCTS) + else: + cflag &= ~(TERMIOS.CRTSCTS) + elif hasattr(TERMIOS, 'CNEW_RTSCTS'): #try it with alternate constant name + if self._rtscts: + cflag |= (TERMIOS.CNEW_RTSCTS) + else: + cflag &= ~(TERMIOS.CNEW_RTSCTS) + #XXX should there be a warning if setting up rtscts (and xonxoff etc) fails?? + + #buffer + #vmin "minimal number of characters to be read. = for non blocking" + if vmin < 0 or vmin > 255: + raise ValueError('Invalid vmin: %r ' % vmin) + cc[TERMIOS.VMIN] = vmin + #vtime + if vtime < 0 or vtime > 255: + raise ValueError('Invalid vtime: %r' % vtime) + cc[TERMIOS.VTIME] = vtime + #activate settings + termios.tcsetattr(self.fd, TERMIOS.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]) + + # apply custom baud rate, if any + if custom_baud is not None: + import array + buf = array.array('i', [0] * 32) + + # get serial_struct + FCNTL.ioctl(self.fd, TERMIOS.TIOCGSERIAL, buf) + + # set custom divisor + buf[6] = buf[7] / custom_baud + + # update flags + buf[4] &= ~ASYNC_SPD_MASK + buf[4] |= ASYNC_SPD_CUST + + # set serial_struct + try: + res = FCNTL.ioctl(self.fd, TERMIOS.TIOCSSERIAL, buf) + except IOError: + raise ValueError('Failed to set custom baud rate: %r' % self._baudrate) + + def close(self): + """Close port""" + if self._isOpen: + if self.fd is not None: + os.close(self.fd) + self.fd = None + self._isOpen = False + + def makeDeviceName(self, port): + return device(port) + + # - - - - - - - - - - - - - - - - - - - - - - - - + + def inWaiting(self): + """Return the number of characters currently in the input buffer.""" + #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str) + s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str) + return struct.unpack('I',s)[0] + + def read(self, size=1): + """Read size bytes from the serial port. If a timeout is set it may + return less characters as requested. With no timeout it will block + until the requested number of bytes is read.""" + if self.fd is None: raise portNotOpenError + read = '' + inp = None + if size > 0: + while len(read) < size: + #print "\tread(): size",size, "have", len(read) #debug + ready,_,_ = select.select([self.fd],[],[], self._timeout) + if not ready: + break #timeout + buf = os.read(self.fd, size-len(read)) + read = read + buf + if (self._timeout >= 0 or self._interCharTimeout > 0) and not buf: + break #early abort on timeout + return read + + def write(self, data): + """Output the given string over the serial port.""" + if self.fd is None: raise portNotOpenError + if not isinstance(data, str): + raise TypeError('expected str, got %s' % type(data)) + t = len(data) + d = data + while t > 0: + try: + if self._writeTimeout is not None and self._writeTimeout > 0: + _,ready,_ = select.select([],[self.fd],[], self._writeTimeout) + if not ready: + raise writeTimeoutError + n = os.write(self.fd, d) + if self._writeTimeout is not None and self._writeTimeout > 0: + _,ready,_ = select.select([],[self.fd],[], self._writeTimeout) + if not ready: + raise writeTimeoutError + d = d[n:] + t = t - n + except OSError,v: + if v.errno != errno.EAGAIN: + raise + + def flush(self): + """Flush of file like objects. In this case, wait until all data + is written.""" + self.drainOutput() + + def flushInput(self): + """Clear input buffer, discarding all that is in the buffer.""" + if self.fd is None: + raise portNotOpenError + termios.tcflush(self.fd, TERMIOS.TCIFLUSH) + + def flushOutput(self): + """Clear output buffer, aborting the current output and + discarding all that is in the buffer.""" + if self.fd is None: + raise portNotOpenError + termios.tcflush(self.fd, TERMIOS.TCOFLUSH) + + def sendBreak(self, duration=0.25): + """Send break condition. Timed, returns to idle state after given duration.""" + if self.fd is None: + raise portNotOpenError + termios.tcsendbreak(self.fd, int(duration/0.25)) + + def setBreak(self, level=1): + """Set break: Controls TXD. When active, to transmitting is possible.""" + if self.fd is None: raise portNotOpenError + if level: + fcntl.ioctl(self.fd, TIOCSBRK) + else: + fcntl.ioctl(self.fd, TIOCCBRK) + + def setRTS(self, level=1): + """Set terminal status line: Request To Send""" + if self.fd is None: raise portNotOpenError + if level: + fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str) + else: + fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str) + + def setDTR(self, level=1): + """Set terminal status line: Data Terminal Ready""" + if self.fd is None: raise portNotOpenError + if level: + fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str) + else: + fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str) + + def getCTS(self): + """Read terminal status line: Clear To Send""" + if self.fd is None: raise portNotOpenError + s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) + return struct.unpack('I',s)[0] & TIOCM_CTS != 0 + + def getDSR(self): + """Read terminal status line: Data Set Ready""" + if self.fd is None: raise portNotOpenError + s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) + return struct.unpack('I',s)[0] & TIOCM_DSR != 0 + + def getRI(self): + """Read terminal status line: Ring Indicator""" + if self.fd is None: raise portNotOpenError + s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) + return struct.unpack('I',s)[0] & TIOCM_RI != 0 + + def getCD(self): + """Read terminal status line: Carrier Detect""" + if self.fd is None: raise portNotOpenError + s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) + return struct.unpack('I',s)[0] & TIOCM_CD != 0 + + # - - platform specific - - - - + + def drainOutput(self): + """internal - not portable!""" + if self.fd is None: raise portNotOpenError + termios.tcdrain(self.fd) + + def nonblocking(self): + """internal - not portable!""" + if self.fd is None: + raise portNotOpenError + fcntl.fcntl(self.fd, FCNTL.F_SETFL, FCNTL.O_NONBLOCK) + + def fileno(self): + """For easier of the serial port instance with select. + WARNING: this function is not portable to different platforms!""" + if self.fd is None: raise portNotOpenError + return self.fd + +if __name__ == '__main__': + s = Serial(0, + baudrate=19200, #baudrate + bytesize=EIGHTBITS, #number of databits + parity=PARITY_EVEN, #enable parity checking + stopbits=STOPBITS_ONE, #number of stopbits + timeout=3, #set a timeout value, None for waiting forever + xonxoff=0, #enable software flow control + rtscts=0, #enable RTS/CTS flow control + ) + s.setRTS(1) + s.setDTR(1) + s.flushInput() + s.flushOutput() + s.write('hello') + print repr(s.read(5)) + print s.inWaiting() + del s + diff --git a/devices/serial/serialposix.pyc b/devices/serial/serialposix.pyc new file mode 100644 index 0000000..e092a0f --- /dev/null +++ b/devices/serial/serialposix.pyc Binary files differ diff --git a/devices/serial/serialutil.py b/devices/serial/serialutil.py new file mode 100644 index 0000000..fd466f2 --- /dev/null +++ b/devices/serial/serialutil.py @@ -0,0 +1,400 @@ +#! python +# Python Serial Port Extension for Win32, Linux, BSD, Jython +# see __init__.py +# +# (C) 2001-2008 Chris Liechti +# this is distributed under a free software license, see license.txt + +PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S' +STOPBITS_ONE, STOPBITS_TWO = (1, 2) +FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5,6,7,8) + +PARITY_NAMES = { + PARITY_NONE: 'None', + PARITY_EVEN: 'Even', + PARITY_ODD: 'Odd', + PARITY_MARK: 'Mark', + PARITY_SPACE:'Space', +} + +XON = chr(17) +XOFF = chr(19) + +#Python < 2.2.3 compatibility +try: + True +except: + True = 1 + False = not True + +class SerialException(Exception): + """Base class for serial port related exceptions.""" + +portNotOpenError = SerialException('Port not open') + +class SerialTimeoutException(SerialException): + """Write timeouts give an exception""" + +writeTimeoutError = SerialTimeoutException("Write timeout") + +class FileLike(object): + """An abstract file like class. + + This class implements readline and readlines based on read and + writelines based on write. + This class is used to provide the above functions for to Serial + port objects. + + Note that when the serial port was opened with _NO_ timeout that + readline blocks until it sees a newline (or the specified size is + reached) and that readlines would never return and therefore + refuses to work (it raises an exception in this case)! + """ + + def read(self, size): raise NotImplementedError + def write(self, s): raise NotImplementedError + + def readline(self, size=None, eol='\n'): + """read a line which is terminated with end-of-line (eol) character + ('\n' by default) or until timeout""" + line = '' + while 1: + c = self.read(1) + if c: + line += c #not very efficient but lines are usually not that long + if c == eol: + break + if size is not None and len(line) >= size: + break + else: + break + return line + + def readlines(self, sizehint=None, eol='\n'): + """read a list of lines, until timeout + sizehint is ignored""" + if self.timeout is None: + raise ValueError, "Serial port MUST have enabled timeout for this function!" + lines = [] + while 1: + line = self.readline(eol=eol) + if line: + lines.append(line) + if line[-1] != eol: #was the line received with a timeout? + break + else: + break + return lines + + def xreadlines(self, sizehint=None): + """just call readlines - here for compatibility""" + return self.readlines() + + def writelines(self, sequence): + for line in sequence: + self.write(line) + + def flush(self): + """flush of file like objects""" + pass + + # iterator for e.g. "for line in Serial(0): ..." usage + def next(self): + line = self.readline() + if not line: raise StopIteration + return line + + def __iter__(self): + return self + + +class SerialBase(FileLike): + """Serial port base class. Provides __init__ function and properties to + get/set port settings.""" + + #default values, may be overriden in subclasses that do not support all values + BAUDRATES = (50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600, + 19200,38400,57600,115200,230400,460800,500000,576000,921600, + 1000000,1152000,1500000,2000000,2500000,3000000,3500000,4000000) + BYTESIZES = (FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS) + PARITIES = (PARITY_NONE, PARITY_EVEN, PARITY_ODD) + STOPBITS = (STOPBITS_ONE, STOPBITS_TWO) + + def __init__(self, + port = None, #number of device, numbering starts at + #zero. if everything fails, the user + #can specify a device string, note + #that this isn't portable anymore + #port will be opened if one is specified + baudrate=9600, #baudrate + bytesize=EIGHTBITS, #number of databits + parity=PARITY_NONE, #enable parity checking + stopbits=STOPBITS_ONE, #number of stopbits + timeout=None, #set a timeout value, None to wait forever + xonxoff=0, #enable software flow control + rtscts=0, #enable RTS/CTS flow control + writeTimeout=None, #set a timeout for writes + dsrdtr=None, #None: use rtscts setting, dsrdtr override if true or false + interCharTimeout=None #Inter-character timeout, None to disable + ): + """Initialize comm port object. If a port is given, then the port will be + opened immediately. Otherwise a Serial port object in closed state + is returned.""" + + self._isOpen = False + self._port = None #correct value is assigned below trough properties + self._baudrate = None #correct value is assigned below trough properties + self._bytesize = None #correct value is assigned below trough properties + self._parity = None #correct value is assigned below trough properties + self._stopbits = None #correct value is assigned below trough properties + self._timeout = None #correct value is assigned below trough properties + self._writeTimeout = None #correct value is assigned below trough properties + self._xonxoff = None #correct value is assigned below trough properties + self._rtscts = None #correct value is assigned below trough properties + self._dsrdtr = None #correct value is assigned below trough properties + self._interCharTimeout = None #correct value is assigned below trough properties + + #assign values using get/set methods using the properties feature + self.port = port + self.baudrate = baudrate + self.bytesize = bytesize + self.parity = parity + self.stopbits = stopbits + self.timeout = timeout + self.writeTimeout = writeTimeout + self.xonxoff = xonxoff + self.rtscts = rtscts + self.dsrdtr = dsrdtr + self.interCharTimeout = interCharTimeout + + if port is not None: + self.open() + + def isOpen(self): + """Check if the port is opened.""" + return self._isOpen + + # - - - - - - - - - - - - - - - - - - - - - - - - + + #TODO: these are not realy needed as the is the BAUDRATES etc attribute... + #maybe i remove them before the final release... + + def getSupportedBaudrates(self): + return [(str(b), b) for b in self.BAUDRATES] + + def getSupportedByteSizes(self): + return [(str(b), b) for b in self.BYTESIZES] + + def getSupportedStopbits(self): + return [(str(b), b) for b in self.STOPBITS] + + def getSupportedParities(self): + return [(PARITY_NAMES[b], b) for b in self.PARITIES] + + # - - - - - - - - - - - - - - - - - - - - - - - - + + def setPort(self, port): + """Change the port. The attribute portstr is set to a string that + contains the name of the port.""" + + was_open = self._isOpen + if was_open: self.close() + if port is not None: + if type(port) in [type(''), type(u'')]: #strings are taken directly + self.portstr = port + else: + self.portstr = self.makeDeviceName(port) + else: + self.portstr = None + self._port = port + if was_open: self.open() + + def getPort(self): + """Get the current port setting. The value that was passed on init or using + setPort() is passed back. See also the attribute portstr which contains + the name of the port as a string.""" + return self._port + + port = property(getPort, setPort, doc="Port setting") + + + def setBaudrate(self, baudrate): + """Change baudrate. It raises a ValueError if the port is open and the + baudrate is not possible. If the port is closed, then tha value is + accepted and the exception is raised when the port is opened.""" + #~ if baudrate not in self.BAUDRATES: raise ValueError("Not a valid baudrate: %r" % baudrate) + try: + self._baudrate = int(baudrate) + except TypeError: + raise ValueError("Not a valid baudrate: %r" % (baudrate,)) + else: + if self._isOpen: self._reconfigurePort() + + def getBaudrate(self): + """Get the current baudrate setting.""" + return self._baudrate + + baudrate = property(getBaudrate, setBaudrate, doc="Baudrate setting") + + + def setByteSize(self, bytesize): + """Change byte size.""" + if bytesize not in self.BYTESIZES: raise ValueError("Not a valid byte size: %r" % (bytesize,)) + self._bytesize = bytesize + if self._isOpen: self._reconfigurePort() + + def getByteSize(self): + """Get the current byte size setting.""" + return self._bytesize + + bytesize = property(getByteSize, setByteSize, doc="Byte size setting") + + + def setParity(self, parity): + """Change parity setting.""" + if parity not in self.PARITIES: raise ValueError("Not a valid parity: %r" % (parity,)) + self._parity = parity + if self._isOpen: self._reconfigurePort() + + def getParity(self): + """Get the current parity setting.""" + return self._parity + + parity = property(getParity, setParity, doc="Parity setting") + + + def setStopbits(self, stopbits): + """Change stopbits size.""" + if stopbits not in self.STOPBITS: raise ValueError("Not a valid stopbit size: %r" % (stopbits,)) + self._stopbits = stopbits + if self._isOpen: self._reconfigurePort() + + def getStopbits(self): + """Get the current stopbits setting.""" + return self._stopbits + + stopbits = property(getStopbits, setStopbits, doc="Stopbits setting") + + + def setTimeout(self, timeout): + """Change timeout setting.""" + if timeout is not None: + if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,)) + try: + timeout + 1 #test if it's a number, will throw a TypeError if not... + except TypeError: + raise ValueError("Not a valid timeout: %r" % (timeout,)) + + self._timeout = timeout + if self._isOpen: self._reconfigurePort() + + def getTimeout(self): + """Get the current timeout setting.""" + return self._timeout + + timeout = property(getTimeout, setTimeout, doc="Timeout setting for read()") + + + def setWriteTimeout(self, timeout): + """Change timeout setting.""" + if timeout is not None: + if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,)) + try: + timeout + 1 #test if it's a number, will throw a TypeError if not... + except TypeError: + raise ValueError("Not a valid timeout: %r" % timeout) + + self._writeTimeout = timeout + if self._isOpen: self._reconfigurePort() + + def getWriteTimeout(self): + """Get the current timeout setting.""" + return self._writeTimeout + + writeTimeout = property(getWriteTimeout, setWriteTimeout, doc="Timeout setting for write()") + + + def setXonXoff(self, xonxoff): + """Change XonXoff setting.""" + self._xonxoff = xonxoff + if self._isOpen: self._reconfigurePort() + + def getXonXoff(self): + """Get the current XonXoff setting.""" + return self._xonxoff + + xonxoff = property(getXonXoff, setXonXoff, doc="Xon/Xoff setting") + + def setRtsCts(self, rtscts): + """Change RtsCts flow control setting.""" + self._rtscts = rtscts + if self._isOpen: self._reconfigurePort() + + def getRtsCts(self): + """Get the current RtsCts flow control setting.""" + return self._rtscts + + rtscts = property(getRtsCts, setRtsCts, doc="RTS/CTS flow control setting") + + def setDsrDtr(self, dsrdtr=None): + """Change DsrDtr flow control setting.""" + if dsrdtr is None: + #if not set, keep backwards compatibility and follow rtscts setting + self._dsrdtr = self._rtscts + else: + #if defined independently, follow its value + self._dsrdtr = dsrdtr + if self._isOpen: self._reconfigurePort() + + def getDsrDtr(self): + """Get the current DsrDtr flow control setting.""" + return self._dsrdtr + + dsrdtr = property(getDsrDtr, setDsrDtr, "DSR/DTR flow control setting") + + def setInterCharTimeout(self, interCharTimeout): + """Change inter-character timeout setting.""" + if interCharTimeout is not None: + if interCharTimeout < 0: raise ValueError("Not a valid timeout: %r" % interCharTimeout) + try: + interCharTimeout + 1 #test if it's a number, will throw a TypeError if not... + except TypeError: + raise ValueError("Not a valid timeout: %r" % interCharTimeout) + + self._interCharTimeout = interCharTimeout + if self._isOpen: self._reconfigurePort() + + def getInterCharTimeout(self): + """Get the current inter-character timeout setting.""" + return self._interCharTimeout + + interCharTimeout = property(getInterCharTimeout, setInterCharTimeout, doc="Inter-character timeout setting for read()") + + + # - - - - - - - - - - - - - - - - - - - - - - - - + + def __repr__(self): + """String representation of the current port settings and its state.""" + return "%s(port=%r, baudrate=%r, bytesize=%r, parity=%r, stopbits=%r, timeout=%r, xonxoff=%r, rtscts=%r, dsrdtr=%r)" % ( + self.__class__.__name__, + id(self), + self._isOpen, + self.portstr, + self.baudrate, + self.bytesize, + self.parity, + self.stopbits, + self.timeout, + self.xonxoff, + self.rtscts, + self.dsrdtr, + ) + +if __name__ == '__main__': + s = SerialBase() + print s.portstr + print s.getSupportedBaudrates() + print s.getSupportedByteSizes() + print s.getSupportedParities() + print s.getSupportedStopbits() + print s diff --git a/devices/serial/serialutil.pyc b/devices/serial/serialutil.pyc new file mode 100644 index 0000000..0199bc5 --- /dev/null +++ b/devices/serial/serialutil.pyc Binary files differ diff --git a/devices/tis2000.py b/devices/tis2000.py new file mode 100644 index 0000000..91d1991 --- /dev/null +++ b/devices/tis2000.py @@ -0,0 +1,252 @@ +from device import RFIDDevice +from serial import Serial +import dbus +from dbus.mainloop.glib import DBusGMainLoop +import gobject +import re +from time import sleep + +HAL_SERVICE = 'org.freedesktop.Hal' +HAL_MGR_PATH = '/org/freedesktop/Hal/Manager' +HAL_MGR_IFACE = 'org.freedesktop.Hal.Manager' +HAL_DEV_IFACE = 'org.freedesktop.Hal.Device' +REGEXP_SERUSB = '\/org\/freedesktop\/Hal\/devices\/usb_device['\ + 'a-z,A-Z,0-9,_]*serial_usb_[0-9]' + +STATE_WAITING = 0 +STATE_WAITING2 = 1 +STATE_READING = 2 + +class RFIDReader(RFIDDevice): + """ + TIS-2000 interface. + """ + + def __init__(self): + + RFIDDevice.__init__(self) + self.last_tag = "" + self.ser = Serial() + self.device = '' + self.device_path = '' + self._connected = False + self._state = STATE_WAITING + + loop = DBusGMainLoop() + self.bus = dbus.SystemBus(mainloop=loop) + hmgr_iface = dbus.Interface(self.bus.get_object(HAL_SERVICE, + HAL_MGR_PATH), HAL_MGR_IFACE) + + hmgr_iface.connect_to_signal('DeviceRemoved', self._device_removed_cb) + + def get_present(self): + """ + Checks if TI-S2000 device is present. + Returns True if so, False otherwise. + """ + hmgr_if = dbus.Interface(self.bus.get_object(HAL_SERVICE, HAL_MGR_PATH), + HAL_MGR_IFACE) + tiusb_devices = set(hmgr_if.FindDeviceStringMatch('serial.type', + 'usb')) & set(hmgr_if.FindDeviceStringMatch( + 'info.product', 'TUSB3410 Microcontroller')) + for i in tiusb_devices: + tiusb_if = dbus.Interface(self.bus.get_object(HAL_SERVICE, i), + HAL_DEV_IFACE) + if tiusb_if.PropertyExists('linux.device_file'): + self.device = str(tiusb_if.GetProperty('linux.device_file')) + self.device_path = i + return True + return False + + def do_connect(self): + """ + Connects to the device. + Returns True if successfull, False otherwise. + """ + retval = False + if self.get_present(): + try: + self.ser = Serial(self.device, 9600, timeout=0.1) + self._connected = True + self._escape() + self._clear() + self._format() + gobject.idle_add(self._loop) + retval = True + except: + self._connected = False + return retval + + def do_disconnect(self): + """ + Disconnect from the device. + """ + self.ser.close() + self._connected = False + + def read_tag(self): + """ + Returns the last read value. + """ + return self.last_tag + + def write_tag(self, hexval): + """ + Usage: write_tag(hexval) + + Writes the hexadecimal string "hexval" into the tag. + Returns True if successfull, False otherwise. + """ + #self.ser.flushInput() + reg = re.compile('([^0-9A-F]+)') + if not (hexval.__len__() == 16 and reg.findall(hexval) == []): + return False + self.ser.read(100) + self.ser.write('P') + for i in hexval: + self.ser.write(i) + sleep(1) + resp = self.ser.read(64) + resp = resp.split()[0] + if resp == "P0": + return True + else: + return False + + def _escape(self): + """ + Sends the scape command to the TIS-2000 device. + """ + try: + #self.ser.flushInput() + self.ser.read(100) + self.ser.write('\x1B') + resp = self.ser.read() + if resp == 'E': + return True + else: + return False + except: + return False + + def _format(self): + """ + Sends the format command to the TIS-2000 device. + """ + try: + #self.ser.flushInput() + self.ser.read(100) + self.ser.write('F') + resp = self.ser.read() + if resp == 'F': + return True + else: + return False + except: + return False + + def _clear(self): + """ + Sends the clear command to the TIS-2000 device. + """ + try: + #self.ser.flushInput() + self.ser.read(100) + self.ser.write('C') + resp = self.ser.read() + if resp == 'C': + return True + else: + return False + except: + return False + + def get_version(self): + """ + Sends the version command to the TIS-2000 device and returns + a string with the device version. + """ + #self.ser.flushInput() + self.ser.read(100) + self.ser.write('V') + version = [] + tver = "" + while 1: + resp = self.ser.read() + if resp == '\x0A' or resp == '': + break + if resp != '\n' and resp != '\r': + version.append(resp) + for i in version: + tver = tver + i + if tver != "": + return tver + return "Unknown" + + def _device_removed_cb(self, path): + """ + Called when a device is removed. + Checks if the removed device is itself and emits the "disconnected" + signal if so. + """ + if path == self.device_path: + self.device_path = '' + self.ser.close() + self._connected = False + self.emit("disconnected","TIS-2000") + + def _loop(self): + """ + Threaded loop for reading data sent from the TIS-2000. + """ + if not self._connected: + return False + + if self._state is STATE_WAITING: + data = self.ser.read() + if data in ['W', 'R']: + self._state = STATE_WAITING2 + return True + + elif self._state is STATE_WAITING2: + data = self.ser.read() + if data.isspace(): + self._state = STATE_READING + else: + self._clear() + self._state = STATE_WAITING + return True + + elif self._state is STATE_READING: + data = self.ser.read(16) + if data.__len__() < 16: + self._clear() + self._state = STATE_WAITING + else: + reg = re.compile('([^0-9A-F]+)') + if reg.findall(data) == []: + self.emit("tag-read", data) + self.last_tag = data + self._clear() + self._state = STATE_WAITING + return True + return True + +# Testing +#if __name__ == '__main__': +# def handler(device, idhex): +# """ +# Handler for "tag-read" signal. +# Prints the tag id. +# """ +# print "ID: ", idhex +# +# dev = RFIDReader() +# if dev.get_present(): +# dev.do_connect() +# dev.connect('tag-read', handler) +# else: +# print "Not connected" +# +# mloop = gobject.MainLoop() +# mloop.run() diff --git a/devices/tis2000.pyc b/devices/tis2000.pyc new file mode 100644 index 0000000..ddf3fa3 --- /dev/null +++ b/devices/tis2000.pyc Binary files differ diff --git a/devices/utils.py b/devices/utils.py new file mode 100644 index 0000000..94e5540 --- /dev/null +++ b/devices/utils.py @@ -0,0 +1,98 @@ +# utils.py - Helper functions for tis2000.py +# Copyright (C) 2010 Emiliano Pastorino +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +def strhex2bin(strhex): + """ + Convert a string representing an hex value into a + string representing the same value in binary format. + """ + dic = { '0':"0000", + '1':"0001", + '2':"0010", + '3':"0011", + '4':"0100", + '5':"0101", + '6':"0110", + '7':"0111", + '8':"1000", + '9':"1001", + 'A':"1010", + 'B':"1011", + 'C':"1100", + 'D':"1101", + 'E':"1110", + 'F':"1111" + } + binstr = "" + for i in strhex: + binstr = binstr + dic[i.upper()] + return binstr + +def strbin2dec(strbin): + """ + Convert a string representing a binary value into a + string representing the same value in decimal format. + """ + strdec = "0" + for i in range(1, strbin.__len__()+1): + strdec = str(int(strdec)+int(strbin[-i])*int(pow(2, i-1))) + return strdec + +def dec2bin(ndec): + """ + Convert a decimal number into a string representing + the same value in binary format. + """ + if ndec < 1: + return "0" + binary = [] + while ndec != 0: + binary.append(ndec%2) + ndec = ndec/2 + strbin = "" + binary.reverse() + for i in binary: + strbin = strbin+str(i) + return strbin + +def bin2hex(strbin): + """ + Convert a string representing a binary number into a string + representing the same value in hexadecimal format. + """ + dic = { "0000":"0", + "0001":"1", + "0010":"2", + "0011":"3", + "0100":"4", + "0101":"5", + "0110":"6", + "0111":"7", + "1000":"8", + "1001":"9", + "1010":"A", + "1011":"B", + "1100":"C", + "1101":"D", + "1110":"E", + "1111":"F" + } + while strbin.__len__()%4 != 0: + strbin = '0' + strbin + strh = "" + for i in range(0, strbin.__len__()/4): + strh = strh + dic[str(strbin[i*4:i*4+4])] + return strh diff --git a/devices/utils.pyc b/devices/utils.pyc new file mode 100644 index 0000000..e7f36e2 --- /dev/null +++ b/devices/utils.pyc Binary files differ -- cgit v0.9.1