"use strict"; import { BASE_URL, QUERY_PARAMS_COMBINED, getDatastreamIdFromBuildingNumber, createObservationsUrl, performGetRequestUsingAxios, extractCombinedObservationsFromAllPages, } from "./appChart.js"; /** * Create 24-hour time strings for a time interval delimited by a start time and an end time. It is assumed that the start time is at "00:00:00" and the end time is at "23:45:00" (when the sampling rate of observations is 15 min) or "23:00:00" (when the sampling rate of observations is 60 min) * @param {String} phenomenonSamplingRate The sampling rate of the phenomenon of interest represented as a string, e.g. "15 min", "60 min" * @returns {Array} An array of two 24-hour strings representing the start time and end time */ const createTimeStringsForInterval = function (phenomenonSamplingRate) { const fifteenMinutes = "15 min"; const sixtyMinutes = "60 min"; const startTime = "00:00:00"; const endTimeFifteenMinutes = "23:45:00"; const endTimeSixtyMinutes = "23:00:00"; if ( phenomenonSamplingRate !== fifteenMinutes && phenomenonSamplingRate !== sixtyMinutes ) return; // 15 min sampling rate if (phenomenonSamplingRate === fifteenMinutes) { return [startTime, endTimeFifteenMinutes]; } // 60 min sampling rate if (phenomenonSamplingRate === sixtyMinutes) { return [startTime, endTimeSixtyMinutes]; } }; /** * Create an ISO 8601 date and time string * @param {String} inputCalendarDate Calendar date string in "YYYY-MM-DD" format * @param {String} inputTwentyFourHourTime 24-hour time string in "hh:mm:ss" format * @returns {String} An ISO 8601 date and time string */ const createIso8601DateTimeString = function ( inputCalendarDate, inputTwentyFourHourTime ) { return `${inputCalendarDate}T${inputTwentyFourHourTime}.000Z`; }; /** * Calculate the index of a timestamp in an array of timestamps * @param {Array} inputTimestampArr An array of timestamps, extracted from an array of observations * @param {String} timestampOfInterest A string representing the timestamp of interest in ISO 8601 format * @returns {Number} An integer representing the index of the timestamp of interest in the array of timestamps */ const getIndexOfTimestamp = function (inputTimestampArr, timestampOfInterest) { const timestampIndex = inputTimestampArr.findIndex( (timestamp) => timestamp === timestampOfInterest ); // If the timestamp does not exist in the timestamp array if (timestampIndex === -1) throw new Error( "A start or end timestamp could not be found in the timestamp array" ); // If the timestamp exists in the timestamp array return timestampIndex; }; /** * Aggregate observations within a time interval delimited by a start date and end date. The start date may be the same as the end date. * @param {Array} obsArray An array of observations (timestamp + value) that is response from SensorThings API * @param {String} samplingRate The sampling rate of observations as a string, e.g. "15 min", "60 min" * @param {String} startDate A 24-hour date string representing the start date * @param {String} endDate A 24-hour date string representing the end date * @returns {Number} A floating-point number representing the aggregated observation value */ const aggregateObservationsWithinTimeInterval = function ( obsArray, samplingRate, startDate, endDate ) { // Extract the timestamps and values from the observations const obsTimestampArr = obsArray.map((obs) => obs[0]); const obsValuesArr = obsArray.map((obs) => obs[1]); // Create array of 24-hour strings for the start and end of interval const startPlusEndTimeStrings = createTimeStringsForInterval(samplingRate); // Extract 24-hour strings for the start and end of interval const [startTimeString, endTimeString] = startPlusEndTimeStrings; // Create ISO 8601 strings for the start and end of interval const startIso8601DateTimeString = createIso8601DateTimeString( startDate, startTimeString ); const endIso8601DateTimeString = createIso8601DateTimeString( endDate, endTimeString ); // Calculate the indexes of the timestamps for the start and end of interval const indexStartTimestamp = getIndexOfTimestamp( obsTimestampArr, startIso8601DateTimeString ); const indexEndTimestamp = getIndexOfTimestamp( obsTimestampArr, endIso8601DateTimeString ); // Extract the observations that fall within our time interval const obsValuesForTimeIntervalArr = obsValuesArr.slice( indexStartTimestamp, indexEndTimestamp + 1 ); // Calculate the aggregated observation value const aggregatedObsValue = obsValuesForTimeIntervalArr.reduce( (accumulator, currentValue) => accumulator + currentValue ); return aggregatedObsValue; }; /** * Test aggregation of observations from a single datastream */ const testAggregation = async function () { // Datastream ID const datastreamIdBau225VL = getDatastreamIdFromBuildingNumber( "225", "vl", "60min" ); // Observations URL const observationsUrlBau225VL = createObservationsUrl( BASE_URL, datastreamIdBau225VL ); // Observations array const observationsBau225VL = await extractCombinedObservationsFromAllPages( performGetRequestUsingAxios(observationsUrlBau225VL, QUERY_PARAMS_COMBINED) ); // Aggregated observations const observationsBau225VLAggregated = aggregateObservationsWithinTimeInterval( observationsBau225VL, "60 min", "2020-02-01", "2020-03-31" ); // console.log(observationsBau225VLAggregated); }; // testAggregation();