annotate server/ts.py @ 332:05c1249da994

- Move crc16 to utils and fix it - Fix main.c crc calculation
author Matt Johnston <matt@ucc.asn.au>
date Thu, 07 Jun 2012 20:26:50 +0800
parents 5de3fc71ce48
children dbbd503119ba
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
327
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1 #!/usr/bin/env python2.7
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
3 BTADDR = "00:12:03:27:70:88"
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
4 SLEEP_TIME = 180
329
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
5 # time that the bluetooth takes to get going?
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
6 EXTRA_WAKEUP = 0
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
7
330
7ac6b8846eea - some fixes for server code
Matt Johnston <matt@ucc.asn.au>
parents: 329
diff changeset
8 FETCH_TRIES = 3
7ac6b8846eea - some fixes for server code
Matt Johnston <matt@ucc.asn.au>
parents: 329
diff changeset
9
329
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
10 # avoid turning off the bluetooth etc.
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
11 TESTING = True
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
12
327
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
13 import sys
331
5de3fc71ce48 - Make the python work on openwrt
Matt Johnston <matt@ucc.asn.au>
parents: 330
diff changeset
14 #import httplib
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
15 import time
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
16 import traceback
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
17
332
05c1249da994 - Move crc16 to utils and fix it
Matt Johnston <matt@ucc.asn.au>
parents: 331
diff changeset
18 from utils import monotonic_time, retry, readline, crc16
327
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
19
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
20 lightblue = None
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
21 try:
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
22 import lightblue
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
23 except ImportError:
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
24 import bluetooth
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
25
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
26 def get_socket(addr):
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
27 if lightblue:
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
28 s = lightblue.socket()
329
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
29 s.connect((addr, 1))
330
7ac6b8846eea - some fixes for server code
Matt Johnston <matt@ucc.asn.au>
parents: 329
diff changeset
30 s.settimeout(3)
327
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
31 else:
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
32 s = bluetooth.BluetoothSocket( bluetooth.RFCOMM )
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
33 s.connect((addr, 1))
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
34
330
7ac6b8846eea - some fixes for server code
Matt Johnston <matt@ucc.asn.au>
parents: 329
diff changeset
35 s.setblocking(False)
7ac6b8846eea - some fixes for server code
Matt Johnston <matt@ucc.asn.au>
parents: 329
diff changeset
36
327
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
37 return s
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
38
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
39
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
40 @retry()
327
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
41 def fetch(sock):
330
7ac6b8846eea - some fixes for server code
Matt Johnston <matt@ucc.asn.au>
parents: 329
diff changeset
42 print "fetch"
327
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
43 sock.send("fetch\n")
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
44
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
45 crc = 0
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
46
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
47 lines = []
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
48 l = readline(sock)
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
49 if l != 'START\n':
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
50 print>>sys.stderr, "Bad expected START line '%s'\n" % l.rstrip('\n')
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
51 return None
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
52 crc = crc16(l, crc)
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
53 lines.append(l)
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
54
330
7ac6b8846eea - some fixes for server code
Matt Johnston <matt@ucc.asn.au>
parents: 329
diff changeset
55 while True:
327
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
56 l = readline(sock)
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
57
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
58 crc = crc16(l, crc)
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
59
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
60 if l == 'END\n':
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
61 break
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
62
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
63 lines.append(l)
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
64
330
7ac6b8846eea - some fixes for server code
Matt Johnston <matt@ucc.asn.au>
parents: 329
diff changeset
65 print lines
7ac6b8846eea - some fixes for server code
Matt Johnston <matt@ucc.asn.au>
parents: 329
diff changeset
66
327
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
67 l = readline(sock)
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
68 recv_crc = None
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
69 try:
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
70 k, v = l.rstrip('\n').split('=')
331
5de3fc71ce48 - Make the python work on openwrt
Matt Johnston <matt@ucc.asn.au>
parents: 330
diff changeset
71 print k,v
327
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
72 if k == 'CRC':
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
73 recv_crc = int(v)
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
74 if recv_crc < 0 or recv_crc > 0xffff:
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
75 recv_crc = None
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
76 except ValueError:
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
77 pass
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
78
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
79 if recv_crc is None:
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
80 print>>sys.stderr, "Bad expected CRC line '%s'\n" % l.rstrip('\n')
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
81 return None
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
82
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
83 if recv_crc != crc:
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
84 print>>sys.stderr, "Bad CRC: calculated 0x%x vs received 0x%x\n" % (crc, recv_crc)
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
85 return None
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
86
5639c74f2cbb untested simple server proxy code
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
87 return ''.join(lines)
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
88
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
89 @retry()
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
90 def turn_off(sock):
329
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
91 if TESTING:
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
92 return None
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
93 sock.send("btoff\n");
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
94 # read newline
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
95 l = readline(sock)
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
96 if not l:
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
97 print>>sys.stderr, "Bad response to btoff\n"
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
98 return None
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
99
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
100 off, next_wake = l.rstrip().split(':')
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
101 if off != 'Off':
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
102 print>>sys.stderr, "Bad response to btoff '%s'\n" % l
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
103
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
104 return int(next_wake)
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
105
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
106 def do_comms(sock):
331
5de3fc71ce48 - Make the python work on openwrt
Matt Johnston <matt@ucc.asn.au>
parents: 330
diff changeset
107 print "do_comms"
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
108 d = None
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
109 # serial could be unreliable, try a few times
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
110 for i in range(FETCH_TRIES):
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
111 d = fetch(sock)
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
112 if d:
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
113 break
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
114 time.sleep(1)
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
115 if not d:
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
116 return
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
117
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
118 res = send_results()
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
119 if not res:
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
120 return
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
121
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
122 clear_meas(sock)
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
123
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
124 next_wake = turn_off(sock)
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
125 sock.close()
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
126 return next_wake
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
127
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
128 testcount = 0
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
129
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
130 def sleep_for(secs):
329
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
131 until = monotonic_time() + secs
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
132 while True:
330
7ac6b8846eea - some fixes for server code
Matt Johnston <matt@ucc.asn.au>
parents: 329
diff changeset
133 length = until - monotonic_time()
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
134 if length <= 0:
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
135 return
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
136 time.sleep(length)
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
137
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
138 def main():
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
139
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
140 while True:
329
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
141 sock = None
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
142 try:
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
143 sock = get_socket(BTADDR)
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
144 except Exception, e:
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
145 print>>sys.stderr, "Error connecting:"
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
146 traceback.print_exc(file=sys.stderr)
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
147 sleep_time = SLEEP_TIME
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
148 if sock:
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
149 next_wake = None
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
150 try:
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
151 next_wake = do_comms(sock)
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
152 except Exception, e:
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
153 print>>sys.stderr, "Error in do_comms:"
329
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
154 traceback.print_exc(file=sys.stderr)
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
155 if next_wake:
329
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
156 sleep_time = min(next_wake+EXTRA_WAKEUP, sleep_time)
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
157
329
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
158 if TESTING:
740438e21ea0 Fix bugs in server code (try actually running it)
Matt Johnston <matt@ucc.asn.au>
parents: 328
diff changeset
159 print "Sleeping for %d" % sleep_time
328
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
160 sleep_for(sleep_time)
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
161
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
162 if __name__ == '__main__':
46070aaf29ea A bit of work on the server python
Matt Johnston <matt@ucc.asn.au>
parents: 327
diff changeset
163 main()