/
BaseStation.py
205 lines (167 loc) · 7.2 KB
/
BaseStation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#!/usr/bin/env python
"""
authors: Kevin Peterson, Stan Baek, Andrew Pullin
Modification on 2011-10-4:
This file creates a class BaseStation that can be used to send commands
to the custom basestation or an XBee module
Wrapper functions are provided for this class, see:
base_functions and robot_functions
Modification on 2013-1-30: (apullin)
Brining in functions from base_functions to create a unified Basestation class.
"""
import time, os, sys, traceback
from lib import command
import serial
from scan import *
from xbee import XBee
from struct import unpack
class BaseStation(object):
api_frame = 'A'
pendingAT = False
def __init__(self, port, baudrate, channel = None, PANid = None, base_addr = None, verbose = False):
self.verbose = verbose
try:
self.ser = serial.Serial(port, baudrate, timeout = 1)
except serial.SerialException:
print
print "Could not open serial port:",port
print
print "Scanning for available COM ports:"
print "------------------------------------"
scanSerialPorts()
print "------------------------------------"
print "Check your BaseStation declaration --OR--"
print " you may need to change the port in shared.py"
sys.exit() #force exit
if verbose:
print "serial open"
self.ser.writeTimeout = 5
#Set up callback
self.xb = XBee(self.ser, callback = self.xbee_received)
def close(self):
try:
self.xb.halt()
self.ser.close()
print "BaseStation halted and close."
except SerialException:
print "SerialException on Basestation close() attempt."
def sendTX(self, status, type, data ):
pld = chr(status) + chr(type) + ''.join(data)
self.xb.tx(dest_addr = self.dest_addr, data = pld)
time.sleep(0.1)
def sendAT(self, command, parameter = None, frame_id = None):
#TODO: This logic may not be correct. Need to sort out condition where frame id and parameters are used
if frame_id is None:
#Send with no wait
if parameter is not None:
self.xb.at(command = command, parameter = parameter)
else:
self.xb.at(command = command)
else: #use frame_id
#send with wait
if parameter is not None:
self.xb.at(frame_id = frame_id, command = command, parameter = parameter)
else:
self.xb.at(frame_id = frame_id, command = command)
self.ATwait()
#if parameter is not None:
# if frame_id is not None:
# self.xb.at(frame_id = frame_id, command = command, parameter = parameter)
# else:
# self.xb.at(command = command, parameter = parameter)
#elif frame_id is not None: # expects an AT response
# self.xb.at(frame_id = frame_id, command = command)
#Since an AT response is expected, this function will busy wait here for the AT response
# self.ATwait()
#else:
# self.xb.at(command = command)
def read(self):
packet = self.xb.wait_read_frame()
return packet
def getChannel(self):
self.incremetAPIFrame()
self.sendAT(command='CH', frame_id = self.api_frame)
return self.atResponseParam
def setChannel(self, param):
self.incremetAPIFrame()
self.sendAT(command='CH', parameter=param, frame_id = self.api_frame)
def getPanID(self):
self.incremetAPIFrame()
self.sendAT(command='ID', frame_id = self.api_frame)
return self.atResponseParam
def setPanID(self, param):
self.incremetAPIFrame()
self.sendAT(command='ID', parameter=param, frame_id = self.api_frame)
def getSrcAddr(self):
self.incremetAPIFrame()
self.sendAT(command='MY', frame_id = self.api_frame)
return self.atResponseParam
def setSrcAddr(self, param):
self.incremetAPIFrame()
self.sendAT(command='MY',parameter=param, frame_id = self.api_frame)
def getLastAckd(self):
self.incremetAPIFrame()
self.sendAT(command='EA', frame_id = self.api_frame)
return self.atResponseParam
def writeParams(self):
self.incremetAPIFrame()
self.sendAT(command='WR', frame_id = self.api_frame)
def incremetAPIFrame(self):
api_frame = chr( ord(self.api_frame) + 1 ) #increment API frame
def ATwait(self):
self.pendingAT = True
self.atResponseParam = None
while self.pendingAT:
pass
#Define functions to use
def xbee_received(self, packet):
try:
#Check type of packet:
name = packet.get('id')
#The packet is a response to an AT command
if name == 'at_response':
frame_id = packet.get('frame_id')
command = packet.get('command')
status = packet.get('status')
parameter = packet.get('parameter')
if parameter is not None: #responses can have no parameter
if len(parameter) == 1:
param_num = unpack('>B',parameter)[0]
else:
param_num = unpack('>H',parameter)[0]
self.atResponseParam = param_num
else:
self.atResponseParam = None
#Handle packet in whatever way is appropriate
if self.verbose:
print "Got AT response"
print "command = ",command
if parameter is not None:
print "length = ",len(parameter)
print "param = 0x%X" % param_num
else:
print "length = 0 (no parameter)"
print "param = None"
print "status = ",ord(status)
#Once all processing done, clear pendingAT flag
self.pendingAT = False
#The packet is data received from the radio
elif name == 'rx':
print "Got RX"
src_addr = packet.get('source_addr')
rssi = packet.get('rssi')
options = packet.get('options')
data = packet.get('rf_data')
#if self.verbose:
# print "RSSI:",rssi,"options:",options,"data:",data
print "RSSI:",-ord(rssi),"dBm","options:",options,"data:",data
#Handle packet in whatever way is appropriate
#TODO: Have installable dictionary of handlers here?
except Exception as args:
print "\nGeneral exception from callbackfunc:",args
print "\n ****** TRACEBACK ****** "
traceback.print_exc()
print " ***************************** \n"
print "Attempting to exit cleanly..."
self.xb.halt()
self.ser.close()