Simplified code for getting vars + corresponding doc

This commit is contained in:
l_samenv
2024-09-09 14:18:27 +02:00
parent 2a4efff511
commit b3d899295d
4 changed files with 57 additions and 36 deletions

View File

@ -378,7 +378,7 @@ function successHandler(s, message) {
begin = timeRange[0] - timeRange[1];
select.value = begin;
// Server-request for variable-list.*/
reqJSONPOST(0, "http://" + hostPort + "/getvars", "time=" + timeRange + "&userconfiguration=" + JSON.stringify(getFormattedUserConfigurationFromLocalStorage()) + "&id="
reqJSONPOST(0, "http://" + hostPort + "/getvars", "time=" + timeRange[1] + "&userconfiguration=" + JSON.stringify(getFormattedUserConfigurationFromLocalStorage()) + "&id="
+ clientID, successHandler, errorHandler);
break;
// Response to a "getvars"-server-request.

View File

@ -867,15 +867,14 @@ let graphs = (function (){
cursorLine(null);
window["wideGraphs"] = true;
adjustGrid()
let msLeftTimestampGetVars = 0, msLeftTimestampGetGraph = 0 , msRightTimestampGetVars = 0, msRightTimestampGetGraph = 0;
let msLeftTimestampGetGraph = 0 , msRightTimestampGetVars = 0, msRightTimestampGetGraph = 0;
msLeftTimestampGetVars = dateTimestampMs;
msLeftTimestampGetGraph = dateTimestampMs;
msRightTimestampGetVars = dateTimestampMs + timeValueMs;
msRightTimestampGetGraph = dateTimestampMs + 24*60*60*1000;
AJAX("http://" + hostPort + "/getvars").postForm("time=" + msLeftTimestampGetVars/1000 + "," + msRightTimestampGetVars/1000 + "&userconfiguration=" + JSON.stringify(getFormattedUserConfigurationFromLocalStorage()) + "&id="+ clientID).then(function(data){
AJAX("http://" + hostPort + "/getvars").postForm("time=" + msRightTimestampGetVars/1000 + "&userconfiguration=" + JSON.stringify(getFormattedUserConfigurationFromLocalStorage()) + "&id="+ clientID).then(function(data){
blocks = data.blocks;
document.getElementById("device").innerHTML = data.device
maxTime = msRightTimestampGetGraph;
@ -948,7 +947,7 @@ let graphs = (function (){
window["wideGraphs"] = false; // will have no effect if hideRightPart is true
adjustGrid();
AJAX("http://" + hostPort + "/getvars").postForm("time=" + msLeftTimestamp/1000 + "," + msRightTimestamp/1000 + "&userconfiguration=" + JSON.stringify(getFormattedUserConfigurationFromLocalStorage()) + "&id="+ clientID).then(function(data){
AJAX("http://" + hostPort + "/getvars").postForm("time=" + msRightTimestamp/1000 + "&userconfiguration=" + JSON.stringify(getFormattedUserConfigurationFromLocalStorage()) + "&id="+ clientID).then(function(data){
currentMaxTime = msRightTimestamp + 60000;
currentMinTime = msLeftTimestamp;
@ -1245,7 +1244,7 @@ let graphs = (function (){
function applySettingsCallback(userConfiguration){
cursorLine(null);
AJAX("http://" + hostPort + "/getvars").postForm("time=" + currentMinTime/1000 + "," + currentMaxTime/1000 + "&userconfiguration=" + JSON.stringify(userConfiguration) + "&id="+ clientID).then(function(data){
AJAX("http://" + hostPort + "/getvars").postForm("time=" + currentMaxTime/1000 + "&userconfiguration=" + JSON.stringify(userConfiguration) + "&id="+ clientID).then(function(data){
blocks = data.blocks;
document.getElementById("device").innerHTML = data.device
maxTime = currentMaxTime;

View File

@ -1,6 +1,5 @@
from influxdb_client import InfluxDBClient
from configparser import ConfigParser
from chart_config import ChartConfig
import ast
from datetime import datetime
from pandas import DataFrame as df, merge_ordered
@ -12,7 +11,10 @@ BUCKET_PREFIX = "nicos-cache-"
class InfluxDB:
"""
Class used to handle the connection with the InfluxDB instance
Attributes :
_client (InfluxDBClient) : the InfluxDB client
"""
def __init__(self):
config = ConfigParser()
config.read("./config/influx.ini")
@ -38,6 +40,15 @@ class InfluxDB:
return self._client.query_api().query(query_str)
def query_data_frame(self, query_str):
"""
Executes the query on the InfluxDB instance and gets the response as a pandas DataFrame
Parameters :
query_str (string) : the Flux query to execute
Returns :
DataFrame : the query response as a DataFrame
"""
return self._client.query_api().query_data_frame(query_str)
class PrettyFloat(float):
@ -54,27 +65,41 @@ class PrettyFloat(float):
return '%.15g' % self
class InfluxDataGetter:
"""
Class used to get data from InfluxDB.
Attributes :
_bucket (str) : the name of the InfluxDB bucket to query (used for all queries)
_db (InfluxDB) : the InfluxDB instance of the database to query
"""
def __init__(self, db, instrument_name):
"""
Parameters :
db (InfluxDB) : the InfluxDB instance of the database to query
instrument_name (str) : the name of the instrument from which the data will be got
"""
self._bucket = BUCKET_PREFIX + instrument_name
self._db = db
# ----- PUBLIC METHODS
def get_available_variables_at_time(self, times, chart_configs = None, user_config = None):
def get_available_variables_at_time(self, time, chart_configs = None, user_config = None):
"""
Gets the available variables (those that we can have a value for since the device has been installed on the instrument) at the given point in time (times[1]).
Here, a variable means : SECOP module name + parameter. By default, this method returns the parameters "value" and "target", unless the config file used in chart_config indicates other directives.
Gets the available variables (those that we can have a value for since the device has been installed on the instrument) at the given point in time.
Here, a variable means : SECOP module name + parameter. By default, this method returns the parameters "value" and "target", unless the config files used in chart_configs or user_config indicates other directives.
Parameters :
times ([int]) : the unix timestamps in seconds of the range. The first value is unused. The last represents the point in time.
chart_config (ChartConfig | None) : the object holding a configuration file for the chart.
time (int) : the unix timestamps in seconds of the point in time to get the variables at.
chart_configs ([ChartConfig] | None) : an array of objects, each holding a configuration file for the chart. Configurations are applied in the order of the list.
user_config ({(str):{"cat":(str), "color":(str), "unit":(str)}} | None) : the Python dict representing the user configuration, applied at the end. The key is <secop_module.parameter>.
Returns :
[{"tag":(str), "unit":(str), "curves":[{"name":(str), "label":(str), "color":(str)}]}] : a list of dictionnaries, each one representing
a block of curves with their name, their label and their color to display, grouped by their category and unit (in tag).
a block of curves with their name, their label and their color to display, grouped by their category if given or unit (in tag).
"""
all_setup_info = self._get_all_setup_info_as_dict(times)
all_setup_info = self._get_all_setup_info_as_dict(time)
available_variables = self._extract_variables(all_setup_info)
if not chart_configs == None:
@ -83,7 +108,7 @@ class InfluxDataGetter:
if not user_config == None:
available_variables = self._filter_params_with_user_config(available_variables, user_config)
available_variables = self._remove_variables_params_not_displayed(available_variables)
available_variables = self._remove_variables_params_wihout_param_float_and_split(available_variables, times)
available_variables = self._remove_variables_params_wihout_param_float_and_split(available_variables, time)
res = self._group_variables_by_cat_unit(available_variables)
return res
@ -298,13 +323,13 @@ class InfluxDataGetter:
# ----- PRIVATE METHODS
def _get_all_setup_info_as_dict(self, times):
def _get_all_setup_info_as_dict(self, time):
"""
Gets the value of the field setup_info in the measurements nicos/se_main, nicos/se_stick, nicos/se_addons as an array of Python dicts.
Takes the last setup_info dict (for each measurement) known at times[1], or all the dicts for this day + the previous known (also for each)
Takes the last setup_info dict (for each measurement) known at time.
Parameters
times ([int]) : the unix timestamps in seconds of the range. The first value can be unused. The last can represent the point in time.
time (int) : the unix timestamps in seconds of the point in time to get the variables at.
Returns :
[{(str):((str), {...})}]: an array of the parsed "setup_info dict" of each measurements. The key is the secop_module prefixed with "se_", and the value is a tuple with its first value
@ -314,10 +339,9 @@ class InfluxDataGetter:
measurements = ["nicos/se_main", "nicos/se_stick", "nicos/se_addons"]
res = []
for measurement in measurements:
to_add = []
query = f"""
from(bucket: "{self._bucket}")
|> range(start: 0, stop: {times[1] + 1})
|> range(start: 0, stop: {time + 1})
|> filter(fn: (r) => r._measurement == "{measurement}")
|> filter(fn: (r) => r._field == "setup_info")
|> last()
@ -326,9 +350,7 @@ class InfluxDataGetter:
tables = self._db.query(query)
for table in tables:
for record in table.records:
to_add.append(ast.literal_eval(record.get_value()))
res.extend(to_add)
res.append(ast.literal_eval(record.get_value()))
return res
def _extract_variables(self, all_setup_info_dict):
@ -341,7 +363,8 @@ class InfluxDataGetter:
Returns :
[{"name":(str), "label":(str), "params":{(str):{"cat":(str), "color":(str), "unit":(str)}}}] : an array of dictionnaries, each containing the Influx name of the corresponding variable out of the setup_info dict,
the label to display in the Web GUI, and a dictionnary of parameters (including value), which consist of dictionnares with the category (empty for the moment), the color (same) and the unit (if available), indexed by the name of the parameter.
the label to display in the Web GUI, and a dictionnary of parameters (including value), which consist of dictionnares with the category ("*" for value and target, "-" else), the color (empty for the moment)
and the unit ("1" if not available or empty), indexed by the name of the parameter.
"""
available_varirables = []
@ -384,12 +407,11 @@ class InfluxDataGetter:
def _filter_params_with_config(self, available_variables, chart_config):
"""
Updates (cat, color, unit) the parameters according to the chart_config object.
Updates (cat, color, unit) the parameters of each variable according to the user_config object.
Parameters:
available_variables ([{"name":(str), "label":(str), "params":{(str):{"cat":(str), "color":(str), "unit":(str)}}}]) : an array of dictionnaries, each containing the Influx name of the corresponding variable out of the setup_info dict,
the label to display in the Web GUI, and a dictionnary of parameters (including value), which consist of dictionnaries with the category ("unit" for value and target or "None"), the color (empty for the moment) and the unit,
indexed by the name of the parameter.
the label to display in the Web GUI, and a dictionnary of parameters (including value), which consist of dictionnaries with the category, the color and the unit, indexed by the name of the parameter.
chart_config (ChartConfig) : the object holding a configuration file for the chart.
Returns :
@ -409,12 +431,12 @@ class InfluxDataGetter:
def _filter_params_with_user_config(self, available_variables, user_config):
"""
Updates (cat, color, unit) the parameters according to the user_config object.
Updates (cat, color, unit) the parameters of each variable according to the user_config object.
Parameters:
available_variables ([{"name":(str), "label":(str), "params":{(str):{"cat":(str), "color":(str), "unit":(str)}}}]) : an array of dictionnaries, each containing the Influx name of the corresponding variable out of the setup_info dict,
the label to display in the Web GUI, and a dictionnary of parameters (including value), which consist of dictionnaries with the category, the color and the unit, indexed by the name of the parameter.
user_config ({(str):{"cat":(str), "color":(str), "unit":(str)}}) : the object representing the user configuration. The key is <secop_module.parameter>.
user_config ({(str):{"cat":(str), "color":(str), "unit":(str)}}) : the Python dict representing the user configuration. The key is <secop_module.parameter>.
Returns :
[{"name":(str), "label":(str), "params":{(str):{"cat":(str), "color":(str), "unit":(str)}}}] : the available_variables parameter, updated
@ -433,7 +455,7 @@ class InfluxDataGetter:
def _remove_variables_params_not_displayed(self, available_variables):
"""
Removes the parameters if their category is None.
Removes the parameters of each variable if their category is "-".
Parameters:
available_variables ([{"name":(str), "label":(str), "params":{(str):{"cat":(str), "color":(str), "unit":(str)}}}]) : an array of dictionnaries, each containing the Influx name of the corresponding variable out of the setup_info dict,
@ -450,14 +472,15 @@ class InfluxDataGetter:
return available_variables
def _remove_variables_params_wihout_param_float_and_split(self, available_variables, times):
def _remove_variables_params_wihout_param_float_and_split(self, available_variables, time):
"""
For each variable, removes the parameters if the Influx database does not contain <param>.float field, and split the parameters to the corresponding output format.
Parameters:
available_variables ([{"name":(str), "label":(str), "params":{(str):{"cat":(str), "color":(str), "unit":(str)}}}]) : an array of dictionnaries, each containing the Influx name of the corresponding variable out of the setup_info dict,
the label to display in the Web GUI, and a dictionnary of parameters (including value), which consist of dictionnares with the category, the color and the unit, indexed by the name of the parameter.
times ([int]): (only second value used) the unix timestamps in seconds of the range at which we want to get the available variables.
time (int) : the unix timestamp in seconds of the point in time to get the variables at. Used to have an upper limit in the query.
Returns :
[{"name":(str), "label":(str), "cat":(str), "color":(str), "unit":(str)}] : an array of dictionnaries, each containing the name of the variable[.<param>],
@ -467,7 +490,7 @@ class InfluxDataGetter:
for variable in available_variables:
query = f"""
import "influxdata/influxdb/schema"
schema.measurementFieldKeys(bucket: "{self._bucket}", measurement: "{variable["name"]}", start:0, stop: {times[1] + 1})
schema.measurementFieldKeys(bucket: "{self._bucket}", measurement: "{variable["name"]}", start:0, stop: {time + 1})
|> yield(name: "res")
"""
records = self._db.query(query)[0].records
@ -486,7 +509,7 @@ class InfluxDataGetter:
def _group_variables_by_cat_unit(self, available_variables):
"""
Performs a group by cat and unit for the available variables
Performs a group by cat if specified (different than "*"), or by unit instead for the available variables
Parameters :
available_variables ([{"name":(str), "label":(str), "cat":(str), "color":(str), "unit":(str)}]) : an array of dictionnaries, each containing the name of the variable[.<param>],

View File

@ -128,12 +128,11 @@ class InfluxGraph:
"""
time = [float(t) for t in time.split(',')]
start_time = int(self.get_abs_time(time)[0])
end_time = int(self.get_abs_time(time)[-1])
if not userconfiguration == None : userconfiguration = json.loads(userconfiguration)
blocks = self.influx_data_getter.get_available_variables_at_time([start_time, end_time], self.chart_configs, userconfiguration)
blocks = self.influx_data_getter.get_available_variables_at_time(end_time, self.chart_configs, userconfiguration)
device_name = self.influx_data_getter.get_device_name(end_time)
# updates the self.variables attribute to keep track of the available variables
self.variables = {variable["name"]:variable["label"] for block in blocks for variable in block["curves"]}