#!/usr/bin/python # Python code to read values from Smart Meter via SML (smart message language) # created: Alexander Kabza, Mar 1, 2016 # last mod: Alexander Kabza, 2020-03-01 # For documentation and further information see http://www.kabza.de/MyHome/SmartMeter/SmartMeter.html import sys import serial import time import datetime import numpy as np def writexml(t, E, E_feed, P): file = open('/var/www/html/SmartMeter.xml', 'w') file.write('' + '' + '' + '' + '' + '') file.close() def writexml15(t, Start, Size, Pmin, Pave, Pmax, Pstddev): file = open('/var/www/html/SmartMeter15.xml', 'w') file.write('' + '' + '' + '' + '' + '' + '' + '' + '') file.close() def hex_to_int(hex): i = int(hex, 16) if i & 0x80000000: # MSB set -> neg. return -((~i & 0xffffffff) + 1) else: return i port = serial.Serial( port='/dev/ttyAMA0', baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS ) #port.open(); start = '1b1b1b1b01010101' end = '1b1b1b1b1a' data = '' a = np.empty(0, dtype=float) now = datetime.datetime.now() starttimestamp = (now.strftime("%Y-%m-%d ") + now.strftime("%H:%M:%S")) prevminute = 321 while True: char = port.read() data = data + char.encode('HEX') pos = data.find(end) if (pos <> -1): for x in range(0, 3): # read three more byte after end of SML message (checksum etc) char = port.read() data = data + char.encode('HEX') now = datetime.datetime.now() timestamp = (now.strftime("%Y-%m-%d ") + now.strftime("%H:%M:%S")) result = timestamp #ExtendedOutput(data) search = '77078181c78203ff0101010104' pos = data.find(search) if (pos <> -1): pos = pos + len(search) value = data[pos:pos + 6] print 'Hersteller-ID: ' + search + ': ' + value + ' = ' + value.decode('HEX') search = '77070100000009ff010101010b' pos = data.find(search) if (pos <> -1): pos = pos + len(search) value = data[pos:pos + 20] print 'Server-ID: ' + search + ': ' + value energy = 0 search = '77070100010800ff64' pos = data.find(search) if (pos <> -1): pos = pos + len(search) + 18 # skip 9 Bytes which may be different value = data[pos:pos + 16] try: energy = float(int(value, 16)) / 10 except: energy = 0.0 print 'Total Bezug: ' + search + ': ' + value + ' = ' + str(energy/1e6) + ' kWh' result = result + ";" + str(energy) energy_feed = 0 search = '77070100020800ff64' pos = data.find(search) if (pos <> -1): pos = pos + len(search) + 18 # skip 9 Bytes which may be different value = data[pos:pos + 16] try: energy_feed = float(int(value, 16)) / 10 except: energy_feed = 0.0 print 'Total Lieferung: ' + search + ': ' + value + ' = ' + str(energy_feed/1e6) + ' kWh' result = result + ";" + str(energy_feed) power = 0 search = '77070100100700ff0101621b52fe59' pos = data.find(search) if (pos <> -1): pos = pos + len(search) value = data[pos:pos + 16] try: power = float(hex_to_int(value)) / 100 except: power = 0.0 print 'Leistung: ' + search + ': ' + value + ' = ' + str(power) + ' W' result = result + ";" + str(power) a = np.append(a, power) now = datetime.datetime.now() currentminute = now.minute if (currentminute % 15 == 0) and (prevminute <> currentminute): prevminute = currentminute writexml15(timestamp, starttimestamp, a.size, np.amin(a), np.average(a), np.amax(a), np.std(a)) a = np.empty(0, dtype=float) now = datetime.datetime.now() starttimestamp = (now.strftime("%Y-%m-%d ") + now.strftime("%H:%M:%S")) writexml(timestamp, energy, energy_feed, power) data = ''