/** * * @param {JSON} obj JSON object on which to replace a specific key. * @param {String} oldKey is the old key in the JSON to be renamed to newKey * @param {String} newKey is the key that should replace the oldKey * usage: myjson.forEach((obj) => renameKey(obj, "oldkey", "newkey")); */ function renameKey(obj, oldKey, newKey) { obj[newKey] = obj[oldKey]; delete obj[oldKey]; } /** * * @param {Array} arr is the Array to be converted into a JSON * @returns {JSON} stringToJsonObject */ function convertArray2JSON(arr) { var arrayToString = JSON.stringify(Object.assign({}, arr)); // convert array to string var stringToJsonObject = JSON.parse(arrayToString); // convert string to json object return stringToJsonObject; } function createDateFromDateTimeString(jsonData) { let datx = []; let daty = []; const MONTH = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; for (var u = 0; u < jsonData.length; u++) { daty.push(jsonData[u].temperature); let date = new Date(jsonData[u].datetime); let datum = date.getDate(); let month = MONTH[date.getMonth()]; let hour = date.getHours() + ":00"; let newDateStr = datum + "/" + month + "-" + hour; datx.push(newDateStr); } return [datx, daty]; } /** * Format the response from SensorThings API to make it suitable for heatmap * @param {Array} obsArray Response from SensorThings API as array * @param {Int8} hours Number of hours to aggregate over. If hours=0, * it will be aggregated by date (e.g. all values recorded on 1st of May etc...) * if hours to any number (also hours=24) data will be aggregated over every 24hours, * even if the date changes (e.g. data from 1st of May from 10pm up 9pm on 2nd of May etc.) * @param {String} method Specify how to aggregate date. Use: 'mean' = default, 'sum', 'min' or 'max' * @returns {Array} Aggregated Response */ export const aggregateResponse = function(obsArray, hours, method) { if (!obsArray) return; if (hours < 0) return; // check if we have a defined method or the method specified is accepted, rest is handeled in switch/case below if (method == undefined) method = 'mean'; // convert obsArray to json let jsonFromArr = []; for (var i = 0; i < obsArray.length; i++) { jsonFromArr.push(convertArray2JSON(obsArray[i])); } // rename the keys in the jason jsonFromArr.forEach((obj) => renameKey(obj, "0", "datetime")); let jsonData = jsonFromArr; jsonData.forEach((obj) => renameKey(obj, "1", "temperature")); let newOutput = []; var aggDates = []; var aggregatedVals = []; var vals = []; // store values temporarily to use for processing if (hours == 0) { // i.e. aggregate over one Date / Day var currentDate; var oldDate; for (var d = 0; d < jsonData.length; d++) { let tmpDate = new Date(jsonData[d].datetime); currentDate = tmpDate.getDate(); // gets the day of the month 1...31 if (d === 0) oldDate = currentDate; if (currentDate == oldDate) { vals.push(jsonData[d].temperature); } else { aggDates.push(new Date(tmpDate - 1)); if (vals.length == 0) { aggregatedVals.push(-1); oldDate = currentDate; continue; } switch (method) { case 'mean': aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0)); break; case 'sum': aggregatedVals.push(vals.reduce(function(a, b) { return a + b; }, 0)); break; case 'min': aggregatedVals.push(vals.reduce(function(a, b) { return Math.min(a, b); })); break; case 'max': aggregatedVals.push(vals.reduce(function(a, b) { return Math.max(a, b); })); break; default: aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0)); } vals = []; // clear the daily value vector vals.push(jsonData[d].temperature); // now push first entry of new day into my temp value vector. } oldDate = currentDate; } // end of for loop // create output to be in the same List format as the original data from obsArray. for (let i = 0; i < aggregatedVals.length; i++) { newOutput.push([aggDates[i].toISOString(), aggregatedVals[i]]); } } else { // i.e. aggregate over X hours, irrespective of the day. let cnt = 0; let cumHours = 0; for (var d = 0; d < jsonData.length; d++) { if (cnt < hours) { vals.push(jsonData[d].temperature); cnt++; } else { cumHours += cnt; cnt = 0; aggDates.push(cumHours); if (vals.length == 0) { aggregatedVals.push(-1); continue; } switch (method) { case 'mean': aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0)); break; case 'sum': aggregatedVals.push(vals.reduce(function(a, b) { return a + b; }, 0)); break; case 'min': aggregatedVals.push(vals.reduce(function(a, b) { return Math.min(a, b); })); break; case 'max': aggregatedVals.push(vals.reduce(function(a, b) { return Math.max(a, b); })); break; default: aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0)); } vals = []; // clear the daily value vector vals.push(jsonData[d].temperature); // now push first entry of new day into my temp value vector. cnt++; } oldDate = currentDate; } // end of for loop // create output to be in the same List format as the original data from obsArray. for (let i = 0; i < aggregatedVals.length; i++) { newOutput.push([aggDates[i], aggregatedVals[i]]); } } // end else return newOutput; }