solarrd/update.py

147 lines
4.1 KiB
Python
Raw Normal View History

2018-03-11 21:30:10 +01:00
#!/usr/bin/env python3
2018-10-13 14:07:07 +02:00
import sys
2018-04-27 02:03:42 +02:00
import time
2018-03-11 21:30:10 +01:00
import serial
import crcmod
2018-04-27 02:03:42 +02:00
import rrdtool
2018-10-13 14:07:07 +02:00
import paramiko
2018-03-11 21:30:10 +01:00
from config import *
calc_crc = crcmod.predefined.mkCrcFun(CRC_TYPE)
def parse_line(line):
if line[-2:] != "\r\n":
2018-10-20 20:20:27 +02:00
print("Failed to parse: newline broken")
2018-03-11 21:30:10 +01:00
return {key : None for key in FORMAT}
line = line[:-2]
2018-10-20 20:07:35 +02:00
crc_str = line[-4:]
payload = line[0:-4]
crc = int(crc_str, 16)
calced_crc = calc_crc(payload.encode('ascii'))
2018-03-11 21:30:10 +01:00
if crc != calc_crc(payload.encode('ascii')):
2018-10-20 20:20:27 +02:00
print("Failed to parse: CRC broken")
2018-03-11 21:30:10 +01:00
return {key : None for key in FORMAT}
parts = payload.split(';')
parts = [p.strip() for p in parts]
parts = [x if x != '#' else None for x in parts]
data = zip(FORMAT, parts)
return dict(data)
2018-04-27 02:03:42 +02:00
def create_database():
sources = []
for name, minval, maxval in STORED_VALUES:
sources += ["DS:%s:GAUGE:%d:%f:%f" % (name, DATA_INTERVAL * 2, minval, maxval)]
now = time.time()
now = now - (now % DATA_INTERVAL)
rrd_params = [DATA_FILE,
"--start", "%d" % now,
"--step", str(DATA_INTERVAL)]
rrd_params += sources
rows = ARCHIVE_INTERVAL / DATA_INTERVAL
rrd_params += ["RRA:LAST:0.1:1:%d" % (rows,)]
rrdtool.create(*rrd_params)
rrd_archive_params = [ARCHIVE_DATA_FILE,
"--start", "now",
"--step", str(DATA_INTERVAL)]
steps = ARCHIVE_INTERVAL / DATA_INTERVAL
rows = ARCHIVE_KEEP_INTERVAL / ARCHIVE_INTERVAL
rrd_archive_params += sources
rrd_archive_params += ["RRA:AVERAGE:%f:%d:%d" % (MAX_MISSING, steps, rows)]
rrdtool.create(*rrd_archive_params)
def update_database(line):
update_values = []
for name, _, _ in STORED_VALUES:
2018-10-20 20:13:23 +02:00
if line[name] == None:
return
2018-04-27 02:03:42 +02:00
update_values += ["%f" % float(line[name])]
now = time.time()
now = now - (now % DATA_INTERVAL)
line = ("%d:" % now) + ":".join(update_values)
print(line)
rrdtool.update(DATA_FILE, line)
rrdtool.update(ARCHIVE_DATA_FILE, line)
def update_graphs():
2018-10-13 14:47:58 +02:00
for graph_name, lines in GRAPHS.items():
2018-04-27 02:03:42 +02:00
2018-10-13 14:07:07 +02:00
# Render current data
2018-10-13 14:47:58 +02:00
graph_params = ['%s.png' % graph_name, '-a',
'PNG', '-s', 'n-%d' % ARCHIVE_INTERVAL]
2018-10-20 20:07:35 +02:00
2018-04-27 02:03:42 +02:00
for name, lable, color in lines:
graph_params += ['DEF:%s=%s:%s:LAST' % (name, DATA_FILE, name)]
graph_params += ['LINE1:%s%s:%s' % (name, color, lable)]
2018-10-20 20:25:03 +02:00
try:
rrdtool.graph(*graph_params)
except rrdtool.OperationalError:
print("Failed to render current data")
2018-04-27 02:03:42 +02:00
2018-10-13 14:07:07 +02:00
# Also render Archives
2018-10-13 14:47:58 +02:00
graph_params = ['%s_archive.png' % graph_name, '-a',
'PNG', '-s', 'n-%d' % ARCHIVE_KEEP_INTERVAL]
2018-04-27 02:03:42 +02:00
2018-10-13 14:07:07 +02:00
for name, lable, color in lines:
graph_params += ['DEF:%s=%s:%s:AVERAGE' % (name, DATA_FILE, name)]
graph_params += ['LINE1:%s%s:%s' % (name, color, lable)]
2018-10-20 20:25:03 +02:00
try:
rrdtool.graph(*graph_params)
except rrdtool.OperationalError:
print("Failed to render archive data")
2018-10-13 14:07:07 +02:00
2018-10-20 20:35:48 +02:00
def _do_upload(sftp, src, dest):
2018-10-13 14:07:07 +02:00
try:
2018-10-20 20:35:48 +02:00
sftp.put(src, dest)
except:
print("Unexpected error while uploading:", sys.exc_info()[1])
def upload_graphs():
2018-10-13 14:07:07 +02:00
key = paramiko.RSAKey.from_private_key_file(SFTP_KEY)
transport = paramiko.Transport((SFTP_HOST, SFTP_PORT))
transport.connect()
transport.auth_publickey(SFTP_USER, key)
sftp = paramiko.SFTPClient.from_transport(transport)
for name, _ in GRAPHS.items():
2018-10-20 20:35:48 +02:00
_do_upload(sftp, '%s.png' % name, 'solar/%s.png' % name)
_do_upload(sftp, '%s_archive.png' % name, 'solar/%s_archive.png' % name)
_do_upload(sftp, 'index.html', 'solar/index.html')
2018-10-13 14:07:07 +02:00
sftp.close()
transport.close()
2018-10-20 20:35:48 +02:00
2018-03-11 21:30:10 +01:00
def main():
2018-10-20 20:13:23 +02:00
ser = serial.Serial(SERIAL, BAUD_RATE, timeout=10.0)
while True:
line = ser.readline().decode('ascii')
if len(line) > 0:
2018-10-20 20:20:27 +02:00
print(line)
2018-10-20 20:13:23 +02:00
parsed = parse_line(line)
update_database(parsed)
2018-10-20 20:20:27 +02:00
update_graphs()
upload_graphs()
2018-10-20 20:13:23 +02:00
2018-03-11 21:30:10 +01:00
if __name__ == '__main__':
main()