407 lines
12 KiB
JavaScript
407 lines
12 KiB
JavaScript
|
const express = require('express')
|
||
|
const mariadb = require('mariadb')
|
||
|
const fs = require('fs');
|
||
|
|
||
|
let db_settings = JSON.parse(fs.readFileSync('resources/db_settings.json', 'utf8'));
|
||
|
|
||
|
const app = express()
|
||
|
const pool = mariadb.createPool({
|
||
|
host: db_settings.host,
|
||
|
port: db_settings.port,
|
||
|
user: db_settings.user,
|
||
|
password: db_settings.password,
|
||
|
database: db_settings.database,
|
||
|
supportBigNumbers: true,
|
||
|
})
|
||
|
|
||
|
const PORT = 80
|
||
|
|
||
|
function convert_rights(rights) {
|
||
|
switch (rights) {
|
||
|
case "Super-User":
|
||
|
return 0;
|
||
|
|
||
|
case "PTS-User":
|
||
|
return 1;
|
||
|
|
||
|
case "Premium-User":
|
||
|
return 2;
|
||
|
|
||
|
case "Standard-User":
|
||
|
return 3;
|
||
|
|
||
|
case "Test-User":
|
||
|
return 4;
|
||
|
|
||
|
default:
|
||
|
throw new Error("Could not parse Rights (" + rights + ")");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// encapsulate db access
|
||
|
async function queryDB(query) {
|
||
|
let conn;
|
||
|
let rows;
|
||
|
|
||
|
try {
|
||
|
conn = await pool.getConnection();
|
||
|
rows = await conn.query(query);
|
||
|
} catch (err) {
|
||
|
throw err;
|
||
|
} finally {
|
||
|
if (conn) {
|
||
|
conn.end();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return rows;
|
||
|
}
|
||
|
|
||
|
async function queryDevice(device, incoming_rights) {
|
||
|
let config_ids = await queryDB(
|
||
|
"SELECT config_id " +
|
||
|
"FROM api_info " +
|
||
|
"WHERE name=\"Gerät\" AND value LIKE \"" + device + "\""
|
||
|
);
|
||
|
|
||
|
let meta_map = {};
|
||
|
|
||
|
for (let i = 0; i < config_ids.length; i++) {
|
||
|
const config_id = config_ids[i].config_id;
|
||
|
|
||
|
let metas = await queryDB(
|
||
|
"SELECT name, value " +
|
||
|
"FROM api_info " +
|
||
|
"WHERE config_id=\"" + config_id + "\""
|
||
|
);
|
||
|
|
||
|
let m = {};
|
||
|
m["data"] = {};
|
||
|
|
||
|
for (let j = 0; j < metas.length; j++) {
|
||
|
let value = metas[j].value;
|
||
|
let name = metas[j].name;
|
||
|
|
||
|
if (name == "Gerät") {
|
||
|
m["Gerät"] = value;
|
||
|
} else {
|
||
|
let values = JSON.parse(value);
|
||
|
|
||
|
for (let [key, value] of Object.entries(values)) {
|
||
|
if (Array.isArray(value)) {
|
||
|
for (let i = 0; i < value.length; i++) {
|
||
|
let v = value[i];
|
||
|
let rights = convert_rights(v.right);
|
||
|
|
||
|
if (rights < incoming_rights) {
|
||
|
delete values[key];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
if (value.right === undefined) {
|
||
|
for (let [inner_key, inner_value] of Object.entries(value)) {
|
||
|
if (Array.isArray(inner_value)) {
|
||
|
for (let i = 0; i < inner_value.length; i++) {
|
||
|
let v = inner_value[i];
|
||
|
|
||
|
for (let [inner_inner_key, inner_inner_value] of Object.entries(v)) {
|
||
|
let rights = convert_rights(inner_inner_value.right);
|
||
|
|
||
|
if (rights < incoming_rights) {
|
||
|
delete v[inner_inner_key];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (inner_value.right !== undefined) {
|
||
|
let rights = convert_rights(inner_value.right);
|
||
|
|
||
|
if (rights < incoming_rights) {
|
||
|
delete value[inner_key];
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
for (let [inner_inner_key, inner_inner_value] of Object.entries(inner_value)) {
|
||
|
let rights = convert_rights(inner_inner_value.right);
|
||
|
|
||
|
if (rights < incoming_rights) {
|
||
|
delete inner_value[inner_inner_key];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
let rights = convert_rights(value.right);
|
||
|
|
||
|
if (rights < incoming_rights) {
|
||
|
delete values[key];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let d = m["data"];
|
||
|
let l = Object.keys(d).length;
|
||
|
|
||
|
if (l != 0) {
|
||
|
m["data"] = { ...d, ...values };
|
||
|
} else {
|
||
|
m["data"] = values;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
meta_map[config_id] = m;
|
||
|
}
|
||
|
|
||
|
for (let config_id of Object.keys(meta_map)) {
|
||
|
let results = await queryDB(
|
||
|
"SELECT id " +
|
||
|
"FROM api_results " +
|
||
|
"WHERE config_id=\"" + config_id + "\""
|
||
|
);
|
||
|
|
||
|
for (let j = 0; j < results.length; j++) {
|
||
|
let measurements = await queryDB(
|
||
|
"SELECT name, value, rights " +
|
||
|
"FROM api_measurements " +
|
||
|
"WHERE result_id=\"" + results[j].id + "\""
|
||
|
);
|
||
|
|
||
|
m = {}
|
||
|
|
||
|
for (let k = 0; k < measurements.length; k++) {
|
||
|
let measurement = measurements[k];
|
||
|
|
||
|
let rights = measurement.rights.replace(/['"]+/g, '');
|
||
|
let rights_value = convert_rights(rights);
|
||
|
|
||
|
if (rights_value >= incoming_rights) {
|
||
|
m[measurement.name] = { name: measurement.name, value: measurement.value, rights: rights };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
meta_map[config_id][results[j].id] = m;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return meta_map;
|
||
|
}
|
||
|
|
||
|
async function calculate(elements, parameter, operation) {
|
||
|
switch (operation) {
|
||
|
case "average":
|
||
|
let tmp = 0;
|
||
|
let count = 0;
|
||
|
|
||
|
for (let param of parameter) {
|
||
|
const value = elements.find(element => element.name == param);
|
||
|
|
||
|
if (value === undefined) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
count += 1;
|
||
|
tmp += value.value;
|
||
|
}
|
||
|
|
||
|
if (count == 0) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return tmp / count;
|
||
|
|
||
|
case "sum":
|
||
|
let sum = 0;
|
||
|
|
||
|
for (let param of parameter) {
|
||
|
const value = elements.find(element => element.name == param);
|
||
|
|
||
|
if (value === undefined) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
sum += value.value;
|
||
|
}
|
||
|
|
||
|
return sum;
|
||
|
|
||
|
case "divide":
|
||
|
const v1 = elements.find(element => element.name == parameter[0]);
|
||
|
const v2 = elements.find(element => element.name == parameter[1]);
|
||
|
|
||
|
if (v1 === undefined || v2 === undefined || v2 == 0) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return v1.value / v2.value;
|
||
|
|
||
|
case "multiply":
|
||
|
let p = 1.0;
|
||
|
|
||
|
for (let param of parameter) {
|
||
|
const value = elements.find(element => element.name == param);
|
||
|
|
||
|
if (value === undefined) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
p *= value.value;
|
||
|
}
|
||
|
|
||
|
return p;
|
||
|
|
||
|
case "subtract":
|
||
|
const s1 = elements.find(element => element.name == parameter[0]);
|
||
|
const s2 = elements.find(element => element.name == parameter[1]);
|
||
|
|
||
|
if (s1 === undefined || s2 === undefined) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return s1.value - s2.value;
|
||
|
|
||
|
case "discard":
|
||
|
const value = elements.find(element => element.name == parameter[0]);
|
||
|
const res = elements.find(element => element.name == parameter[1]);
|
||
|
|
||
|
if (value === undefined || res === undefined) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
if (value.value !== null && !value.value) {
|
||
|
return res.value;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
throw "unknown operation " + operation;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function createResultForEntry(parameters, descriptions, calculations) {
|
||
|
let result = {};
|
||
|
|
||
|
for (let [key, data] of Object.entries(parameters)) {
|
||
|
if (Object.keys(data).length == 0) {
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
if (key == "Gerät") {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
let elements = findAll(data);
|
||
|
|
||
|
for (let [calc_key, calc_value] of Object.entries(calculations)) {
|
||
|
let val = null;
|
||
|
|
||
|
if (calc_value.const !== undefined) {
|
||
|
val = parseFloat(calc_value.const[0]);
|
||
|
} else {
|
||
|
val = await calculate(elements, calc_value.source, calc_value.operation);
|
||
|
}
|
||
|
|
||
|
if (val !== null) {
|
||
|
elements.push({ name: calc_key, value: val });
|
||
|
}
|
||
|
}
|
||
|
|
||
|
console.info(elements);
|
||
|
|
||
|
for (let element of elements) {
|
||
|
let key = String(element.name);
|
||
|
let value = element.value;
|
||
|
|
||
|
let description = descriptions[key];
|
||
|
|
||
|
if (description !== undefined) {
|
||
|
if (value !== null) {
|
||
|
result[key] = {
|
||
|
name: description.name,
|
||
|
value: value,
|
||
|
description: description.description,
|
||
|
unit: description.unit,
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
for (let [description_key, description] of Object.entries(descriptions)) {
|
||
|
if (key.startsWith(description_key)) {
|
||
|
result[key] = {
|
||
|
name: description.name,
|
||
|
value: value,
|
||
|
description: description.description,
|
||
|
unit: description.unit,
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
async function createResultList(parameters, descriptions, calculations) {
|
||
|
let result = [];
|
||
|
|
||
|
for (let entry of Object.values(parameters)) {
|
||
|
let entry_result = await createResultForEntry(entry, descriptions, calculations);
|
||
|
|
||
|
if (Object.keys(entry_result).length != 0) {
|
||
|
result.push(entry_result);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
function findAll(object) {
|
||
|
let list = [];
|
||
|
|
||
|
if (object === null) {
|
||
|
return list;
|
||
|
}
|
||
|
|
||
|
if (object.name !== undefined) {
|
||
|
if (object.value !== undefined) {
|
||
|
list.push({ name: object.name, value: object.value });
|
||
|
} else {
|
||
|
for (let [key, value] of Object.entries(object)) {
|
||
|
list = list.concat(findAll(value));
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
for (let [key, value] of Object.entries(object)) {
|
||
|
list = list.concat(findAll(value));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return list;
|
||
|
}
|
||
|
|
||
|
app.get('/ddtrust/cepi/:rights', async (request, response) => {
|
||
|
// read parameters from DB and only return accessible
|
||
|
let deviceParameters = await queryDevice("%Cepi%", convert_rights(request.params.rights));
|
||
|
|
||
|
// read paremeter description file
|
||
|
let descriptions = JSON.parse(fs.readFileSync('resources/variable_description.json', 'utf8'));
|
||
|
|
||
|
// read parameter calculation file,
|
||
|
let calculations = JSON.parse(fs.readFileSync('resources/variable_calculation.json', 'utf8'));
|
||
|
|
||
|
// combine description information with parameters queried from DB
|
||
|
let result = await createResultList(deviceParameters, descriptions, calculations);
|
||
|
|
||
|
response.json(result)
|
||
|
})
|
||
|
|
||
|
app.listen(PORT, () => {
|
||
|
console.log(`Server running on port ${PORT}`)
|
||
|
})
|