annotate zb.py @ 12:a3ec3f2988ac

Initial commit of zbmux. This program demultiplexes packets from remote ZB modules to feed into a log file. Also allows user(s) to telnet to a port to talk to a particular module. Needs more work. eg - TCP connections should be in raw mode, not line. - There is no way to access statistics for each module.
author darius@Inchoate
date Tue, 13 Jan 2009 12:17:02 +1030
parents 75f785a09e2e
children 729f2393f296
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
1 #
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
2 # Code to talk to MaxStream ZigBee modules in API (no escaped
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
3 # characters)
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
4 #
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
5 # Copyright (c) 2009
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
6 # Daniel O'Connor <darius@dons.net.au>. All rights reserved.
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
7 #
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
8 # Redistribution and use in source and binary forms, with or without
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
9 # modification, are permitted provided that the following conditions
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
10 # are met:
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
11 # 1. Redistributions of source code must retain the above copyright
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
12 # notice, this list of conditions and the following disclaimer.
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
13 # 2. Redistributions in binary form must reproduce the above copyright
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
14 # notice, this list of conditions and the following disclaimer in the
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
15 # documentation and/or other materials provided with the distribution.
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
16 #
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
17 # THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
18 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
19 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
20 # ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
21 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
22 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
23 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
24 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
26 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
27 # SUCH DAMAGE.
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
28 #
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
29 """MaxStream ZigBee module API interface
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
30
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
31 This code expects the module to be in API mode 1 (no escape
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
32 characters), ie you have done something like..
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
33 +++
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
34 ATAP=1
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
35 ATWR
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
36 ATCN
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
37
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
38 See here for details
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
39 http://www.digi.com/products/wireless/point-multipoint/xbee-series1-moduledocs.jsp
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
40 """
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
41
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
42 import inspect
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
43
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
44 def easyord(i):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
45 """Helper function to return the ordinal of a string, or just the
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
46 passed in value"""
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
47 if (type(i) != type(str())):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
48 return i
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
49 else:
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
50 return ord(i)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
51
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
52 class PktBase(object):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
53 """Base class for all packet types"""
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
54 PKT_MAXLEN = 2 ** 16
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
55 PKT_TYPE = None
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
56
10
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
57 def __init__(self):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
58 #print "Constructing " + self.__class__.__name__
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
59 pass
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
60
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
61 def Encapsulate(self):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
62 """Encapsulate the packet"""
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
63 return Packets.Encapsulate([self.PKT_TYPE] + self.data)
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
64
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
65 def Pack(self):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
66 """Return string version of encapsulated packet"""
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
67 return reduce(lambda x, y: str(x) + str(y), self.Encapsulate())
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
68
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
69 def resize(self, dlen):
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
70 """Ensure the data list can hold at least len elements (0 fill)"""
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
71 if (len(self._data) < dlen):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
72 self._data = (self._data + [0] * dlen)[0:dlen]
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
73
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
74 @staticmethod
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
75 def _checklist(list, min = 0, max = 255, maxlen = None):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
76 if (maxlen != None and len(list) > maxlen):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
77 raise ValueError("must have %d elements" % (maxlen))
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
78
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
79 for i in xrange(len(list)):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
80 if (easyord(list[i]) < min or easyord(list[i]) > max):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
81 raise ValueError("element %d (= %d) out of range must be between %d and %d inclusive" %
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
82 (i, ord(list[i]), min, max))
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
83
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
84 class TXPkts(PktBase):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
85 """Base class for all packets that go to the module"""
10
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
86
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
87 def __init__(self):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
88 # Frame ID of 0 will prevent TX status pakets being sent
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
89 self._frameid = 1
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
90
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
91 def setframeid(self, value):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
92 if (value < 0 or value > 255):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
93 raise ValueError("FrameID must be 0-255")
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
94 self._frameid = value
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
95 frameid = property(lambda s: s._frameid, setframeid)
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
96
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
97 class AT_Cmd(TXPkts):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
98 """AT command packet"""
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
99
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
100 PKT_TYPE = 0x08
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
101 PKT_DESC = "AT Command"
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
102
10
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
103 def __init__(self, cmd = None, cmdarg = None):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
104 self.frameid = 1 # XXX: why do I need to dupe this?
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
105 self.cmdarg = []
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
106
10
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
107 super(AT_Cmd, self).__init__()
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
108 if (cmd != None):
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
109 self.cmd = cmd
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
110 if (cmdarg != None):
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
111 self.cmdarg = cmdarg
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
112
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
113 def setcmd(self, value):
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
114 if (len(value) != 2):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
115 raise ValueError("must have 2 elements")
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
116 self._checklist(value, ord('0'), ord('z'))
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
117 self._cmd = value
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
118 cmd = property(lambda s: s._cmd, setcmd)
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
119
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
120 def setcmdarg(self, value):
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
121 self._checklist(value, maxlen = self.PKT_MAXLEN - 3)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
122 self._cmdarg = value
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
123 cmdarg = property(lambda s: s._cmdarg, setcmdarg)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
124
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
125 def getdata(self):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
126 return([self.frameid] + map(ord, self.cmd) + map(easyord, self.cmdarg))
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
127 data = property(getdata)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
128
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
129 class AT_Cmd_Queue(AT_Cmd):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
130 """Queued AT command packet"""
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
131
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
132 PKT_TYPE = 0x09
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
133 PKT_DESC = "AT Command (queued)"
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
134
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
135 class AT_Response(PktBase):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
136 """Response from an AT command packet"""
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
137
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
138 PKT_TYPE = 0x88
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
139 PKT_DESC = "AT Command response"
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
140 frameid = property(lambda s: s._data[0], None)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
141 cmd = property(lambda s: chr(s._data[1]) + chr(s._data[2]), None)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
142 statusOK = property(lambda s: s._data[3] == 0, None)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
143 payload = property(lambda s: s._data[4:], None)
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
144
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
145 def __init__(self, data = []):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
146 super(AT_Response, self).__init__()
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
147 self._data = data
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
148
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
149 class Modem_Status(PktBase):
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
150 PKT_TYPE = 0x8a
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
151 PKT_DESC = "Modem Status"
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
152
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
153 class RX_16_Bit(PktBase):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
154 """RX packet from a remote module (16 bit)"""
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
155 PKT_TYPE = 0x81
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
156 PKT_DESC = "RX Packet: 16 bit address"
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
157 ADDR_SIZE = 2
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
158 ADRBCASTMSK = 0x01
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
159 PANBCASTMSK = 0x02
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
160
10
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
161 def __init__(self, data = []):
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
162 super(RX_16_Bit, self).__init__()
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
163 self._data = data
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
164
8
9f0808b13454 Use non-blocking serial access. Add __str__ method for RX packets.
darius@inchoate.localdomain
parents: 7
diff changeset
165 def __str__(self):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
166 return "RX_%d_Bit 0x%0*x (%ddBm) -> %s" % (self.ADDR_SIZE * 8, self.ADDR_SIZE * 2,
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
167 self.sender, self.rssi, self.payloadstr)
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
168 def getsender(self):
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
169 value = 0
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
170 # Done this way so we can reuse the code for the 64 bit version
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
171 for i, j in zip(reversed(range(self.ADDR_SIZE)), range(0, self.ADDR_SIZE * 8, 8)):
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
172 value |= self._data[i] << j
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
173 return value
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
174 #: Source module address
5
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
175 sender = property(getsender, None)
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
176
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
177 def isAdrBcast(self):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
178 """Is this an address broadcast packet?"""
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
179 return self.flags & self.ADRBCASTMSK
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
180
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
181 def isPanBcast(self):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
182 """Is this an PAN broadcast packet?"""
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
183 return self.flags & self.PANBCASTMSK
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
184
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
185 #: RX signal strength (dBm)
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
186 rssi = property(lambda s: -1 * s._data[s.ADDR_SIZE], None)
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
187
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
188 #: Return flag byte
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
189 flags = property(lambda s: s._data[s.ADDR_SIZE + 1], None)
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
190
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
191 #: Payload (list of ords)
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
192 payload = property(lambda s: s._data[s.ADDR_SIZE + 2:], None)
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
193
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
194 #: String version of payload
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
195 def payloadstr(self):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
196 return reduce(lambda a, b: a + chr(b), self.payload, "")
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
197 payloadstr = property(payloadstr, None)
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
198
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
199
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
200 class RX_64_Bit(RX_16_Bit):
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
201 PKT_TYPE = 0x80
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
202 PKT_DESC = "RX Packet: 64 bit address"
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
203 ADDR_SIZE = 8
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
204
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
205 class RXIO_16_Bit(RX_16_Bit):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
206 """RX I/O packet from remote module (16 bit).
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
207
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
208 This is sent when a remote module is configured to send data based on its IO or DAC pins
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
209 """
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
210 PKT_TYPE = 0x83
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
211 PKT_DESC = "RXIO Packet: 16 bit address"
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
212
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
213 nsamples = property(lambda s: s._data[s.ADDR_SIZE + 2])
5
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
214
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
215 mask = property(lambda s: s._data[s.ADDR_SIZE + 3] << 8 | s._data[s.ADDR_SIZE + 4])
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
216
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
217 def __str__(self):
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
218 rtn = "0x%0*x (%ddBm) -> %d samples, mask 0x%04x" % (self.ADDR_SIZE * 2, self.sender,
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
219 self.rssi, self.nsamples, self.mask)
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
220 # Any DIO lines enabled?
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
221 if (self.mask | 0x01ff):
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
222 rtn = rtn + ", DIO - 0x%03x" % (self._data[self.ADDR_SIZE + 5] << 8 |
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
223 self._data[self.ADDR_SIZE + 6])
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
224 offs = self.ADDR_SIZE + 7
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
225 else:
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
226 offs = self.ADDR_SIZE + 5
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
227
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
228 # Any ADC lines enabled?
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
229 if (self.mask | 0x7e00):
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
230 for i in range(6):
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
231 if (self.mask & 1 << (i + 9)):
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
232 rtn = rtn + ", ADC%d - 0x%02x" % (i, self._data[offs] << 8 |
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
233 self._data[offs + 1])
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
234 offs = offs + 2
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
235 return rtn
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
236
5
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
237 class RXIO_64_Bit(RXIO_16_Bit):
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
238 PKT_TYPE = 0x82
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
239 PKT_DESC = "RXIO Packet: 64 bit address"
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
240 ADDR_SIZE = 8
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
241
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
242 class TX_16_Bit(TXPkts):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
243 """Transmit to a 16 bit destination"""
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
244 PKT_TYPE = 0x01
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
245 PKT_DESC = "TX Packet: 16 bit address"
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
246 ADDR_SIZE = 2
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
247 #: Flag to disable ACK
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
248 FLG_DISABLE_ACK = 0x01
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
249 #: Send to broadcast PAN ID
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
250 FLG_BCAST_PANID = 0x04
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
251 #: Maximum size payload we can send
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
252 PKT_MAX_PAYLOAD = 100
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
253
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
254 def __init__(self, *args):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
255 """Takes 0 to 2 arguments. First is the recipient, the second is the payload (string)"""
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
256 self._flags = 0
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
257 self.payload = []
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
258
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
259 if len(args) == 0:
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
260 pass
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
261 if len(args) == 1:
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
262 super(TX_16_Bit, self).__init__()
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
263 self.recipient = args[0]
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
264 elif len(args) == 2:
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
265 super(TX_16_Bit, self).__init__()
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
266 self.recipient = args[0]
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
267 self.payload = args[1]
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
268 else:
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
269 raise TypeError("incorrect number of arguments");
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
270
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
271 def __str__(self):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
272 return "TX_%d_Bit 0x%0*x <- %s" % (self.ADDR_SIZE * 8, self.ADDR_SIZE * 2, self.recipient,
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
273 self.payload)
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
274
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
275 def setrecipient(self, value):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
276 if (value < 0 or value > 2 ** (self.ADDR_SIZE * 8)):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
277 raise ValueError("value out of range must be between 0 and %d" % (2 ** self.ADDR_SIZE))
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
278
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
279 self._recipient = value
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
280
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
281 """Destination address of the packet"""
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
282 recipient = property(lambda s: s._recipient, setrecipient)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
283
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
284 def setflags(self, value):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
285 if (value < 0 or value > 255):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
286 raise ValueError("Value must be between 0 and 255 inclusive")
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
287
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
288 self._flags = value
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
289 flags = property(lambda s: s._flags, setflags)
5
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
290
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
291 def setpayload(self, value):
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
292 self._checklist(value, maxlen = self.PKT_MAX_PAYLOAD)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
293 self._payload = value
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
294 payload = property(lambda s: s._payload, setpayload)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
295
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
296 def payloadstr(self):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
297 return reduce(lambda a, b: a + chr(b), self.payload, "")
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
298 payloadstr = property(payloadstr, None)
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
299
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
300 def getdata(self):
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
301 data = [self.frameid]
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
302 for i, j in zip(reversed(range(self.ADDR_SIZE)), reversed(range(0, self.ADDR_SIZE * 8, 8))):
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
303 data.append((self.recipient & (0xff << j)) >> j)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
304 data.append(self.flags)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
305 data.extend(map(easyord, self.payload))
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
306 return(data)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
307 data = property(getdata)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
308
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
309 class TX_64_Bit(TX_16_Bit):
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
310 PKT_TYPE = 0x00
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
311 PKT_DESC = "TX Packet: 64 bit address"
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
312 ADDR_SIZE = 8
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
313
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
314 class TX_Status(PktBase):
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
315 PKT_TYPE = 0x89
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
316 PKT_DESC = "TX Status"
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
317 statusTxt = ['OK', 'No Ack', 'CCA failure', 'Purged']
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
318 frameid = property(lambda s: s._data[0], None)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
319 status = property(lambda s: s._data[1], None)
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
320 statusMsg = property(lambda s: s.statusTxt[s._data[1]], None)
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
321
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
322 def __init__(self, data = []):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
323 super(TX_Status, self).__init__()
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
324 self._data = data
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
325
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
326 class Packets(object):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
327 """Packet parsing class (misnamed)"""
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
328 PKT_CLASSES = None
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
329
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
330 @classmethod
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
331 def Build(self, data):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
332 """Build a packet from data"""
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
333 if (self.PKT_CLASSES == None):
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
334 m = inspect.getmodule(self)
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
335 # Generate list of objects from their names
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
336 mobjs = map(lambda n: m.__dict__[n], m.__dict__)
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
337 # Find all the classes
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
338 pktclasses = filter(inspect.isclass, mobjs)
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
339 # Find all subclasses of PktBase (but not PktBase itself)
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
340 pktclasses = filter(lambda s: issubclass(s, m.PktBase) and s != m.PktBase, pktclasses)
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
341 self.PKT_CLASSES = pktclasses
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
342
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
343 for p in self.PKT_CLASSES:
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
344 if (p.PKT_TYPE == data[0]):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
345 #print "Matched " + str(p.PKT_TYPE)
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
346 return(p(data[1:]))
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
347
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
348 raise ValueError("Unknown packet type 0x%02x" % (data[0]))
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
349
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
350 @staticmethod
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
351 def Encapsulate(data):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
352 """Encapsulate a packet so it can be sent to the module. Calculates checksum etc.."""
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
353 pktsum = reduce(lambda x, y: x + y, data) & 0xff
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
354 pkt = [0x7e] + [len(data) >> 8] + [len(data) & 0xff] + data + [0xff - pktsum]
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
355 return(map(chr, pkt))
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
356
10
4c91fdfc862e - Further changes to make things cleaner (ie RX packets are "read only" etc).
darius@inchoate.localdomain
parents: 9
diff changeset
357 def __init__(self, s = None):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
358 """Init class, if s is passed in it is used for reading & writing data"""
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
359 #print str(inspect.getmodule(self))
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
360 self.buffer = []
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
361 self.state = 'init'
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
362 self.packets = []
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
363
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
364 self.bufmsb = 0
9
d147529ad2db Switch to only reading RX pkts and writing TX pkts to make things simpler.
darius@inchoate.localdomain
parents: 8
diff changeset
365 self._dataleft = 0
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
366
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
367 self.fr_err = 0 # Framing error
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
368 self.ck_err = 0 # Checksum error
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
369 self.rx_cnt = 0 # Packet count
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
370
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
371 self.pktq = []
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
372 self.s = s # Output handle for convenience methods
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
373
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
374 def writedata(self, data):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
375 """Convenience method to write data"""
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
376 self.s.write("".join(map(str, data)))
5
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
377
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
378 def getdata(self):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
379 """Read data until nothing is available (assumes non-blocking) and process it"""
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
380 l = []
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
381 while 1:
6
9c499d923544 Many fixes.
darius@inchoate.localdomain
parents: 5
diff changeset
382 a = self.s.read()
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
383 if a == '':
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
384 break
5
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
385 l.append(ord(a))
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
386
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
387 return self.process(l)
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
388
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
389 def processstr(self, data):
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
390 """Process a string of data"""
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
391 return self.process(map(ord, data))
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
392
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
393 def process(self, data):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
394 """Process (ordinal) data through the state machine.
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
395
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
396 Returns the number of packets in the queue when finished. Updates
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
397 various internal counters too.
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
398 """
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
399 pktcount = 0
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
400 for d in data:
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
401 if (self.state == 'init'):
5
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
402 if (d != 0x7e):
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
403 print "Framing error, got 0x%02x, expected 0x7e" % d
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
404 self.fr_err += 1
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
405 continue
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
406
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
407 self.state = 'sizemsb'
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
408 elif (self.state == 'sizemsb'):
5
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
409 self.bufmsb = d
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
410 self.state = 'sizelsb'
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
411 elif (self.state == 'sizelsb'):
7
579dedf5a1f1 Rejoin line break, left over from removal of struct.
darius@inchoate.localdomain
parents: 6
diff changeset
412 self.dataleft = self.bufmsb << 8 | d
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
413 self.state = 'data'
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
414 elif (self.state == 'data'):
5
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
415 self.buffer.append(d)
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
416 self.dataleft = self.dataleft - 1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
417 if (self.dataleft == 0):
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
418 self.state = 'cksum'
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
419 elif (self.state == 'cksum'):
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
420 pktsum = reduce(lambda x, y: x + y, self.buffer) & 0xff
5
5d5963d542bc More tidyups & fixes.
darius@inchoate.localdomain
parents: 4
diff changeset
421 rxcksum = d
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
422 self.state = 'init'
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
423 if (pktsum + rxcksum != 0xff):
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
424 self.buffer = []
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
425 self.ck_err += 1
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
426 print "Checksum error, got 0x%02x, expected 0x%02x" % \
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
427 (rxcksum, 0xff - pktsum)
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
428 else:
11
75f785a09e2e Add license.
darius@Inchoate
parents: 10
diff changeset
429 #print "Got a packet - " + str(self.buffer)
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
430 p = Packets.Build(self.buffer)
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
431 self.pktq.append(p)
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
432 self.buffer = []
4
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
433 pktcount += 1
ed7abe6f59c2 Many fixes (again)
darius@inchoate.localdomain
parents: 3
diff changeset
434 self.rx_cnt += 1
1
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
435 else:
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
436 print "Invalid state %s! Resetting" % (self.state)
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
437 self.state = 'init'
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
438
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
439 return pktcount
b5d8ec0ffd21 Lots of changes..
darius@inchoate.localdomain
parents: 0
diff changeset
440