Implemented connection with InfluxDB
This commit is contained in:
169
influxgraph.py
Normal file
169
influxgraph.py
Normal file
@ -0,0 +1,169 @@
|
||||
from influxdb import InfluxDB, InfluxDataGetter
|
||||
import time
|
||||
import logging
|
||||
from colors import assign_colors_to_curves
|
||||
import json
|
||||
|
||||
class InfluxGraph:
|
||||
"""
|
||||
Class implementing the logic of the different routes that are called by the client to retrieve graph data with InfluxDB.
|
||||
|
||||
Global constants :
|
||||
HISTORICAL (int) : value that represents the "historical" visualisation mode, meaning that the most recent point is not in the visualisation window.
|
||||
ACTUAL (int) : value that represents the "actual" visualisation mode, meaning that the curves stay in place, but new data is being added to the right (expansion in the future).
|
||||
LIVE (int) : value that represents the "live" visualisation mode, meaning that the curves move with the most recent point always at the same place.
|
||||
|
||||
Attributes :
|
||||
db (InfluxDB) : the InfluxDB instance that holds the connection with InfluxDB.
|
||||
influx_data_getter (InfluxDataGetter) : the InfluxDataGetter instance that allows to get data out of InfluxDB.
|
||||
livemode (int) : the type of visualisation the user is currently in. Can be HISTORICAL, ACTUAL or LIVE.
|
||||
time ([(int)]) : an array of unix timestamp in seconds, where the first value is the last most recent requested point in time,
|
||||
and the second value is the current most recent requested point in time.
|
||||
lastvalues ({(str):((int), (float))}) : a dictionnary where the keys are the variable names, and the values are tuples, where the first
|
||||
value is the unix timestamp of the most recent value known for this variable, and the second value its corresponding value
|
||||
"""
|
||||
HISTORICAL = 0
|
||||
ACTUAL = 1
|
||||
LIVE = 2
|
||||
|
||||
def __init__(self):
|
||||
self.db = InfluxDB()
|
||||
self.influx_data_getter = InfluxDataGetter(self.db, json.load(open("./graphs/lab4.json", "r"))["influx"])
|
||||
self.livemode = self.HISTORICAL
|
||||
self.time = [0, 0]
|
||||
self.lastvalues = {}
|
||||
|
||||
def get_abs_time(self, times):
|
||||
"""
|
||||
Gets the absolute times for the given pontential relative times. If the given timestamps are less than one year, then the value is relative
|
||||
and converted into an asbolute timestamps
|
||||
|
||||
Parameters :
|
||||
times([(float)]) : an array of unix timestamps or relative duration (< 1 year) as floats
|
||||
|
||||
Returns :
|
||||
[(float)] : an array of absolute unix timestamps as floats
|
||||
"""
|
||||
now = int(time.time() + 0.999)
|
||||
oneyear = 365 * 24 * 3600
|
||||
return [t + now if t < oneyear else t for t in times]
|
||||
|
||||
def strip_future(self, result):
|
||||
"""
|
||||
OLD : strip future points (happens only on dummy test_day)
|
||||
Removes points more recent that the last requested point in time
|
||||
|
||||
Parameters :
|
||||
result ({(str):[[(int),(float)]]}) : a dictionnary with the variable names as key, and an array of points,
|
||||
which are an array containing the timestamp as their first value, and the y-value in float as their second one.
|
||||
"""
|
||||
# if self.livemode == self.LIVE:
|
||||
for c in result.values():
|
||||
while c:
|
||||
lastt, lastx = c[-1]
|
||||
if lastt <= self.time[1]:
|
||||
break
|
||||
c.pop()
|
||||
|
||||
def complete_to_end(self, result, endtime):
|
||||
"""
|
||||
Completes the data until the last requested point in time by adding the last known y-value at the end point.
|
||||
|
||||
Parameters :
|
||||
result ({(str):[[(int),(float)]]}) : a dictionnary with the variable names as key, and an array of points,
|
||||
which are an array containing the timestamp as their first value, and the y-value in float as their second one.
|
||||
endtime (int) : the unix timestamp in seconds of the time we want to have data until
|
||||
"""
|
||||
for var, c in result.items():
|
||||
if c:
|
||||
lastt, lastx = c[-1]
|
||||
if lastt < endtime:
|
||||
c.append((endtime, lastx))
|
||||
self.lastvalues[var] = (endtime, lastx)
|
||||
|
||||
def w_graph(self, variables, time="-1800,0"):
|
||||
"""
|
||||
Gets the curves given by variables in the time range "time"
|
||||
Called when the route /graph is reached.
|
||||
|
||||
Parameters :
|
||||
variables (str) : a comma separataed value string of variable names (influx names) to retrieve
|
||||
time (str) : a commma separated value string (range) of seconds. They are treated as relative from now if they are lesser than one year.
|
||||
|
||||
Returns :
|
||||
{"type":"graph-draw", "reduced":(bool), "graph":{(str):[[(int),(float)]]}} : a dictionnary with its "graph-draw" type (so it can be processed by the client), a "reduced" value
|
||||
indicating if the data is reduced or not (meaning the data is sampled to be lighter for data viewing), and a "graph" dictionnary with the variable names as key, and an array of points,
|
||||
which are an array containing the timestamp as their first value, and the y-value in float as their second one.
|
||||
"""
|
||||
time = [float(t) for t in time.split(',')]
|
||||
start, end, now = self.get_abs_time(time + [0])
|
||||
start, end, now = int(start), int(end), int(now)
|
||||
self.time = [start, end]
|
||||
self.variables = variables.split(',')
|
||||
self.livemode = self.ACTUAL if end >= now else self.HISTORICAL
|
||||
logging.info('LIVE %g %g %d %d', end, now, end >= now, self.livemode)
|
||||
|
||||
result = self.influx_data_getter.get_curves_in_timerange(self.variables, self.time)
|
||||
|
||||
self.strip_future(result)
|
||||
self.complete_to_end(result, end)
|
||||
self.time[0] = self.time[1]
|
||||
# reduction not yet implemented
|
||||
return dict(type='graph-draw', reduced=False, graph=result)
|
||||
|
||||
def w_gettime(self, time):
|
||||
"""
|
||||
Gets the server time for the give time.
|
||||
Called when the route /gettime is reached.
|
||||
|
||||
Parameters :
|
||||
time (str="-1800,0") : the given point in time represented by a string, which is a comma separated unix timestamp values list (in seconds). They are treated as relative from now if they are lesser than one year.
|
||||
|
||||
Returns :
|
||||
{"type":"time", "time":(int)} : a dictionnary with its "time" type (so the data can be processed by the client) and the server unix timestamp in seconds corresponding
|
||||
to the time asked by the client
|
||||
"""
|
||||
time = [float(t) for t in time.split(',')]
|
||||
return dict(type='time', time= self.get_abs_time(time))
|
||||
|
||||
def w_getvars(self, time):
|
||||
"""
|
||||
Gets the curve names available at a given point in time.
|
||||
Called when the route /getvars is reached.
|
||||
|
||||
Parameters :
|
||||
time (str) : the given point in time represented by a string, which is a comma separated unix timestamp values list (in seconds). They are treated as relative from now if they are lesser than one year.
|
||||
|
||||
Returns :
|
||||
{"type":"var_list", "blocks":[{"tag":(str),"unit":(str), "curves":[{"name":(str), "label":(str), "color":(str), "original_color":(str)}]}]} :
|
||||
a dictionnary with its "var_list" type (so the data can be processed by the client) and the available curves with the name of the internal variable,
|
||||
the color to display for this curve, its original color in SEA, grouped by their tag (which is a unit augmented with an index) and their unit ("in blocks")
|
||||
"""
|
||||
|
||||
time = [float(t) for t in time.split(',')]
|
||||
end_time = int(self.get_abs_time(time)[-1])
|
||||
|
||||
blocks = self.influx_data_getter.get_available_variables_at_time(end_time)
|
||||
assign_colors_to_curves(blocks)
|
||||
result = dict(type='var_list')
|
||||
result['blocks'] = blocks
|
||||
return result
|
||||
|
||||
def w_updategraph(self):
|
||||
"""
|
||||
TODO : method needed for live data update. See example in seaweb.py : SeaGraph
|
||||
|
||||
OLD : update live values - seems not to work
|
||||
Sets the current visualisation mode to LIVE.
|
||||
Called when the route /updategraph is reached.
|
||||
Returns :
|
||||
{"type":"accept-graph", "live": bool} : a dict with its "accept-graph" type and a "live" value telling if the server could change its visualization mode to live
|
||||
"""
|
||||
|
||||
return dict(type='accept-graph', live=False)
|
||||
|
||||
def graphpoll(self):
|
||||
"""
|
||||
TODO : method needed for live data update. See example in seaweb.py : SeaGraph
|
||||
"""
|
||||
return None
|
Reference in New Issue
Block a user