major rework
using influxdb structure independed of nicos cache
This commit is contained in:
106
influxdb.py
106
influxdb.py
@@ -17,6 +17,7 @@ class InfluxDB:
|
||||
|
||||
def __init__(self):
|
||||
config = ConfigParser()
|
||||
config.optionxform = str
|
||||
config.read("./config/influx.ini")
|
||||
self._client = InfluxDBClient(url=config["INFLUX"]["url"], token=config["INFLUX"]["token"],
|
||||
org=config["INFLUX"]["org"])
|
||||
@@ -83,35 +84,6 @@ class InfluxDataGetter:
|
||||
self._db = db
|
||||
|
||||
# ----- PUBLIC METHODS
|
||||
|
||||
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.
|
||||
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 :
|
||||
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 if given or unit (in tag).
|
||||
"""
|
||||
|
||||
all_setup_info = self._get_all_setup_info_as_dict(time)
|
||||
|
||||
available_variables = self._extract_variables(all_setup_info)
|
||||
if not chart_configs == None:
|
||||
for chart_config in chart_configs:
|
||||
available_variables = self._filter_params_with_config(available_variables, chart_config)
|
||||
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, time)
|
||||
res = self._group_variables_by_cat_unit(available_variables)
|
||||
|
||||
return res
|
||||
|
||||
def get_curves_in_timerange(self, variables, time, interval = None):
|
||||
"""
|
||||
@@ -199,18 +171,17 @@ class InfluxDataGetter:
|
||||
parameter = "value" if len(var_param) == 1 else var_param[1]
|
||||
|
||||
# we need to rename the "_time" column to simply "time" in case we want binning because of the comparison done later in the "binned points with same timestamp" process.
|
||||
# chr(34) is the double quote char, because we cannot escape them in a f string
|
||||
query = f"""
|
||||
from(bucket: "{self._bucket}")
|
||||
|> range(start: {times[0]}, stop: {times[1] + 1})
|
||||
|> filter(fn : (r) => r._measurement == "{variable_name_for_query}")
|
||||
|> filter(fn : (r) => r._field == "{parameter+"_float"}")
|
||||
{"|> aggregateWindow(every: duration(v: "+ str(self._seconds_to_nanoseconds(interval))+"), fn: last, createEmpty:false, timeDst:"+chr(34)+"binning_time"+chr(34)+")" if interval != "None" else ""}
|
||||
{f'|> aggregateWindow(every: duration(v: {self._seconds_to_nanoseconds(interval)}), fn: last, createEmpty:false, timeDst:"binning_time")' if interval != 'None' else ''}
|
||||
|> map(fn: (r) => ({{r with relative: ( float(v: uint(v: {"r.binning_time" if interval != "None" else "r._time"}) - uint(v:{self._seconds_to_nanoseconds(times[0])})) / 1000000000.0 )}}))
|
||||
|> map(fn: (r) => ({{r with timestamp: float(v: uint(v: {"r.binning_time" if interval != "None" else "r._time"})) / 1000000000.0}}))
|
||||
{"|> rename(columns: {_time:"+chr(34)+"time"+chr(34)+"})" if interval != "None" else ""}
|
||||
{'|> rename(columns: {_time:"time"})' if interval != 'None' else ''}
|
||||
|> drop(columns:["_start", "_stop", "_field"])
|
||||
|> pivot(rowKey:["relative", "timestamp", "expired"{", "+chr(34)+"time"+chr(34) if interval != "None" else ""}], columnKey: ["_measurement"], valueColumn: "_value")
|
||||
|> pivot(rowKey:["relative", "timestamp", "expired"{', "time"' if interval != "None" else ''}], columnKey: ["_measurement"], valueColumn: "_value")
|
||||
"""
|
||||
data_frame = self._db.query_data_frame(query)
|
||||
|
||||
@@ -322,75 +293,6 @@ class InfluxDataGetter:
|
||||
|
||||
# ----- PRIVATE METHODS
|
||||
|
||||
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 time.
|
||||
|
||||
Parameters
|
||||
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
|
||||
being the type of Secop device for this module, and the value is too big to give its signature. Some tuple examples can be found under graphs/setup_info_examples.
|
||||
|
||||
"""
|
||||
measurements = ["nicos/se_main", "nicos/se_stick", "nicos/se_addons"]
|
||||
res = []
|
||||
for measurement in measurements:
|
||||
query = f"""
|
||||
from(bucket: "{self._bucket}")
|
||||
|> range(start: 0, stop: {time + 1})
|
||||
|> filter(fn: (r) => r._measurement == "{measurement}")
|
||||
|> filter(fn: (r) => r._field == "setup_info")
|
||||
|> last()
|
||||
|> yield(name: "res")
|
||||
"""
|
||||
tables = self._db.query(query)
|
||||
for table in tables:
|
||||
for record in table.records:
|
||||
res.append(ast.literal_eval(record.get_value()))
|
||||
return res
|
||||
|
||||
def _extract_variables(self, all_setup_info_dict):
|
||||
"""
|
||||
Extracts relevant information out of the setup_info dict for each available variable in measurements nicos/se_main, nicos/se_stick, nicos/se_addons
|
||||
|
||||
Parameters :
|
||||
all_setup_info_dict ([{(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
|
||||
being the type of Secop device for this module, and the value is too big to give its signature. Some tuple examples can be found under graphs/setup_info_examples.
|
||||
|
||||
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 ("*" 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 = []
|
||||
added_names = []
|
||||
for setup_info_dict in all_setup_info_dict:
|
||||
for (_, content) in setup_info_dict.items():
|
||||
if content[0] != "nicos.devices.secop.devices.SecopDevice":
|
||||
name = self._transform_secop_module_name_to_influx(content[1]["secop_module"])
|
||||
if name not in added_names:
|
||||
value_unit = "1" if (not "unit" in content[1].keys() or content[1]["unit"] == "") else content[1]["unit"]
|
||||
variable = {
|
||||
"name":name,
|
||||
"label":content[1]["secop_module"],
|
||||
"params":{"value":{"cat":"*", "color":"", "unit":value_unit}} # main value, shown by default
|
||||
}
|
||||
|
||||
for param_name, param_content in content[1]["params_cfg"].items():
|
||||
param_unit = "1" if (not "unit" in param_content.keys() or param_content["unit"] == "") else param_content["unit"]
|
||||
variable["params"][param_name] = {
|
||||
"cat":"*" if param_name == "target" else "-", # target is also shown by default, not the other parameters
|
||||
"color":"",
|
||||
"unit":param_unit
|
||||
}
|
||||
available_varirables.append(variable)
|
||||
added_names.append(name)
|
||||
return available_varirables
|
||||
|
||||
def _transform_secop_module_name_to_influx(self, secop_module_name):
|
||||
"""
|
||||
Transforms the name of the variable available in the setup_info dict into the Influx name.
|
||||
|
||||
Reference in New Issue
Block a user