diff --git a/actions/data4map.js b/actions/data4map.js index 7ce7d64..d218e28 100644 --- a/actions/data4map.js +++ b/actions/data4map.js @@ -2,6 +2,7 @@ import {DateTime} from "luxon" import * as mongo from "../databases/mongo.js" import { returnOnError } from "../utilities/reporterror.js" +import { fetchLatestLAmaxForChips } from '../databases/influx_sql.js' // Default distance for center search ( in km) @@ -127,6 +128,8 @@ export var getData4map = async (params) => { } } } + // Nur Einträge verwenden, die eine ESP-Chipid haben + query.chip = { $exists: true } try { // fetch mapdata from mongodb let { properties, err } = await mongo.getallProperties(mongo.properties_collection, query) @@ -134,19 +137,26 @@ export var getData4map = async (params) => { return returnOnError(ret, 'NOPROPSFOUND', getData4map.name) } let v4map = getValue4Map(typ) + + const chipIds = properties.map(prop => prop.chip?.id).filter(id => id) + const result = await fetchLatestLAmaxForChips({ chipids: chipIds}) + for (let sensor of properties) { + const resIndex = result.values.findIndex((id) => id.chipid == sensor.chip.id) + const chpvalues = result.values[resIndex] let oneAktData = {} - if (sensor.values !== undefined) { + if (!((sensor.values === undefined) || (chpvalues === undefined))) { oneAktData = { location: sensor.location[0].loc.coordinates, id: sensor._id, - name: sensor.name[0].name, + name: sensor.chip.name, indoor: sensor.location[0].indoor, - lastseen: sensor.values.timestamp + lastseen: chpvalues.timestamp } let now = new Date().getTime() if(oneAktData.lastseen !== '') { - let diff = now - oneAktData.lastseen.getTime() + const dt = new Date(oneAktData.lastseen).getTime() + let diff = now - dt if (diff >= 365 * 24 * 3600 * 1000) { oneAktData.value = -4 } else if (diff >= 30 * 24 * 3600 * 1000) { @@ -156,15 +166,15 @@ export var getData4map = async (params) => { } else if (diff >= 2 * 3600 * 1000) { oneAktData.value = -1 } else { - if (sensor.values !== undefined) { - oneAktData.value = Math.round(sensor.values[v4map] * 100) / 100 + if (chpvalues !== undefined) { + oneAktData.value = Math.round(chpvalues[v4map] * 100) / 100 } } let weeks = Math.round(diff / (7 * 24 * 3600 * 1000)) oneAktData.weeks = weeks } - if (sensor.values.timestamp > lastDate) { - lastDate = sensor.values.timestamp + if (new Date(oneAktData.lastseen).getTime() > lastDate) { + lastDate = new Date(oneAktData.lastseen).getTime() } } else { oneAktData.value = -5 @@ -176,7 +186,7 @@ export var getData4map = async (params) => { ret = { err: null, options: { - lastdate: lastDate, + lastdate: new Date(lastDate).toISOString(), count: aktData.length, data: 'map' }, diff --git a/databases/influx_sql.js b/databases/influx_sql.js index dd96146..5ed48d0 100644 --- a/databases/influx_sql.js +++ b/databases/influx_sql.js @@ -144,9 +144,11 @@ const transformInfluxResult = (series) => { if (col === 'time') { // Convert timestamp to ISO string for compatibility record.datetime = new Date(row[index]).toISOString() - } else { + } else if (col.startsWith('DNMS')) { col = col.slice(11) record[col] = row[index] + } else { + record[col] = row[index] } }) result.push(record) @@ -423,5 +425,83 @@ export const fetchNoiseAVGData = async (opts) => { return ret } +/** + * Fetch latest LA_max values for multiple chip IDs + * @param {Object} opts - Options object + * @param {Array} opts.chipids - Array of chip IDs + * @returns {Object} - {err: null, values: [{chipid, LA_max, timestamp}]} + */ +export const fetchLatestLAmaxForChips = async (opts) => { + let ret = { err: null, values: [] } + + if (!opts.chipids || !Array.isArray(opts.chipids) || opts.chipids.length === 0) { + ret.err = 'No chip IDs provided' + logit(`ERROR ${fetchLatestLAmaxForChips.name}: ${ret.err}`) + return ret + } + + try { + // Build WHERE clause with multiple chip IDs using OR (InfluxQL doesn't support IN) + const chipIdConditions = opts.chipids.map(id => `"node" = '${id}'`).join(' OR ') + + // Query to get latest LA_max for each chip + const query = `SELECT "DNMS_noise_LA_max", "node" FROM "DNMS" WHERE (${chipIdConditions}) AND time >= now() - 24h ORDER BY time DESC` + + let { values: lamaxValues, err: lamaxErr } = await influxRead(query) + if (lamaxErr) { + ret.err = lamaxErr.toString() + logit(`ERROR ${fetchLatestLAmaxForChips.name}: ${ret.err}`) + return ret + } + + if (!lamaxValues || !lamaxValues.length || !lamaxValues[0].series) { + ret.err = 'NODATA' + logit(`ERROR ${fetchLatestLAmaxForChips.name}: No data returned from query`) + return ret + } + + // Transform results + const allData = transformInfluxResult(lamaxValues[0].series) + + // Get latest value for each chip (data is already sorted by time DESC) + const latestByChip = {} + + allData.forEach(record => { + const chipid = record.node + const lamax = record.LA_max + + // Only keep the first (latest) value for each chip + if (!latestByChip[chipid] && lamax !== null && lamax !== undefined) { + latestByChip[chipid] = { + chipid: chipid, + LA_max: lamax, + timestamp: record.datetime + } + } + }) + + // Convert to array + ret.values = Object.values(latestByChip) + + // Add null entries for chips without data + opts.chipids.forEach(chipid => { + if (!latestByChip[chipid]) { + ret.values.push({ + chipid: chipid, + LA_max: null, + timestamp: null + }) + } + }) + + } catch (e) { + ret.err = e.toString() + logit(`ERROR ${fetchLatestLAmaxForChips.name}: ${ret.err}`) + return ret + } + + return ret +} + // Export write function for compatibility export { influxWrite }