Package ckbot :: Module port2port
[hide private]
[frames] | no frames]

Source Code for Module ckbot.port2port

  1  """ 
  2  module ckbot.port2port  
  3   
  4  This module provides point-to-point connectivity tools for the rest of 
  5  the ckbot classes. In particular, it encapsulates the differences  
  6  between serial ports in Linux, OS X and other common operating 
  7  environments, as well as offering a UDP transport and an xbee wrapper 
  8  for serial links. 
  9   
 10  All connections provided by this module are subclasses of Connection 
 11  class. 
 12  """ 
 13   
 14  from serial import Serial 
 15  from socket import socket, error as SocketError, AF_INET, SOCK_DGRAM 
 16  from glob import glob as GLOB_GLOB 
 17  from sys import platform, stderr 
 18  from os import sep 
 19  from json import loads as json_loads 
 20   
 21  # Handle windows 
 22  try: 
 23    import _winreg as winreg 
 24  except: 
 25    winreg = None 
 26   
27 -class Connection( object ):
28 """ 29 Abstract superclass of all Connection objects 30 """ 31
32 - def open( self ):
33 """Make the connection active""" 34 pass
35
36 - def isOpen( self ):
37 """Test if connection is open""" 38 return False
39
40 - def write( self, msg ):
41 """(pure) Attempt to write the specified message through the 42 connection. Returns number of byte written 43 """ 44 raise RuntimeError("Pure method called")
45
46 - def read( self, length ):
47 """(pure) Attempt to read the specified number of bytes. 48 r 49 Return number of bytes actually read 50 """ 51 return 0
52
53 - def close( self ):
54 """Disconnect; further traffic may raise an exception 55 """ 56 pass
57
58 - def reconnect( self, **changes ):
59 """Try to reconnect with some configuration changes""" 60 pass
61
62 -class SerialConnection( Serial, Connection ):
63 """ 64 Concrete Connection subclass representing a serial port 65 """
66 - def __init__(self, glob=None, *args, **kw):
67 # Try to resolve user globs 68 port_path = None 69 if glob is not None: 70 port_path = (GLOB_GLOB(glob)+[None])[0] 71 if port_path is None: 72 # Determine port name for current operating system 73 plat = platform.lower() 74 if "linux" in plat: # Linux 75 port_path = (GLOB_GLOB("/dev/ttyUSB*")+[None])[0] 76 elif "win32" in plat: # Windows 77 # Grab first serial port from windows machine 78 path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM' 79 key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path) 80 port_path = winreg.EnumValue(key,0)[1] 81 elif "darwin" in plat: # Mac 82 # Grab the first usbserial, failing that the first usbmodem 83 port_path = (GLOB_GLOB("/dev/tty.usbserial*")+GLOB_GLOB("/dev/tty.usbmodem*")+[None])[0] 84 else: # Unhandled OS 85 raise IOError('Unknown OS -- cannot auto-configure serial') 86 87 if port_path is None: 88 raise IOError("No serial port found and no glob hint given") 89 Serial.__init__(self, port_path, *args, **kw) 90 Connection.__init__(self) 91 if self.isOpen(): 92 self.path = port_path 93 else: 94 self.path = "<<COULD-NOT-OPEN>>"
95 96 """Since pySerial decided to break things, lets un-break them""" 97 if not hasattr(Serial,'getSupportedBaudRates'):
98 - def getSupportedBaudrates(self):
99 if type(self.BAUDRATES[0]) is int: 100 return list(self.BAUDRATES) 101 return [ (b,None) for b in self.BAUDRATES ]
102
103 - def __repr__(self):
104 r = object.__repr__(self) 105 return "%s %s %d:%d%s>" % (r[:-1],self.path, self.baudrate,self.stopbits,self.parity )
106
107 -def newConnection( spec ):
108 """Factory method for creating a Connection from a string or dictionary 109 110 Formats: 111 udp={dst="host", dport=<port>, sport=<sport>} -- set up a UDP 112 connection. 113 tty={glob=<glob>, baudrate=<baud>, stopbits = <n>, parity = 'N'|'E'|'O', timeout=0.5 } -- set up a tty connection 114 115 In dictionary format, the Connection type is given by the TYPE key, e.g. 116 dict( TYPE='tty', baudrate=9600 ) 117 other: assumed to be a Serial device glob pattern 118 """ 119 if type(spec) is str: 120 spl = spec.split("=",1) 121 if len(spl)==1: # No '=' found --> legacy string is a serial device path 122 # Just a plain string; fall back on legacy interpretation 123 res = SerialConnection(spec) 124 if not res.isOpen(): 125 raise IOError("Could not open '%s'" % spec) 126 return res 127 args = json_loads( spl[1] ) 128 T = spl[0] 129 elif type(spec) is not dict: 130 raise TypeError('spec must be a string or a dictionary') 131 else: 132 args = spec.copy() 133 T = args['TYPE'] 134 del args['TYPE'] 135 136 if T.lower() == 'udp': 137 res = UDPConnection( **args ) 138 elif T.lower() == 'tty': 139 if not args.has_key('glob'): 140 res = SerialConnection(**args) 141 if not res.isOpen(): 142 raise IOError("Could not open default port") 143 else: 144 kw = args.copy() 145 g = kw['glob'] 146 del kw['glob'] 147 res = SerialConnection(g,**kw) 148 if not res.isOpen(): 149 raise IOError("Could no open '%s'" % g) 150 else: 151 raise ValueError('Unknown Connection type %s' % repr(T)) 152 # new connection is ready, store the spec used to create it 153 args['TYPE']=T 154 res.newConnection_spec = args 155 return res
156 # 157
158 -class UDPConnection( Connection ):
159 - def __init__(self,*arg,**kw):
160 raise RuntimeError("UNIMPLEMENTED")
161