view iec1107.py @ 0:fd8520d969c4

Initial commit, only readmeter function works
author Daniel O'Connor <darius@dons.net.au>
date Wed, 20 Nov 2013 10:16:37 +1030
parents
children 99f25c8ab92f
line wrap: on
line source

#!/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 --