Forked from
Simon Delamare / wattmetre-read
14 commits behind, 5 commits ahead of the upstream repository.
-
Simon Delamare authoredSimon Delamare authored
wattmetre_oldapi.py 3.97 KiB
#!/usr/bin/python3
"""
Read wattmetre log files and serve values as JSON over HTTP, with same API than old wattmetres
"""
import sys
import os
import time
import glob
import yaml
import requests
from file_read_backwards import FileReadBackwards
from bottle import Bottle, run
if not len(sys.argv)>2:
print("Usage: %s wattmetre1-log-dir,wattmetre2-log-dir,... url-to-wattmetre1-refapi,url-to-wattmetre2-refapi,..." % sys.argv[0], file=sys.stderr)
sys.exit(1)
previous_request_time = None
previous_output = None
wattmetre_log_directories = sys.argv[1].split(",")
wattmetre_mappings = []
for url in sys.argv[2].split(","):
wattmetre = {}
for port, node in requests.get(url, verify=False).json().get('ports', {}).items():
try:
port = int(port)
wattmetre[node] = wattmetre[node].append(port) if wattmetre.get(node) else [port]
except ValueError:
continue
wattmetre_mappings.append(wattmetre)
print(wattmetre_mappings)
if len(wattmetre_mappings)!=len(wattmetre_log_directories):
print("Error: Please provide same number of log directories than mapping files")
sys.exit(1)
app = Bottle()
@app.route("/")
def getjson():
global previous_request_time
global previous_output
request_time = int(time.time())
# Disable caching feature
if False #and request_time == previous_request_time:
output = previous_output
else:
previous_request_time = request_time
output = {}
for wattmetre_log_directory, wattmetre_mapping in zip(wattmetre_log_directories, wattmetre_mappings):
last_power_files = sorted([
f for f in glob.glob(wattmetre_log_directory+'/power.csv.*')
if not os.path.basename(f).endswith('gz')
])
values_to_compute = get_last_valid_values(last_power_files[-1])
mean_values = []
if values_to_compute:
mean_values = get_mean_values(values_to_compute)
output.update(format_output(mean_values, wattmetre_mapping))
previous_output = output
return output
def get_last_valid_values(filename):
" Return all values in filename with before-the-last available timestamp in second "
last_timestamp = None
last_valid_values = []
first_line = True
with FileReadBackwards(filename, encoding="utf-8") as frb:
for line in frb:
if first_line:
first_line = False
continue
cur_values = line.split(',')
# Uncomment f wattmetre-read debug mode is in use
cur_values = cur_values[2:]
timestamp = int(float(cur_values[0]))
if not last_timestamp:
last_timestamp = timestamp
if timestamp == last_timestamp - 1:
if cur_values[1] == "OK":
last_valid_values.append(cur_values)
if timestamp <= last_timestamp - 2:
break
return last_valid_values
def get_mean_values(values):
"Return the mean values for each column of values matrix"
mean_values = []
for col in range(len(values[0])):
try:
valid_values = [float(v[col]) for v in values if v[col].strip() != '']
mean_value = sum(valid_values)/len(values)
mean_value = round(10*mean_value)/10
mean_values.append(mean_value)
except ValueError:
mean_values.append("str")
return mean_values
def format_output(values, wattmetre_mapping):
" Format ouput same as old-style wattmetre, according to wattmetre_mapping content "
" (a dict with node name as key and the list of its plugs number as value) "
output = {}
for node, plugs in wattmetre_mapping.items():
if not isinstance(plugs, list):
plugs = [plugs]
output[node] = {"watt": sum([values[2+i] for i in range(len(values[2:])) if i in plugs]), "timestamp": int(values[0])}
return output
run(app, host='localhost', port=5000, debug=True)