# HG changeset patch # User Daniel O'Connor # Date 1384904797 -37800 # Node ID fd8520d969c403e9286c1afa6dcaf82b209e3ec5 Initial commit, only readmeter function works diff -r 000000000000 -r fd8520d969c4 iec1107.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iec1107.py Wed Nov 20 10:16:37 2013 +1030 @@ -0,0 +1,156 @@ +#!/usr/bin/env python + +# +# http://www.domoticaforum.eu/viewtopic.php?f=71&t=7489 +# + +import exceptions +import serial +import sys +import time + +baudtable = {'0' : 300, '1' : 600, '2' : 1200, '3' : 2400, '4' : 4800, '5' : 9600, '6' : 19200} + +class Error(exceptions.BaseException): + pass + +def readmeter(portname): + s = serial.Serial(portname, baudrate = 300, bytesize = 7, parity = 'E', stopbits = 1) + s.timeout = 1.5 + + # Send ident message + s.write('/?!\r\n') + + rtn = s.readline() + if len(rtn) < 6 or rtn[0] != '/' or rtn[-1] != '\n' or rtn[-2] != '\r': + raise Error('Invalid line "%s"' % (rtn)) + + # ACK meter and ask for data + s.write('\x06000\x0d\x0a') + s.timeout = 2 + + lines = [] + cksum = 0 + + line = s.readline() + if len(line) == 0 or line[0] != '\x02': + raise Error('No reply to query or invalid reply \"%s\"' % (line)) + else: + cksum ^= reduce(lambda x, y: x ^ y, map(ord, line[1:])) + lines.append(line[1:].strip()) + while True: + line = s.readline() + cksum ^= reduce(lambda x, y: x ^ y, map(ord, line)) + line = line.strip() + if len(line) == 0: + raise Error('Timeout during message') + if line == '!': + break + lines.append(line) + fin = s.read(2) + if len(fin) != 2: + raise Error('Timeout reading trailer') + if fin[0] != '\x03': + raise Error('Trailer malformed, expected 0x03, got 0x%02x' % (ord(fin[0]))) + + cksum ^= ord(fin[0]) + if cksum != ord(fin[1]): + raise Error('Checksum mismatch, expected 0x%02x, got 0x%02x' % (cksum, ord(fin[1]))) + return lines + + +class IEC1107(object): + def __init__(self, port): + # Open port + self.s = serial.Serial(port, baudrate=300, bytesize=7, parity='E', stopbits=1) + self.s.timeout = 0.2 + + # Send ident message + self.s.write('/?!\r\n') + self.s.flush() + rtn = self.s.readline() + if len(rtn) < 6 or rtn[0] != '/' or rtn[-1] != '\n' or rtn[-2] != '\r': + raise Error('Invalid line "%s"' % (rtn)) + rtn = rtn.strip() + self.mfg = rtn[1:4] + + if self.mfg[2].isupper(): + self.restime = 0.2 + else: + self.restime = 0.02 + + #self.baudid = rtn[4] + self.baudid = '0' + if self.baudid not in baudtable: + raise Error('Invalid baud rate %c from "%s"' % (selfbaudid, rtn)) + else: + self.baud = baudtable[self.baudid] + + if rtn[5] == '/': + self.mode = rtn[6] + self.mfg = rtn[7:] + else: + self.mode = None + self.mfg = rtn[5:] + + # Send ACK/option message + # Byte Meaning + # 0 ACK (0x06) + # 1 Protocol character ('0' = normal, '1' = secondary, '2' = HDLC protocol) + # 2 Baud rate ID ('0', '1', etc) + # 3 Mode control('0' = read data, '1' = device prog) + self.s.write('\x060%c0\x0d\x0a' % (self.baudid)) + self.s.flush() + + time.sleep(self.restime) + self.s.setBaudrate(self.baud) + + self.s.timeout = 1 + + def getdata(self): + self.dat = '' + while len(self.dat) == 0: + data = self.s.read(1000) + self.dat += data + + cksum = reduce(lambda x, y: x ^ y, map(ord,self.dat[1:-1])) + if cksum != ord(self.dat[-1]): + raise Error('checksum mismatch, epected 0x%02x got 0x%02x' % (cksum, ord(self.dat[-1]))) + return self.dat + +def main(): + d = IEC1107('/dev/cu.usbserial-AM01Z7UC') + +if __name__ == '__main__': + main() + +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{' + + +# Meter number is 1288004 +# 1.8.0 is import +# 1.8.1 is ?? +# 1.8.2 is ?? +# 1.8.3 is ?? +# 2.8.0 is export + +# C.1(12880041.0(22:25 18-11-13) +# 1.8.1(0000000597*Wh) +# 1.8.2(0000000000*Wh) +# 1.8.3(0000264238*Wh) +# 1.8.0(0000264835*Wh) +# 2.8.0(0000511354*Wh) + +# ==> /?!<0D><0A> +# <== /ACE5SMLCD +# ==> <06>050<0D><0A> +# <== -- STX -- +# <== C.1(12880041.0(22:48 18-11-13) +# <== 1.8.1(0000000597*Wh) +# <== 1.8.2(0000000000*Wh) +# <== 1.8.3(0000264460*Wh) +# <== 1.8.0(0000265057*Wh) +# <== 2.8.0(0000511354*Wh) +# <== ! +# <== -- ETX -- +# <== -- BCC --