Toggle Navigation
Hatchery
Eggs
Kamstrup
__init__.py
Users
Badges
Login
Register
MCH2022 badge?
go to mch2022.badge.team
__init__.py
raw
Content
# Borrowed most of the code from https://github.com/bsdphk/PyKamstrup #!/usr/local/bin/python # # ---------------------------------------------------------------------------- # "THE BEER-WARE LICENSE" (Revision 42): # <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you # can do whatever you want with this stuff. If we meet some day, and you think # this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp # ---------------------------------------------------------------------------- # #from __future__ import print_function # You need pySerial import math import badge import ugfx import easydraw ugfx.init() ugfx.clear( ugfx.BLACK ) ugfx.flush() ugfx.clear( ugfx.WHITE ) ugfx.flush() #uart = UART(2, 1200) #uart.init(1200, bits=8, parity=None, stop=1, tx=33, rx=16) from machine import UART irpoort = UART(2, 1200) irpoort.init(1200, bits=8, parity=None, stop=2, tx=33, rx=16) ####################################################################### # These are the variables I have managed to identify # Submissions welcome. kamstrup_382_var = { 0x0001: "Energy in", 0x0002: "Energy out", 0x000d: "Energy in hi-res", 0x000e: "Energy out hi-res", 0x041e: "Voltage p1", 0x041f: "Voltage p2", 0x0420: "Voltage p3", 0x0434: "Current p1", 0x0435: "Current p2", 0x0436: "Current p3", 0x03ff: "Power In", 0x0438: "Power p1 In", 0x0439: "Power p2 In", 0x043a: "Power p3 In", 0x0400: "Power In", 0x0540: "Power p1 Out", 0x0541: "Power p2 Out", 0x0542: "Power p3 Out", } kamstrup_681_var = { 1: "Date", 60: "Heat", 61: "x", 62: "x", 63: "x", 95: "x", 96: "x", 97: "x", } kamstrup_MC601_var = { 0x003C: "Energy register 1: Heat energy", 0x0044: "Volume register V1", 0x0058: "Current temperature T3", 0x03EC: "Operation hours counter", } #Command overview # 0x01 - GetType # 0x02 - GetSerialNo # 0x09 - SetClock # 0x10 - GetRegister # # Special for the Multical 601/602 maybe: # 0xA0 - GetLogTimePresent # 0xA1 - GetLogLastPresent # 0xA2 - GetLogIDPresent # 0xA3 - GetLogTimePast # 0x9B - GetEventStatus # 0x9C - ClearEventStatus # 0x11 - PutRegister # Time is formatted as a 32bit binary value # Time 16:15:57 = 161557d = 0x027715 # GetRegister (0x10) # max of 8 registers in 1 request # 0x80 [destination adress] # 0x10 [number of registers] [register 1 id] [register 2 id] .. [CRC] 0x0D # Register ID's are 16bit register identification codes kamstrup_MC602_var = { 1003: "Current date (YYMMDD)", 60: "Energy Register 1: Heat energy", 94: "Energy Register 2: Control energy", 63: "Energy Register 3: Cooling energy", 61: "Energy Register 4: Inlet energy (forwarded energy)", 62: "Energy Register 5: Outlet energy (returned energy)", 95: "Energy Register 6: Tap water energy", 96: "Energy Register 7: Heat energy Y", 97: "Energy Register 8: [m^3 x T1]", 110: "Energy Register 9: [m^3 x T2]", 64: "Tariff register 2", 65: "Tariff register 3", 68: "Volume register V1", 69: "Volume register V2", 84: "Input register VA", 85: "Input register VB", 72: "Mass register V1", 73: "Mass register V2", 1004: "Operational hour counter", 113: "Info-event counter", 1002: "Current time (HHMMSS)", 99: "Infocode register, current", 86: "Current inlet temperature (T1)", 87: "Current outlet temperature (T2)", 88: "Current temperature T3", 122: "Current temperature T4", 89: "Current temperature difference (T1-T2)", 91: "Pressure in inlet (P1)", 92: "Pressure in outlet (P2)", 74: "Current flow in inlet pipe", 75: "Current flow in outlet pipe", 80: "Current power calculated on basis of V1-T1-T2", 123: "Date for max flow this year", 124: "Max flow this year", 125: "Date for min flow this year", 126: "Min flow this year", 127: "Date for max power (effect) this year", 128: "Max power (effect) this year", 129: "Date for min power (effect) this year", 130: "Min power (effect) this year", 138: "Date for max flow this month", 139: "Max flow this month", 140: "Date for min flow this month", 141: "Min flow this month", 142: "Date for max power (effect) this month", 143: "Max power (effect) this month", 144: "Date for min power (effect) this month", 145: "Min power (effect) this month", 146: "Year-to-date average for T1", 147: "Year-to-date average for T2", 149: "Month-to-date average for T1", 150: "Month-to-date average for T2", 66: "Tariff limit 2", 67: "Tariff limit 3", 98: "Target date (reading date)", 152: "Program no. ABCCCCCC", 153: "Config no. DDDEE", 168: "Config no. FFGGMN", 1001: "Serial no.", 112: "Customer number (8 most important digits)", 1010: "Customer number (8 less important digits)", 114: "Meter number for VA", 104: "Meter number for VB", 1005: "Software edition (Meter type)", 154: "Software check sum", 155: "High resolution energy register for testing", 157: "ID number for top module", 158: "ID number for bottom module", 175: "Error hour counter", 234: "l/imp. for VA", 235: "l/imp. for VB", } ####################################################################### # Units, provided by Erik Jensen units = { 0: '', 1: 'Wh', 2: 'kWh', 3: 'MWh', 4: 'GWh', 5: 'j', 6: 'kj', 7: 'Mj', 8: 'Gj', 9: 'Cal', 10: 'kCal', 11: 'Mcal', 12: 'Gcal', 13: 'varh', 14: 'kvarh', 15: 'Mvarh', 16: 'Gvarh', 17: 'VAh', 18: 'kVAh', 19: 'MVAh', 20: 'GVAh', 21: 'kW', 22: 'kW', 23: 'MW', 24: 'GW', 25: 'kvar', 26: 'kvar', 27: 'Mvar', 28: 'Gvar', 29: 'VA', 30: 'kVA', 31: 'MVA', 32: 'GVA', 33: 'V', 34: 'A', 35: 'kV',36: 'kA', 37: 'C', 38: 'K', 39: 'l', 40: 'm3', 41: 'l/h', 42: 'm3/h', 43: 'm3xC', 44: 'ton', 45: 'ton/h', 46: 'h', 47: 'hh:mm:ss', 48: 'yy:mm:dd', 49: 'yyyy:mm:dd', 50: 'mm:dd', 51: '', 52: 'bar', 53: 'RTC', 54: 'ASCII', 55: 'm3 x 10', 56: 'ton x 10', 57: 'GJ x 10', 58: 'minutes', 59: 'Bitfield', 60: 's', 61: 'ms', 62: 'days', 63: 'RTC-Q', 64: 'Datetime' } ####################################################################### # Kamstrup uses the "true" CCITT CRC-16 # def crc_1021(message): poly = 0x1021 reg = 0x0000 for byte in message: mask = 0x80 while(mask > 0): reg<<=1 if byte & mask: reg |= 1 mask>>=1 if reg & 0x10000: reg &= 0xffff reg ^= poly return reg ####################################################################### # Byte values which must be escaped before transmission # escapes = { 0x06: True, 0x0d: True, 0x1b: True, 0x40: True, 0x80: True, } ####################################################################### # And here we go.... # class kamstrup(object): # def __init__(self): # print("init") def wr(self, b): b = bytearray(b) irpoort.write(b) a = irpoort.read(1) def rd(self): a = irpoort.read(1) if len(a) == 0: return None b = bytearray(a)[0] return b def send(self, pfx, msg): b = bytearray(msg) b.append(0) b.append(0) c = crc_1021(b) b[-2] = c >> 8 b[-1] = c & 0xff c = bytearray() c.append(pfx) for i in b: if i in escapes: c.append(0x1b) c.append(i ^ 0xff) else: c.append(i) c.append(0x0d) self.wr(c) def recv(self): b = bytearray() while True: d = self.rd() if d == None: return None if d == 0x40: b = bytearray() b.append(d) if d == 0x0d: break c = bytearray() i = 1; while i < len(b) - 1: if b[i] == 0x1b: v = b[i + 1] ^ 0xff if v not in escapes: print("Missing Escape %02x" % v) c.append(v) i += 2 else: c.append(b[i]) i += 1 if crc_1021(c): print("CRC error") return c[:-2] def readvar(self, nbr): # I wouldn't be surprised if you can ask for more than # one variable at the time, given that the length is # encoded in the response. Havn't tried. self.send(0x80, (0x3f, 0x10, 0x01, nbr >> 8, nbr & 0xff)) b = self.recv() if b == None: return (None, None) if b[0] != 0x3f or b[1] != 0x10: return (None, None) if b[2] != nbr >> 8 or b[3] != nbr & 0xff: return (None, None) if b[4] in units: u = units[b[4]] else: u = None # Decode the mantissa x = 0 for i in range(0,b[5]): x <<= 8 x |= b[i + 7] # Decode the exponent i = b[6] & 0x3f if b[6] & 0x40: i = -i i = math.pow(10,i) if b[6] & 0x80: i = -i x *= i if False: # Debug print s = "" for i in b[:4]: s += " %02x" % i s += " |" for i in b[4:7]: s += " %02x" % i s += " |" for i in b[7:]: s += " %02x" % i print(s, "=", x, units[b[4]]) return (x, u) import time foo = kamstrup() for i in kamstrup_MC602_var: x,u = foo.readvar(i) print("%-50s" % kamstrup_MC602_var[i], x, u) easydraw.msg(kamstrup_MC602_var[i] + ' ' + str(x) + ' ' + str(u), title="Still Kamstrup Anyway")