483 lines
16 KiB
JavaScript
483 lines
16 KiB
JavaScript
"use strict";
|
|
const express = require('express');
|
|
const router = express.Router();
|
|
const moment = require('moment');
|
|
const mathe = require('mathjs');
|
|
const util = require('./utilities');
|
|
|
|
// Mongo wird in app.js geöffnet und verbunden und bleibt immer verbunden !!
|
|
|
|
let sv_factor = {'SBM-20': 1 / 2.47, 'SBM-19': 1 / 9.81888, 'Si22G': 0.081438};
|
|
|
|
//Get readings for all data out ot the database
|
|
router.get('/getfs/:week', function (req, res) {
|
|
let week = req.params.week;
|
|
let db = req.app.get('dbase');
|
|
let st = req.query.start;
|
|
let sid = parseInt(req.query.sensorid);
|
|
let sname = req.query.sensorname;
|
|
let avg = req.query.avgTime;
|
|
let live = (req.query.live == 'true');
|
|
let movingAvg = (req.query.moving=='true');
|
|
let longAVG = req.query.longAVG;
|
|
let system = req.query.os;
|
|
|
|
if (week == 'oneday') {
|
|
console.log(`Operating System = ${system}`);
|
|
getDWMData(db, sid, st, avg, live, movingAvg, 1, longAVG)
|
|
.then(erg => res.json(erg));
|
|
} else if (week == 'oneweek') {
|
|
getDWMData(db, sid, st, avg, live, movingAvg, 7)
|
|
.then(erg => res.json(erg));
|
|
} else if (week == 'onemonth') {
|
|
getDWMData(db, sid, st, 1440, false, false, 31)
|
|
.then(erg => res.json(erg));
|
|
} else if (week == 'korr') {
|
|
getSensorProperties(db,sid)
|
|
.then(erg => res.json(erg));
|
|
} else {
|
|
res.json({'error': 'MIST VERDAMMTER!!'});
|
|
}
|
|
});
|
|
|
|
// fetch name of given sensor-id
|
|
function getSensorName(db,sid) {
|
|
const p = new Promise((resolve,reject) => {
|
|
let coll = db.collection('properties');
|
|
coll.findOne({_id: parseInt(sid)})
|
|
.then(erg => {
|
|
// name is now an array, get the current (last) entry
|
|
if (erg && erg.name && Array.isArray(erg.name)) {
|
|
resolve(erg.name[erg.name.length - 1].name);
|
|
} else {
|
|
resolve(erg ? erg.name : null);
|
|
}
|
|
})
|
|
.catch(err => {
|
|
console.log('getSensorName',err);
|
|
reject(err);
|
|
});
|
|
});
|
|
return p
|
|
}
|
|
|
|
// fetch the properties for the given sensor
|
|
async function getSensorProperties(db,sid) {
|
|
let start = new Date();
|
|
console.log("Get properties for", sid,"from DB");
|
|
let sensorEntries = [{'sid':sid}];
|
|
let coll = db.collection('properties');
|
|
let properties;
|
|
try {
|
|
properties = await coll.findOne({_id: sid});
|
|
}
|
|
catch(e) {
|
|
console.log("getSensorProperties",e);
|
|
return {};
|
|
}
|
|
console.log("got properties - time:", new Date() - start);
|
|
if(properties == null) return null;
|
|
// name is now an array, get the current (last) entry
|
|
let currentName = properties.name;
|
|
if (Array.isArray(properties.name)) {
|
|
currentName = properties.name[properties.name.length - 1].name;
|
|
}
|
|
|
|
// Overwrite name field with string for frontend compatibility
|
|
properties.name = currentName;
|
|
sensorEntries[0]['name'] = currentName;
|
|
|
|
// Check if othersensors exists (might not in new DB structure)
|
|
if (!properties.othersensors || properties.othersensors.length === 0) {
|
|
properties.othersensors = sensorEntries;
|
|
return properties;
|
|
}
|
|
|
|
let mustbeobject = false;
|
|
for(let i = 0, j=1; i<properties.othersensors.length; i++) {
|
|
let es = properties.othersensors[i];
|
|
let e = {};
|
|
if (es != null) {
|
|
if ( typeof es === 'object') {
|
|
mustbeobject=true;
|
|
e.sid = es.id;
|
|
e.name = es.name;
|
|
} else {
|
|
if(mustbeobject) { continue; }
|
|
e.sid = es;
|
|
e.name = await getSensorName(db, es);
|
|
}
|
|
}
|
|
sensorEntries[j] = e;
|
|
j++;
|
|
}
|
|
sensorEntries.sort(function (a, b) {
|
|
if (a.sid < b.sid) {
|
|
return -1;
|
|
}
|
|
if (a.sid > b.sid) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
});
|
|
properties.othersensors = sensorEntries;
|
|
return properties;
|
|
}
|
|
|
|
|
|
async function readRadiationMovingAverage(db, sid, start, end, average, factor) {
|
|
let docs = [];
|
|
let collection = db.collection('radioactivity_sensors');
|
|
try {
|
|
docs = await collection.find({
|
|
sensorid: sid,
|
|
datetime: {
|
|
$gte: new Date(start),
|
|
$lt: new Date(end)
|
|
}
|
|
}, {sort: {datetime: 1}}).toArray();
|
|
} catch (e) {
|
|
console.log('readRadiationMovingAverage',e);
|
|
return [];
|
|
}
|
|
if (docs.length == 0) {
|
|
return [];
|
|
} else {
|
|
let d = await util.calcMovingAverage(db, sid, docs, average , false, factor);
|
|
return d.RAD;
|
|
}
|
|
}
|
|
|
|
async function readRadiationAverages(db, sid, start, end, average, factor) {
|
|
let docs = [];
|
|
let collection = db.collection('radioactivity_sensors');
|
|
try {
|
|
docs = await collection.aggregate([
|
|
{$match: {sensorid: sid, datetime: {$gte: new Date(start), $lt: new Date(end)}}},
|
|
{$sort: {datetime: 1}},
|
|
{
|
|
$group: {
|
|
_id: {
|
|
$toDate: {
|
|
$subtract: [
|
|
{$toLong: '$datetime'},
|
|
{$mod: [{$toLong: '$datetime'}, 1000 * 60 * average]} // aggregate every average minutes
|
|
]
|
|
}
|
|
},
|
|
cpmAvg: {$avg: '$values.counts_per_minute'},
|
|
cpmSum: {$sum: '$values.counts_per_minute'},
|
|
count: {$sum: 1}
|
|
}
|
|
},
|
|
{ $addFields: { uSvphAvg: { $multiply: ["$cpmAvg", factor]}}},
|
|
{$sort: {_id: 1}}
|
|
]).toArray();
|
|
}
|
|
catch(e) {
|
|
console.log('readRadiationAverages', e);
|
|
return [];
|
|
}
|
|
return docs;
|
|
}
|
|
|
|
async function readClimateAverages(db, sid, start, end, average) {
|
|
let docs = [];
|
|
let collection = db.collection('thp_sensors');
|
|
try {
|
|
docs = await collection.aggregate([
|
|
{$match: {sensorid: sid, datetime: {$gte: new Date(start), $lt: new Date(end)}}},
|
|
{$sort: {datetime: 1}},
|
|
{
|
|
$group: {
|
|
_id: {
|
|
$toDate: {
|
|
$subtract: [
|
|
{$toLong: '$datetime'},
|
|
{$mod: [{$toLong: '$datetime'}, 1000 * 60 * average]} // aggregate every average min
|
|
]
|
|
}
|
|
},
|
|
tempAvg: {$avg: '$values.temperature'}, // average over every 10min
|
|
humiAvg: {$avg: '$values.humidity'},
|
|
pressSeaAvg: {$avg: '$values.pressure_at_sealevel'},
|
|
count: {$sum: 1}
|
|
}
|
|
},
|
|
{$sort: {_id: 1}}
|
|
]).toArray();
|
|
}
|
|
catch(e) {
|
|
console.log('readClimateAverage', e);
|
|
return [];
|
|
}
|
|
return docs;
|
|
}
|
|
|
|
function calcTimeRange(st, range, live, avg) {
|
|
let start = moment(st);
|
|
let end = moment(st);
|
|
if(range == 1) { // one day
|
|
if (live == true) {
|
|
start.subtract(24, 'h');
|
|
start.subtract(avg, 'm');
|
|
} else {
|
|
start.subtract(avg, 'm');
|
|
end.add(24, 'h');
|
|
}
|
|
} else if (range == 7) { // one week (7 days)
|
|
if (live == true) {
|
|
start.subtract(24 * 8, 'h');
|
|
} else {
|
|
start.subtract(24 * 8, 'h');
|
|
// end.add(24 * 7, 'h');
|
|
console.log(start.format(), end.format());
|
|
}
|
|
} else if (range == 31) { // one month (31 days)
|
|
start=start.startOf('day');
|
|
end = end.startOf('day');
|
|
start.subtract(33, 'd');
|
|
} else if (range >= 48) { // 48 hours
|
|
if(live == true) {
|
|
start.subtract(range, 'h')
|
|
}
|
|
}
|
|
return { start: start, end: end };
|
|
}
|
|
|
|
// get data for one day, one week or one month from the database
|
|
async function getDWMData(db, sensorid, st, avg, live, doMoving, span, longAVG) {
|
|
let docs = [];
|
|
let ret = {radiation: [], climate: []};
|
|
// first fetch properties for this sensor
|
|
let properties = await getSensorProperties(db,sensorid);
|
|
// calculate time range
|
|
let timerange = calcTimeRange(st, span, live, avg);
|
|
for (let n = 0; n<properties.othersensors.length; n++) {
|
|
let sid = properties.othersensors[n].sid;
|
|
let sname = properties.othersensors[n].name;
|
|
try {
|
|
if (sname.startsWith("Radiation")) {
|
|
let factor = sv_factor[sname.substring(10)] / 60;
|
|
if(doMoving) {
|
|
docs = await readRadiationMovingAverage(db, sid, timerange.start, timerange.end, avg, factor);
|
|
} else {
|
|
docs = await readRadiationAverages(db, sid, timerange.start, timerange.end, avg, factor);
|
|
}
|
|
let avg48 = null;
|
|
if (longAVG != undefined) {
|
|
let tr = calcTimeRange(st, longAVG, true, avg);
|
|
let avg48_docs = await readRadiationAverages(db, sid, tr.start, tr.end, longAVG*60, factor);
|
|
avg48 = avg48_docs[0];
|
|
}
|
|
ret['radiation'] = {sid: sid, sname: sname, avg48: avg48, values: docs};
|
|
} else if (sname == "BME280") {
|
|
docs = await readClimateAverages(db, sid, timerange.start, timerange.end, 10);
|
|
if (docs.length != 0) {
|
|
ret['climate'] = {sid: sid, sname: sname, values: docs};
|
|
}
|
|
} else {
|
|
ret['error'] = "Sensor not of right type (unknown)";
|
|
}
|
|
} catch (e) {
|
|
console.log('getDayData', e);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// für die Wochenanzeige die Daten als gleitenden Mittelwert über 24h durchrechnen
|
|
// ===============================================================
|
|
// PM (FEINSTAUB) FUNCTIONS REMOVED - Not needed in new DB
|
|
// ===============================================================
|
|
/*
|
|
// und in einem neuen Array übergeben
|
|
function movAvgSDSWeek(data) {
|
|
var neuData = [];
|
|
const oneDay = 3600*24;
|
|
|
|
// first convert date to timestam (in secs)
|
|
for (var i=0; i<data.length; i++) {
|
|
data[i].datetime = ( new Date(data[i].datetime)) / 1000; // the math does the convertion
|
|
}
|
|
|
|
// now calculate the moving average over 24 hours
|
|
let left=0, roll_sum=0, nd = [];
|
|
for (let right =0; right < data.length; right++) {
|
|
// if(right == 200) {
|
|
// console.log("right = 200");
|
|
// }
|
|
|
|
if(data[right].P1 != undefined) {
|
|
roll_sum += data[right].P1;
|
|
}
|
|
if(data[right].P10 != undefined) {
|
|
roll_sum += data[right].P10;
|
|
}
|
|
|
|
while( data[left].datetime <= data[right].datetime - oneDay) {
|
|
if(data[left].P1 != undefined) {
|
|
roll_sum -= data[left].P1;
|
|
}
|
|
if(data[left].P10 != undefined) {
|
|
roll_sum -= data[left].P10;
|
|
}
|
|
left += 1;
|
|
}
|
|
nd[right] = { 'P1024': roll_sum/ (right-left+1)+5};
|
|
}
|
|
|
|
for (var i=1, j=0; i< data.length; i++, j++) {
|
|
var sum1=0, sum2 = 0, cnt1 = 0, cnt2 = 0;
|
|
var di = data[i].datetime;
|
|
for (var k=i; k>=0 ; k--) {
|
|
if (data[k].datetime+oneDay < di) {
|
|
break;
|
|
}
|
|
if (data[k].P1 !== undefined) {
|
|
sum1 += data[k].P1;
|
|
cnt1++;
|
|
}
|
|
if (data[k].P2 !== undefined) {
|
|
sum2 += data[k].P2;
|
|
cnt2++;
|
|
}
|
|
if (data[k].P10 !== undefined) {
|
|
sum1 += data[k].P10;
|
|
cnt1++;
|
|
}
|
|
if (data[k].P2_5 !== undefined) {
|
|
sum2 += data[k].P2_5;
|
|
cnt2++;
|
|
}
|
|
}
|
|
neuData[j] = {'P10': sum1 / cnt1, 'P2_5': sum2 / cnt2, 'date': data[i].datetime} ;
|
|
}
|
|
// finally shrink datasize, so that max. 1000 values will be returned
|
|
var neu1 = [];
|
|
var step = Math.round(neuData.length / 500);
|
|
// if (step == 0) step = 1;
|
|
step = 1;
|
|
for (var i = 0, j=0; i < neuData.length; i+=step, j++) {
|
|
var d = neuData.slice(i,i+step)
|
|
var p1=0, p2=0;
|
|
for(var k=0; k<d.length; k++) {
|
|
if (d[k].P10 > p1) {
|
|
p1 = d[k].P10;
|
|
}
|
|
if (d[k].P2_5 > p2) {
|
|
p2 = d[k].P2_5;
|
|
}
|
|
}
|
|
neu1[j] = {'P10': p1, 'P2_5': p2, 'date': neuData[i].date*1000} ;
|
|
}
|
|
return { 'ndold': neu1, 'ndnew': nd };
|
|
}
|
|
|
|
|
|
|
|
function calcMinMaxAvgSDS(data,isp10) {
|
|
var p1=[], p2=[];
|
|
for (var i = 0; i < data.length; i++) {
|
|
if (data[i].P10 != undefined) {
|
|
p1.push(data[i].P10);
|
|
}
|
|
if (data[i].P2_5 != undefined) {
|
|
p2.push(data[i].P2_5);
|
|
}
|
|
if (data[i].P1 != undefined) {
|
|
p1.push(data[i].P1);
|
|
}
|
|
if (data[i].P2 != undefined) {
|
|
p2.push(data[i].P2);
|
|
}
|
|
}
|
|
return {
|
|
'P10_max': mathe.max(p1),
|
|
'P2_5_max': mathe.max(p2),
|
|
'P10_min': mathe.min(p1),
|
|
'P2_5_min': mathe.min(p2),
|
|
'P10_avg' : mathe.mean(p1),
|
|
'P2_5_avg' : mathe.mean(p2) };
|
|
}
|
|
*/
|
|
|
|
function calcMinMaxAvgDHT(data) {
|
|
var t=[], h=[];
|
|
for (var i=0; i<data.length; i++) {
|
|
if(data[i].temperature != undefined) {
|
|
t.push(data[i].temperature);
|
|
}
|
|
if(data[i].humidity != undefined) {
|
|
h.push(data[i].humidity);
|
|
}
|
|
}
|
|
return {
|
|
'temp_max': mathe.max(t),
|
|
'humi_max': mathe.max(h),
|
|
'temp_min': mathe.min(t),
|
|
'humi_min': mathe.min(h),
|
|
'temp_avg' : mathe.mean(t),
|
|
'humi_avg' : mathe.mean(h) };
|
|
}
|
|
|
|
|
|
async function calcMinMaxAvgBMP(db, sid, data) {
|
|
var t = [], p = [];
|
|
for (var i = 0; i < data.length; i++) {
|
|
if (data[i].temperature != undefined) {
|
|
t.push(data[i].temperature);
|
|
}
|
|
if (data[i].pressure != undefined) {
|
|
p.push(data[i].pressure);
|
|
}
|
|
}
|
|
let altitude = await util.getAltitude(db, sid);
|
|
p = util.calcSealevelPressure(p, '', altitude);
|
|
return {
|
|
'temp_max': mathe.max(t), 'press_max': mathe.max(p),
|
|
'temp_min': mathe.min(t), 'press_min': mathe.min(p),
|
|
'temp_avg': mathe.mean(t), 'press_avg': mathe.mean(p)
|
|
};
|
|
}
|
|
|
|
async function calcMinMaxAvgBME(db, sid, data) {
|
|
var t = [], h = [], p = [], sumt = 0;
|
|
for (var i = 0; i < data.length; i++) {
|
|
if (data[i].temperature != undefined) {
|
|
t.push(data[i].temperature);
|
|
}
|
|
if (data[i].humidity != undefined) {
|
|
h.push(data[i].humidity);
|
|
}
|
|
if (data[i].pressure != undefined) {
|
|
p.push(data[i].pressure);
|
|
}
|
|
}
|
|
let altitude = await util.getAltitude(db, sid);
|
|
p = util.calcSealevelPressure(p, '', altitude);
|
|
return {
|
|
'temp_max': mathe.max(t), 'humi_max': mathe.max(h), 'press_max': mathe.max(p),
|
|
'temp_min': mathe.min(t), 'humi_min': mathe.min(h), 'press_min': mathe.min(p),
|
|
'temp_avg': mathe.mean(t), 'humi_avg': mathe.mean(h), 'press_avg': mathe.mean(p)
|
|
};
|
|
}
|
|
|
|
/* PM (FEINSTAUB) FUNCTIONS REMOVED
|
|
function isPM(name) {
|
|
if ((name == "SDS011") || (name.startsWith("PPD")) || (name.startsWith("PMS"))) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Statistiken für den Sensor holen und übergeben - PM only
|
|
async function getStatistics(db,sensorid) {
|
|
// REMOVED - Was PM-specific
|
|
return { error: 'PM statistics removed in new DB' };
|
|
}
|
|
*/
|
|
|
|
|
|
module.exports = router;
|