Mentions légales du service

Skip to content
Snippets Groups Projects
Forked from Simon Delamare / wattmetre-read
14 commits behind, 5 commits ahead of the upstream repository.
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)