Package killerbee :: Module dev_telosb
[hide private]
[frames] | no frames]

Source Code for Module killerbee.dev_telosb

  1  ''' 
  2  Support for the TelosB / Tmote Sky platforms, and close clones. 
  3   
  4  Utilizes the GoodFET firmware with CCSPI application, and the GoodFET client code. 
  5  ''' 
  6   
  7  import os 
  8  import time 
  9  import struct 
 10  import time 
 11  from datetime import datetime, date, timedelta 
 12  from kbutils import KBCapabilities, makeFCS 
 13  from GoodFETCCSPI import GoodFETCCSPI 
 14   
 15  CC2420_REG_SYNC = 0x14 
 16   
17 -class TELOSB:
18 - def __init__(self, dev):
19 ''' 20 Instantiates the KillerBee class for our TelosB/TmoteSky running GoodFET firmware. 21 @type dev: String 22 @param dev: Serial device identifier (ex /dev/ttyUSB0) 23 @return: None 24 @rtype: None 25 ''' 26 self._channel = None 27 self.handle = None 28 self.dev = dev 29 30 os.environ["board"] = "telosb" #set enviroment variable for GoodFET code to use 31 self.handle = GoodFETCCSPI() 32 self.handle.serInit(port=self.dev) 33 self.handle.setup() 34 35 self.__stream_open = False 36 self.capabilities = KBCapabilities() 37 self.__set_capabilities()
38
39 - def close(self):
40 self.handle.serClose() 41 self.handle = None
42
43 - def check_capability(self, capab):
44 return self.capabilities.check(capab)
45 - def get_capabilities(self):
46 return self.capabilities.getlist()
47 - def __set_capabilities(self):
48 ''' 49 Sets the capability information appropriate for GoodFETCCSPI client and firmware. 50 @rtype: None 51 @return: None 52 ''' 53 self.capabilities.setcapab(KBCapabilities.FREQ_2400, True) 54 self.capabilities.setcapab(KBCapabilities.SNIFF, True) 55 self.capabilities.setcapab(KBCapabilities.SETCHAN, True) 56 self.capabilities.setcapab(KBCapabilities.INJECT, True) 57 self.capabilities.setcapab(KBCapabilities.PHYJAM_REFLEX, True) 58 self.capabilities.setcapab(KBCapabilities.SET_SYNC, True) 59 return
60 61 # KillerBee expects the driver to implement this function 62 #def get_dev_info(self, dev, bus):
63 - def get_dev_info(self):
64 ''' 65 Returns device information in a list identifying the device. 66 @rtype: List 67 @return: List of 3 strings identifying device. 68 ''' 69 return [self.dev, "TelosB/Tmote", ""]
70 71 # KillerBee expects the driver to implement this function
72 - def sniffer_on(self, channel=None):
73 ''' 74 Turns the sniffer on such that pnext() will start returning observed 75 data. Will set the command mode to Air Capture if it is not already 76 set. 77 @type channel: Integer 78 @param channel: Sets the channel, optional 79 @rtype: None 80 ''' 81 self.capabilities.require(KBCapabilities.SNIFF) 82 83 self.handle.RF_promiscuity(1); 84 self.handle.RF_autocrc(0); 85 86 if channel != None: 87 self.set_channel(channel) 88 89 self.handle.CC_RFST_RX(); 90 #print "Sniffer started (listening as %010x on %i MHz)" % (self.handle.RF_getsmac(), self.handle.RF_getfreq()/10**6); 91 92 self.__stream_open = True
93 94 # KillerBee expects the driver to implement this function
95 - def sniffer_off(self):
96 ''' 97 Turns the sniffer off, freeing the hardware for other functions. It is 98 not necessary to call this function before closing the interface with 99 close(). 100 @rtype: None 101 ''' 102 #TODO actually have firmware stop sending us packets! 103 self.__stream_open = False
104 105 # KillerBee expects the driver to implement this function
106 - def set_channel(self, channel):
107 ''' 108 Sets the radio interface to the specifid channel (limited to 2.4 GHz channels 11-26) 109 @type channel: Integer 110 @param channel: Sets the channel, optional 111 @rtype: None 112 ''' 113 self.capabilities.require(KBCapabilities.SETCHAN) 114 115 if channel >= 11 or channel <= 26: 116 self._channel = channel 117 self.handle.RF_setchan(channel) 118 else: 119 raise Exception('Invalid channel')
120 121 # KillerBee expects the driver to implement this function
122 - def inject(self, packet, channel=None, count=1, delay=0):
123 ''' 124 Injects the specified packet contents. 125 @type packet: String 126 @param packet: Packet contents to transmit, without FCS. 127 @type channel: Integer 128 @param channel: Sets the channel, optional 129 @type count: Integer 130 @param count: Transmits a specified number of frames, def=1 131 @type delay: Float 132 @param delay: Delay between each frame, def=1 133 @rtype: None 134 ''' 135 self.capabilities.require(KBCapabilities.INJECT) 136 137 if len(packet) < 1: 138 raise Exception('Empty packet') 139 if len(packet) > 125: # 127 - 2 to accommodate FCS 140 raise Exception('Packet too long') 141 142 if channel != None: 143 self.set_channel(channel) 144 145 self.handle.RF_autocrc(1) #let radio add the CRC 146 for pnum in range(0, count): 147 gfready = [ord(x) for x in packet] #convert packet string to GoodFET expected integer format 148 gfready.insert(0, len(gfready)+2) #add a length that leaves room for CRC 149 self.handle.RF_txpacket(gfready) 150 # Sleep was for 1 second but testing by Gianfranco Costamagna suggested lowering to 1/100th of a second 151 time.sleep(0.01) #TODO get rid of completely, and just check CC2420 status
152 # https://github.com/alvarop/msp430-cc2500/blob/master/lib/cc2500/cc2500.c 153 154 # KillerBee expects the driver to implement this function
155 - def pnext(self, timeout=100):
156 ''' 157 Returns a dictionary containing packet data, else None. 158 @type timeout: Integer 159 @param timeout: Timeout to wait for packet reception in usec 160 @rtype: List 161 @return: Returns None is timeout expires and no packet received. When a packet is received, a dictionary is returned with the keys bytes (string of packet bytes), validcrc (boolean if a vaid CRC), rssi (unscaled RSSI), and location (may be set to None). For backwards compatibility, keys for 0,1,2 are provided such that it can be treated as if a list is returned, in the form [ String: packet contents | Bool: Valid CRC | Int: Unscaled RSSI ] 162 ''' 163 if self.__stream_open == False: 164 self.sniffer_on() #start sniffing 165 166 packet = None; 167 start = datetime.now() 168 169 while (packet is None and (start + timedelta(microseconds=timeout) > datetime.now())): 170 packet = self.handle.RF_rxpacket() 171 rssi = self.handle.RF_getrssi() #TODO calibrate 172 173 if packet is None: 174 return None 175 176 frame = packet[1:] 177 if frame[-2:] == makeFCS(frame[:-2]): validcrc = True 178 else: validcrc = False 179 #Return in a nicer dictionary format, so we don't have to reference by number indicies. 180 #Note that 0,1,2 indicies inserted twice for backwards compatibility. 181 result = {0:frame, 1:validcrc, 2:rssi, 'bytes':frame, 'validcrc':validcrc, 'rssi':rssi, 'location':None} 182 result['dbm'] = rssi - 45 #TODO tune specifically to the Tmote platform (does ext antenna need to different?) 183 result['datetime'] = datetime.combine(date.today(), (datetime.now()).time()) #TODO address timezones by going to UTC everywhere 184 return result
185
186 - def ping(self, da, panid, sa, channel=None):
187 ''' 188 Not yet implemented. 189 @return: None 190 @rtype: None 191 ''' 192 raise Exception('Not yet implemented')
193
194 - def jammer_on(self, channel=None):
195 ''' 196 Not yet implemented. 197 @type channel: Integer 198 @param channel: Sets the channel, optional 199 @rtype: None 200 ''' 201 self.capabilities.require(KBCapabilities.PHYJAM_REFLEX) 202 203 self.handle.RF_promiscuity(1) 204 self.handle.RF_autocrc(0) 205 if channel != None: 206 self.set_channel(channel) 207 self.handle.CC_RFST_RX() 208 self.handle.RF_reflexjam()
209
210 - def set_sync(self, sync=0xA70F):
211 '''Set the register controlling the 802.15.4 PHY sync byte.''' 212 self.capabilities.require(KBCapabilities.SET_SYNC) 213 if (sync >> 16) > 0: 214 raise Exception("Sync word (%x) must be 2-bytes or less." % sync) 215 return self.handle.poke(CC2420_REG_SYNC, sync)
216
217 - def jammer_off(self, channel=None):
218 ''' 219 Not yet implemented. 220 @return: None 221 @rtype: None 222 ''' 223 #TODO implement 224 raise Exception('Not yet implemented')
225