Mercurial > ~darius > hgwebdir.cgi > iec1107
comparison iec1107.py @ 1:99f25c8ab92f
Make class version actually work, remove procedure.
Rename as it doesn't get continuous results, just one shot.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Wed, 20 Nov 2013 12:46:59 +1030 |
parents | fd8520d969c4 |
children | 8f1a773a3cd5 |
comparison
equal
deleted
inserted
replaced
0:fd8520d969c4 | 1:99f25c8ab92f |
---|---|
12 baudtable = {'0' : 300, '1' : 600, '2' : 1200, '3' : 2400, '4' : 4800, '5' : 9600, '6' : 19200} | 12 baudtable = {'0' : 300, '1' : 600, '2' : 1200, '3' : 2400, '4' : 4800, '5' : 9600, '6' : 19200} |
13 | 13 |
14 class Error(exceptions.BaseException): | 14 class Error(exceptions.BaseException): |
15 pass | 15 pass |
16 | 16 |
17 def readmeter(portname): | 17 class IEC1107Reading(object): |
18 s = serial.Serial(portname, baudrate = 300, bytesize = 7, parity = 'E', stopbits = 1) | 18 def __init__(self, port, force300bps = True): |
19 s.timeout = 1.5 | |
20 | |
21 # Send ident message | |
22 s.write('/?!\r\n') | |
23 | |
24 rtn = s.readline() | |
25 if len(rtn) < 6 or rtn[0] != '/' or rtn[-1] != '\n' or rtn[-2] != '\r': | |
26 raise Error('Invalid line "%s"' % (rtn)) | |
27 | |
28 # ACK meter and ask for data | |
29 s.write('\x06000\x0d\x0a') | |
30 s.timeout = 2 | |
31 | |
32 lines = [] | |
33 cksum = 0 | |
34 | |
35 line = s.readline() | |
36 if len(line) == 0 or line[0] != '\x02': | |
37 raise Error('No reply to query or invalid reply \"%s\"' % (line)) | |
38 else: | |
39 cksum ^= reduce(lambda x, y: x ^ y, map(ord, line[1:])) | |
40 lines.append(line[1:].strip()) | |
41 while True: | |
42 line = s.readline() | |
43 cksum ^= reduce(lambda x, y: x ^ y, map(ord, line)) | |
44 line = line.strip() | |
45 if len(line) == 0: | |
46 raise Error('Timeout during message') | |
47 if line == '!': | |
48 break | |
49 lines.append(line) | |
50 fin = s.read(2) | |
51 if len(fin) != 2: | |
52 raise Error('Timeout reading trailer') | |
53 if fin[0] != '\x03': | |
54 raise Error('Trailer malformed, expected 0x03, got 0x%02x' % (ord(fin[0]))) | |
55 | |
56 cksum ^= ord(fin[0]) | |
57 if cksum != ord(fin[1]): | |
58 raise Error('Checksum mismatch, expected 0x%02x, got 0x%02x' % (cksum, ord(fin[1]))) | |
59 return lines | |
60 | |
61 | |
62 class IEC1107(object): | |
63 def __init__(self, port): | |
64 # Open port | 19 # Open port |
65 self.s = serial.Serial(port, baudrate=300, bytesize=7, parity='E', stopbits=1) | 20 s = serial.Serial(port, baudrate = 300, bytesize = 7, parity = 'E', stopbits = 1) |
66 self.s.timeout = 0.2 | 21 s.timeout = 2.5 |
67 | 22 |
68 # Send ident message | 23 # Send ident message |
69 self.s.write('/?!\r\n') | 24 s.write('/?!\r\n') |
70 self.s.flush() | 25 rtn = s.readline() |
71 rtn = self.s.readline() | 26 if len(rtn) == 0: |
27 raise Error('No reply to probe') | |
72 if len(rtn) < 6 or rtn[0] != '/' or rtn[-1] != '\n' or rtn[-2] != '\r': | 28 if len(rtn) < 6 or rtn[0] != '/' or rtn[-1] != '\n' or rtn[-2] != '\r': |
73 raise Error('Invalid line "%s"' % (rtn)) | 29 raise Error('Invalid line "%s"' % (rtn)) |
30 | |
74 rtn = rtn.strip() | 31 rtn = rtn.strip() |
75 self.mfg = rtn[1:4] | 32 self.mfg = rtn[1:4] |
76 | 33 |
77 if self.mfg[2].isupper(): | 34 if self.mfg[2].isupper(): |
78 self.restime = 0.2 | 35 self.restime = 0.2 |
79 else: | 36 else: |
80 self.restime = 0.02 | 37 self.restime = 0.02 |
81 | 38 |
82 #self.baudid = rtn[4] | 39 if force300bps: |
83 self.baudid = '0' | 40 self.baudid = '0' |
41 else: | |
42 self.baudid = rtn[4] | |
84 if self.baudid not in baudtable: | 43 if self.baudid not in baudtable: |
85 raise Error('Invalid baud rate %c from "%s"' % (selfbaudid, rtn)) | 44 raise Error('Invalid baud rate %c from "%s"' % (selfbaudid, rtn)) |
86 else: | 45 else: |
87 self.baud = baudtable[self.baudid] | 46 self.baud = baudtable[self.baudid] |
88 | 47 |
97 # Byte Meaning | 56 # Byte Meaning |
98 # 0 ACK (0x06) | 57 # 0 ACK (0x06) |
99 # 1 Protocol character ('0' = normal, '1' = secondary, '2' = HDLC protocol) | 58 # 1 Protocol character ('0' = normal, '1' = secondary, '2' = HDLC protocol) |
100 # 2 Baud rate ID ('0', '1', etc) | 59 # 2 Baud rate ID ('0', '1', etc) |
101 # 3 Mode control('0' = read data, '1' = device prog) | 60 # 3 Mode control('0' = read data, '1' = device prog) |
102 self.s.write('\x060%c0\x0d\x0a' % (self.baudid)) | 61 s.write('\x060%c0\r\n' % (self.baudid)) |
103 self.s.flush() | |
104 | 62 |
105 time.sleep(self.restime) | 63 time.sleep(self.restime) |
106 self.s.setBaudrate(self.baud) | 64 s.setBaudrate(self.baud) |
107 | 65 |
108 self.s.timeout = 1 | 66 lines = [] |
67 cksum = 0 | |
109 | 68 |
110 def getdata(self): | 69 # Read STX |
111 self.dat = '' | 70 head = s.read(1) |
112 while len(self.dat) == 0: | 71 if len(head) == 0: |
113 data = self.s.read(1000) | 72 raise Error('No reply to query') |
114 self.dat += data | 73 if head != '\x02': |
74 raise Error('Invalid reply header 0x%02x' % (ord(head))) | |
75 | |
76 # Read result lines | |
77 while True: | |
78 line = s.readline() | |
79 cksum ^= reduce(lambda x, y: x ^ y, map(ord, line)) | |
80 line = line.strip() | |
81 if len(line) == 0: | |
82 raise Error('Timeout during message') | |
83 if line == '!': | |
84 break | |
85 lines.append(line) | |
115 | 86 |
116 cksum = reduce(lambda x, y: x ^ y, map(ord,self.dat[1:-1])) | 87 # Read trailer |
117 if cksum != ord(self.dat[-1]): | 88 fin = s.read(2) |
118 raise Error('checksum mismatch, epected 0x%02x got 0x%02x' % (cksum, ord(self.dat[-1]))) | 89 if len(fin) != 2: |
119 return self.dat | 90 raise Error('Timeout reading trailer') |
120 | 91 if fin[0] != '\x03': |
92 raise Error('Trailer malformed, expected 0x03, got 0x%02x' % (ord(fin[0]))) | |
93 | |
94 # Validate checksum | |
95 cksum ^= ord(fin[0]) | |
96 if cksum != ord(fin[1]): | |
97 raise Error('Checksum mismatch, expected 0x%02x, got 0x%02x' % (cksum, ord(fin[1]))) | |
98 self.reading = lines | |
99 del s | |
100 | |
121 def main(): | 101 def main(): |
122 d = IEC1107('/dev/cu.usbserial-AM01Z7UC') | 102 if len(sys.argv) != 2: |
103 print 'Bad usage' | |
104 print '\t%s portname' % (sys.argv[0]) | |
105 sys.exit(1) | |
106 | |
107 res = IEC1107Reading(sys.argv[1]) | |
108 print res.reading | |
123 | 109 |
124 if __name__ == '__main__': | 110 if __name__ == '__main__': |
125 main() | 111 main() |
126 | |
127 s = '\x02C.1(12880041.0(22:25 18-11-13)\r\n1.8.1(0000000597*Wh)\r\n1.8.2(0000000000*Wh)\r\n1.8.3(0000264238*Wh)\r\n1.8.0(0000264835*Wh)\r\n2.8.0(0000511354*Wh)\r\n!\r\n\x03{' | |
128 | |
129 | 112 |
130 # Meter number is 1288004 | 113 # Meter number is 1288004 |
131 # 1.8.0 is import | 114 # 1.8.0 is import |
132 # 1.8.1 is ?? | 115 # 1.8.1 is ?? |
133 # 1.8.2 is ?? | 116 # 1.8.2 is ?? |