// get data for one sensor const DBASE = process.env.DBASE || 'mongo' import {DateTime} from "luxon" import * as influx from "../databases/influx.js" import * as mongo from "../databases/mongo.js" import {returnOnError} from "../utilities/reporterror.js" import {csv2Json} from "../utilities/csv2json.js" import checkParams from "../utilities/checkparams.js" import {getOneProperty} from "./getproperties.js" import {getNoiseData} from "../sensorspecials/noise.js" import {getgeigerData} from "../sensorspecials/geigeract.js" // Possible params for the different sensor types const noiseParams = [ {name:'data', type: 'string', default: 'live'}, {name: 'span', type: 'int', default: 1}, {name: 'daystart', type: 'bool', default: null}, {name: 'peak', type: 'int', default: 70}, {name: 'since', type: 'date', default: '1900-01-01T00:00:00Z'}, {name: 'box', type: 'array', default: null}, {name: 'out', type: 'string', default: ''}, {name: 'csv', type: 'bool', default: false}, {name: 'long', type: 'bool', default: false}, {name: 'sort', type: 'int', default: 1}, {name: 'last_seen', type: 'date', default: '1900-01-01T00:00:00Z'}, {name: 'datetime', type: 'date', default: null} ] const thpParams = [] const pmParams = [] const geigerParams = [ {name: 'what', type: 'string', default: 'day'}, {name: 'span', type: 'int', default: 1}, {name: 'daystart', type: 'bool', default: null}, {name: 'avg', type: 'int', default: 1}, {name: 'since', type: 'date', default: '1900-01-01T00:00:00Z'}, {name: 'box', type: 'array', default: null}, {name: 'out', type: 'string', default: ''}, {name: 'csv', type: 'bool', default: false}, {name: 'long', type: 'bool', default: false}, {name: 'sort', type: 'int', default: 1}, {name: 'last_seen', type: 'date', default: '1900-01-01T00:00:00Z'}, {name: 'datetime', type: 'date', default: null}, {name: 'moving', type: 'bool', default: false}, ] // >>>>>>>>>>>>>>>>>>>>> DUMMIES async function getPmData(opts) { } async function getThpData(opts) { } // <<<<<<<<<<<<<<<<<<<<< DUMMIES // Table for the different sensor types const sensorTypeTable = [ { typ: 'thp', possibleParams: thpParams, func: getThpData}, { typ: 'noise', possibleParams: noiseParams, func: getNoiseData}, { typ: 'pm', possibleParams: pmParams, func: getPmData}, { typ: 'radioactivity', possibleParams: geigerParams, func: getgeigerData} ] /* Units: * span -> days * avg -> minutes */ // ********************************************* // calcRange // // Calculate the date/time range ro read the data from // // If 'datetime' is not given, use 'now()' as end and 'now()' - span as start // If 'datetime' is given, use it as start and 'datetime'+span as end // If 'daystart'==true, change start and end so, that they begin at 00:00:00h // if 'avg' has a value, move start backward ba 'avg' minutes // // params: // opts: Object with different options, specially // datetime, avg, daystart, span // // return: // Object with start and stop in ISO-Format // ********************************************* export const calcRange = (opts) => { let start, end let ret = { start: start, stop: end, err: null} if((opts.datetime === null) || (opts.datetime === undefined) || (opts.datetime === '')) { start = end = DateTime.local().toUTC() start = start.minus({days: opts.span}) } else { start = end = DateTime.fromISO(opts.datetime).toUTC() end = end.plus({days: opts.span}) } if(opts.daystart) { start = start.startOf("day") end = end.startOf("day") } // start = start.toUTC() // end = end.toUTC() // if(opts.avg !== undefined) { // start = start.minus({minutes: opts.avg}) // } ret.start = `start: ${start.toISO()}` ret.stop = `stop: ${end.toISO()}` return ret } // ********************************************* // getSensorData // // Depending on the parameter 'sensorid', distribute to the special routines for // the sensors // // params: // params: all parameters from the url // // return: // Returns from the special routines // ********************************************* // export const getSensorData = async (params) => { export async function getSensorData(params) { let ret = {err: null} let {opts, err} = checkParams(params, { // check for sensorid mandatory: [{name: 'sensorid', type: 'int'}], optional: [] }) if (err) { return returnOnError(ret, err, getSensorData.name) } // with the sensorid get the type of this sensor let erg = await getOneProperty({sensorid: opts.sensorid}) if (erg.err) { return returnOnError(ret, erg.err, getSensorData.name) } // distribute to the right routine for(let item of sensorTypeTable) { if(item.typ === erg.props.type) { ret = await item.func(params, item.possibleParams, erg.props) // get the values from database return ret } } return returnOnError(ret, 'CMNDUNKNOWN', getActData.name) } // export const getActData = async (opts) => { export async function getActData(opts) { if (DBASE === 'mongo') { return await mongo.fetchActData(opts) } else if (DBASE === 'influx') { return await influx.fetchActData(opts) } return {err: 'DBASEUNKNOWN', values: []} } // ..../api/getavgdata? // ToDo: check UTC !!!! export var getAvgData = async (params) => { let ret = {data: {count: 0, values: []}, err: null} let {opts, err} = checkParams(params, { mandatory: [ {name: 'sensorid', type: 'int'}, ], optional: [ {name: 'span', type: 'int', default: 1}, {name: 'datetime', type: 'date', default: null}, {name: 'avg', type: 'int', default: 10}, {name: 'moving', type: 'bool', default: true}, ] } ) if (err) { return returnOnError(ret, err, getActdata.name) } let {start, stop} = calcRange(opts) if (stop === '') { ret.data.start = DateTime.now().toUTC().minus({days: `${opts.span}`}).toFormat("yyyy-LL-dd'T'HH:mm:ss'Z'") } else { ret.data.start = DateTime.fromISO(opts.datetime, {zone: 'utc'}).toISO() } ret.data.span = opts.span ret.data.moving = opts.moving ret.data.avg = opts.avg let every = opts.moving ? '150s' : `${opts.avg}m` let period = `${opts.avg}m` let query = ` from(bucket: "sensor_data") |> range(${start}, ${stop}) |> filter(fn: (r) => r.sid == "${opts.sensorid}") |> timedMovingAverage(every: ${every}, period: ${period}) |> keep(columns: ["_time","_field","_value"]) |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") ` return await fetchFromInflux(ret, query) } // ..../api/getlongavg?sensorid=123&span=2 export var getLongAvg = async (params) => { let ret = {data: {count: 0, values: []}, err: null} let {opts, err} = checkParams(params, { mandatory: [ {name: 'sensorid', type: 'int'}, ], optional: [ {name: 'span', type: 'int', default: 2}, ] } ) if (err) { return returnOnError(ret, err, getActdata.name) } ret.data.span = opts.span let query = ` from(bucket: "sensor_data") |> range(start: -${opts.span}d) |> filter(fn: (r) => r.sid == "${opts.sensorid}") |> mean() |> drop(columns: ["_start","_measurement", "sid"]) |> pivot(rowKey:["_stop"], columnKey: ["_field"], valueColumn: "_value") ` return await fetchFromInflux(ret, query) } // ********************************************* // function getMAPaktData() { // // Get the actual data from the database within the bounds for the given sensor typ // // params: // opt: opt.box => region for which to find sensor data // opt.typ: type of sensor // // return // JSON // { avgs: [ // { location: [ 9.00, 48.80 ], id: 29174, lastSeen: "2019-10-23T12:03:00.000Z", max: "65" } // { location: [ 9.10, 49.80 ], id: 28194, lastSeen: "2019-10-22T16:03:00.000Z", max: "45" } // ......... // ], lastDate: "2019-10-29T15:05:59.000Z" } // // ********************************************* export const getMAPaktData = async (opt) => { let box = opt.box if ((box == "") || (box == undefined)) { return {"avgs": [], "lastDate": null} } let south = parseFloat(box[0][1]) let north = parseFloat(box[1][1]) let east = parseFloat(box[1][0]) let west = parseFloat(box[0][0]) let aktData = [] let lastDate = 0 let loc = { location: { $geoWithin: { $box: [ [west, south], [east, north] ] } }, typ: opt.typ, } let docs = await mongo.readMapdata(loc,0) // console.log(docs) for (let i = 0;i < docs.length; i++) { let item = docs[i] let oneAktData = {} oneAktData['location'] = item.location.coordinates oneAktData['id'] = item._id // ID des Sensors holen oneAktData['lastSeen'] = item.values.datetime oneAktData['indoor'] = item.indoor let dati = item.values.datetime let dt = new Date(dati) if ((now - dt) >= 31 * 24 * 3600 * 1000) { // älter als 1 Monat -> oneAktData['noise_max'] = -2 // -2 zurückgeben } else if ((now - dt) >= 3600 * 1000) { // älter als 1 Stunde -> oneAktData['noise_max'] = -1 // -1 zurückgeben } else { oneAktData['noise_max'] = -5 // bedutet -> nicht anzeigen if (item.values.hasOwnProperty('LA_max')) { oneAktData['noise_max'] = item.values.LA_max.toFixed(0) // und merken } if (dati > lastDate) { lastDate = dati } } aktData.push(oneAktData) // dies ganzen Werte nun in das Array } return {"avgs": aktData, "lastDate": lastDate} // alles bearbeitet _> Array senden }