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