Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
70c4e39
updated layout for create a conversion modal, changed scripts from CR…
minhtriet359 Jun 30, 2025
9c1f31d
Created meter_hourly_readings_unit view, added new version of meter_l…
tdthompson650 Jun 30, 2025
b2836b9
Merge branch 'oed-csumb-su25:development' into views
tdthompson650 Jun 30, 2025
a47072c
Created meter_daily_readings_unit view, altered meter_line_readings_u…
tdthompson650 Jul 1, 2025
a460009
Created new function meter_bar_readings_unit_v2 that uses the meter_d…
tdthompson650 Jul 2, 2025
31bfa16
Created new function meter_3d_readings_unit_v2 that uses the meter_ho…
tdthompson650 Jul 2, 2025
85979ea
Created new function meter_compare_readings_unit_v2 that uses the met…
tdthompson650 Jul 4, 2025
de6ee87
changed state in create conversion modal to be compitable with new up…
minhtriet359 Jul 7, 2025
ffaf4a9
created an overview page for daily patterns
minhtriet359 Jul 8, 2025
e72bbd7
changed component folder name from days to daily-pattern
minhtriet359 Jul 8, 2025
2a94037
Added an index to both meter_hourly_readings_unit and meter_daily_rea…
tdthompson650 Jul 9, 2025
85fe904
Added new meter_hourly view for time varying conversions.
tdthompson650 Jul 10, 2025
f6af041
Meter hourly time varying conversions are complete, changes were merg…
tdthompson650 Jul 11, 2025
82d411d
added function meter_hourly_readings_unit_vB which is hourly_readings…
LeSci Jul 13, 2025
e437035
Initial UI for the weekly conversion patterns feature
evan-carey Jul 13, 2025
f432522
modified meter_daily_readings_unit to get it's data from meter_hourly…
tdthompson650 Jul 16, 2025
6bc1661
Merge branch 'views' of https://github.com/oed-csumb-su25/OED-backend…
tdthompson650 Jul 16, 2025
d858087
update error in hourly_readings_unit and modified meter_hourly_readin…
LeSci Jul 17, 2025
69e9433
Merge branch 'oed-csumb-su25:development' into evan-carey/weekly-pattern
evan-carey Jul 19, 2025
9f65376
feat(weeks): add help tooltips to week views; change /weeks page link…
evan-carey Jul 19, 2025
f4a0cc5
Merge remote-tracking branch 'oed-backend/taliaBranch' into evan-care…
evan-carey Jul 19, 2025
47b3130
feat(weeks): complete weekly conversion patterns feature
evan-carey Jul 23, 2025
6af16b5
Merge remote-tracking branch 'oed-backend/taliaBranch' into evan-care…
evan-carey Jul 23, 2025
8835272
fix(weeks): create week API request fails because `id` is included
evan-carey Jul 23, 2025
dbfd046
revert changes to gitignore and docker-compose
evan-carey Jul 23, 2025
63deb77
fix(database): weeks table must be created before conversion_segments…
evan-carey Jul 23, 2025
b9d892f
update meter_hourly_readings_unit_vB
LeSci Jul 23, 2025
70addde
Updated meter_line_readings_unit_v3 function so that it can handle ti…
tdthompson650 Jul 24, 2025
2271086
Merge branch 'views' of https://github.com/oed-csumb-su25/OED-backend…
tdthompson650 Jul 24, 2025
92bd352
undo formatting changes to docker-compose
evan-carey Jul 26, 2025
109fd51
undo formatting change to docker-compose
evan-carey Jul 26, 2025
026b882
Address code review comments for Weeks feature
evan-carey Jul 26, 2025
22ee2c1
Revert docker-compose.yml to match development branch
evan-carey Jul 26, 2025
c3a6cdb
fix(weeks): WeeksDetailComponent does not need a loading spinner
evan-carey Jul 29, 2025
505b1d9
Meter_hourly_readings_unit view is no longer dependent on old hourly …
tdthompson650 Jul 30, 2025
c9d87fc
Merge pull request #1 from oed-csumb-su25/evan-carey/weeks-api
evan-carey Jul 31, 2025
3dfa0c6
Deleted old functions, did some reformatting.
tdthompson650 Jul 31, 2025
4c9c876
Merge branch 'oed-csumb-su25:development' into views
tdthompson650 Aug 1, 2025
e224fc8
Updated the meter_raw_readings_unit view, it should not contain all t…
tdthompson650 Aug 2, 2025
bb8cc15
Created new view meter_hourly_readings_unit_v3, this view aggregates …
tdthompson650 Aug 3, 2025
6c78d8f
Added comments, made sure all comments were on their own line (not tr…
tdthompson650 Aug 6, 2025
a379f72
Merge branch 'development' into development
minhtriet359 Aug 7, 2025
64f4263
Moved the raw view above the hourly view.
tdthompson650 Aug 14, 2025
b7122ed
removed/commented out unused views
tdthompson650 Aug 22, 2025
4ae2ff6
Removed an old view, created a new houlry view that uses a CTEand onl…
tdthompson650 Aug 23, 2025
75b97e6
Merge remote-tracking branch 'wendys/views' into views
tdthompson650 Aug 30, 2025
93f8f25
moddified group views to get data from new meter views so that they n…
tdthompson650 Aug 30, 2025
dec8814
Get most tests to work with time varying
huss Sep 3, 2025
639da64
removed old/unused views, added comments, renamed g_unit_id to passed…
tdthompson650 Sep 6, 2025
f01d4fd
formating
tdthompson650 Sep 6, 2025
2fe7f64
Fixed a couple bugs that were causing some test to not pass
tdthompson650 Sep 22, 2025
0b5f2ff
Migration
tdthompson650 Sep 29, 2025
2f6e990
Modified the migration
tdthompson650 Oct 17, 2025
e29aadf
Merge remote-tracking branch 'upstream/development' into views
tdthompson650 Nov 23, 2025
557eb87
Revert "Merge remote-tracking branch 'upstream/development' into views"
tdthompson650 Dec 2, 2025
2e44e7d
resolved most PR comments
tdthompson650 Dec 2, 2025
bd16d72
address some comments/minor
huss Dec 8, 2025
8d0399f
Merge remote-tracking branch 'origin/timeVary' into pr/tdthompson650/…
huss Dec 18, 2025
992be3c
correct that no rows possible in query
huss Dec 18, 2025
eda0555
basic working with cik_vary
huss Dec 19, 2025
6b5cecb
try to fix merge issues
huss Dec 19, 2025
3de8fb1
fix sql for and conversion test for cik_vary
huss Dec 19, 2025
5bb82b7
fix cik create & compareTest
huss Dec 19, 2025
58ba7e8
use cikVary not cik
huss Dec 19, 2025
998ba2b
fix suffix units
huss Dec 20, 2025
f976fef
3D group fixed & all tests passing
huss Dec 20, 2025
d17a419
fix testData so refresh views
huss Dec 20, 2025
3a6293a
Update cik
huss Dec 22, 2025
a6865d5
update migrations
huss Dec 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"refreshDailyReadingViews": "node -e 'require(\"./src/server/services/refreshReadingViews\").refreshReadingViews()'",
"refreshHourlyReadingViews": "node -e 'require(\"./src/server/services/refreshHourlyReadingViews\").refreshHourlyReadingViews()'",
"refreshGroupsDeepMeters": "node -e 'require(\"./src/server/services/refreshGroupsDeepMetersView\").refreshGroupsDeepMetersView()'",
"updateCikAndViews": "node -e 'require(\"./src/server/services/graph/redoCik.js\").updateCikAndViews()'",
"updateCikAndViews": "node -e 'require(\"./src/server/services/graph/redoCik.js\").updateCikVaryAndViews()'",
"obvius:showConfigfiles": "node ./src/server/services/obvius/showConfigfiles.js",
"obvius:purgeConfigfiles": "node ./src/server/services/obvius/purgeConfigfiles.js",
"generateFourDayTestingData": "node -e 'require(\"./src/server/data/automatedTestingData\").generateFourDayTestingData()'",
Expand Down
2 changes: 0 additions & 2 deletions src/client/app/types/redux/ciks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@
export interface CikData {
meterUnitId: number;
nonMeterUnitId: number;
slope: number;
intercept: number;
}
14 changes: 8 additions & 6 deletions src/server/data/automatedTestingData.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

const { generateSine, generateCosine } = require('./generateTestingData');
const Unit = require('../models/Unit');
const Group = require('../models/Group');
const { insertUnits, insertStandardUnits, insertConversions, insertStandardConversions, insertMeters, insertGroups } = require('../util/insertData');
const { getConnection } = require('../db');
const { redoCik } = require('../services/graph/redoCik');
const { redoCikVary } = require('../services/graph/redoCik');
const { refreshAllReadingViews } = require('../services/refreshAllReadingViews');
const fs = require('fs').promises;

// Define the start and end date for data generation.
const DEFAULT_OPTIONS = {
Expand Down Expand Up @@ -1335,18 +1335,20 @@ async function insertSpecialUnitsConversionsMetersGroups() {
await insertSpecialConversions(conn);
// Recreate the Cik entries since changed units/conversions.
// Do now since needed to insert meters with suffix units.
await redoCik(conn);
await redoCikVary(conn);
// Generate the mathematical test data needed.
console.log(`Start loading each set of test data into OED meters, may take minutes):\n`);
// This is very fast so wait since simpler and easier to see if this part fails.
await insertMeters(specialMeters, conn);
// Now do the large dataset generation.
await testData();
// Recreate the Cik entries since changed meters.
await redoCik(conn);
// Refresh the readings since added new ones.
await refreshAllReadingViews();
await redoCikVary(conn);
await insertGroups(specialGroups, conn);
// Refresh groups deep meters view after adding new groups.
await Group.refreshGroupsDeepMetersView(conn);
// Refresh the readings since added new ones & groups.
await refreshAllReadingViews();
}

/*
Expand Down
6 changes: 3 additions & 3 deletions src/server/data/websiteData.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

const Unit = require('../models/Unit');
const Group = require('../models/Group');
const { redoCik } = require('../services/graph/redoCik');
const { redoCikVary } = require('../services/graph/redoCik');
const { refreshAllReadingViews } = require('../services/refreshAllReadingViews');
const { getConnection } = require('../db');
const { insertUnits, insertStandardUnits, insertConversions, insertStandardConversions, insertMeters, insertGroups } = require('../util/insertData');
Expand Down Expand Up @@ -753,12 +753,12 @@ async function insertWebsiteData() {
await insertConversions(conversions, conn);
// Recreate the Cik entries since changed units/conversions.
// Do now since needed to insert meters with suffix units.
await redoCik(conn);
await redoCikVary(conn);
console.log(`Start loading each set of test data into OED meters (${meters.length} files of varying length, may take minutes):`);
// await Meter.insertMany(meters, conn);
await insertMeters(meters, conn);
// Recreate the Cik entries since changed meters.
await redoCik(conn);
await redoCikVary(conn);
await insertGroups(groups, conn);
// Refresh groups deep meters view after adding new groups.
await Group.refreshGroupsDeepMetersView(conn);
Expand Down
19 changes: 19 additions & 0 deletions src/server/migrations/2.0.0-3.0.0/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

const database = require('../../models/database');
const sqlFile = database.sqlFile;

module.exports = {
fromVersion: '2.0.0',
toVersion: '3.0.0',
up: async db => {
await db.none(sqlFile('../migrations/2.0.0-3.0.0/sql/cik/alter_cik_table.sql'));
await db.none(sqlFile('../migrations/2.0.0-3.0.0/sql/readings/drop_old_views.sql'));
await db.none(sqlFile('../migrations/2.0.0-3.0.0/sql/readings/create_reading_views.sql'));
await db.none(sqlFile('../migrations/2.0.0-3.0.0/sql/readings/create_function_get_3d_readings.sql'));
await db.none(sqlFile('../migrations/2.0.0-3.0.0/sql/readings/create_function_get_compare_readings.sql'));
}
};
10 changes: 10 additions & 0 deletions src/server/migrations/2.0.0-3.0.0/sql/cik/alter_cik_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

--Add the new columns with appropriate infinity defaults
ALTER TABLE cik
DROP COLUMN slope,
DROP COLUMN intercept
;
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

-- By indexing both columns together, the database can efficiently handle queries that involve both meter_id and time_interval.
-- Created to support the usage of the view by 3d.
-- TODO verify helps with newer views.
CREATE INDEX IF NOT EXISTS idx_meter_hourly_readings_unit_meter_time
ON meter_hourly_readings_unit (meter_id, lower(time_interval));
-- TODO How does this relate to index for same view in create_reading_views? Are both needed?
CREATE INDEX if not exists idx_two_group_hourly_readings_unit
ON group_hourly_readings_unit (group_id, graphic_unit_id, lower(time_interval));

/*
This takes tsrange_to_shrink which is the requested time range to plot and makes sure it does
not exceed the start/end times for the readings in the supplied meter. This can be an issue, in particular,
because infinity is used to indicate to graph all readings. This version does it to the nearest
day by using the day reading view and is used by 3D readings which only allow days and a single meter.
*/
CREATE OR REPLACE FUNCTION shrink_tsrange_to_meter_readings_by_day(tsrange_to_shrink TSRANGE, meter_id_desired INTEGER)
RETURNS TSRANGE
AS $$
DECLARE
readings_max_tsrange TSRANGE;
BEGIN
SELECT tsrange(min(lower(time_interval)), max(upper(time_interval))) INTO readings_max_tsrange
FROM meter_daily_readings_unit
where meter_id = meter_id_desired;
RETURN tsrange_to_shrink * readings_max_tsrange;
END;
$$ LANGUAGE 'plpgsql';

/* Similar to meter version but for a group */
CREATE OR REPLACE FUNCTION shrink_tsrange_to_group_readings_by_day(tsrange_to_shrink TSRANGE, group_id_desired INTEGER)
RETURNS TSRANGE
AS $$
DECLARE
readings_max_tsrange TSRANGE;
BEGIN
SELECT tsrange(min(lower(time_interval)), max(upper(time_interval))) INTO readings_max_tsrange
FROM group_daily_readings_unit
where group_id = group_id_desired;
RETURN tsrange_to_shrink * readings_max_tsrange;
END;
$$ LANGUAGE 'plpgsql';


-- Determines the spacing between 3D points. It uses the lowest one for all meters passed
-- that is valid.
CREATE OR REPLACE FUNCTION reading_interval_3d (
-- The desired meter ids.
IN meter_ids_requested INTEGER[],
-- The number of hours in each reading requested
IN reading_length_hours INTEGER,
-- The number of hours in each reading determined
OUT reading_length_hours_use INTEGER,
-- The number of hours in each reading determined as an interval
OUT reading_length_interval INTERVAL
)
AS $$
DECLARE
-- The meter frequency from all meters.
meter_frequency INTERVAL;
-- The meter frequency rounded up to a whole number of hours.
meter_frequency_hour_up INTEGER;
-- The larger of the meter value and the argument sent.
max_frequency INTEGER;
BEGIN
-- Get the smallest reading frequency for all meters requested.
SELECT min(reading_frequency) INTO meter_frequency
FROM (meters m
INNER JOIN unnest(meter_ids_requested) meters(id) ON m.id = meters.id);
-- Get the seconds in the frequency from epoch, /3600 To get hours and then round up to a whole number of hours.
meter_frequency_hour_up := CEIL((SELECT * FROM EXTRACT(EPOCH FROM meter_frequency)) / 3600);
-- Use the hours that is the largest of the request and the meter values.
max_frequency := GREATEST(meter_frequency_hour_up, reading_length_hours);
-- The value used must be a divisor of 24 or greater than 12.
IF (max_frequency = 5) THEN
reading_length_hours_use := 6;
ELSIF (max_frequency = 7) THEN
reading_length_hours_use := 8;
ELSIF (max_frequency > 8 AND max_frequency < 12) THEN
reading_length_hours_use := 12;
ELSE
reading_length_hours_use := max_frequency;
END IF;
-- Hours per reading determined returned as an interval.
reading_length_interval := (reading_length_hours_use::TEXT || ' hour')::INTERVAL;
END;
$$ LANGUAGE 'plpgsql';


-- Gets meters graphing data for 3D graphic by returning points that span the requested
-- length of time over the days requested.
-- New meter_3d_readings_unit function that uses new meter_hourly_readings_unit view.
CREATE OR REPLACE FUNCTION meter_3d_readings_unit (
-- The desired meter ids. It is normally a single value for a 3D graphic.
-- TODO Should the array be changed to a single value as with group? Need to be sure client never asks for multiple.
meter_ids_requested INTEGER[],
-- The desired graphic unit of the returned data
graphic_unit_id_requested INTEGER,
-- The start and end time for the data to return
start_stamp TIMESTAMP,
end_stamp TIMESTAMP,
-- The number of hours in each reading requested
reading_length_hours INTEGER
)
RETURNS TABLE(meter_id INTEGER, reading_rate FLOAT, start_timestamp TIMESTAMP, end_timestamp TIMESTAMP)
AS $$
DECLARE
-- Holds the range of dates for returned data that fits the actual data.
requested_range TSRANGE;
-- The number of hours in each reading determined as an interval
reading_length_interval INTERVAL;
-- Which index of the meter_id array you are currently working on.
current_meter_index INTEGER := 1;
-- The id of the meter index working on
current_meter_id INTEGER;
-- The meter frequency from all meters.
meter_frequency INTERVAL;
-- The meter frequency rounded up to a whole number of hours.
meter_frequency_hour_up INTEGER;
-- The larger of the meter value and the argument sent.
max_frequency INTEGER;
-- The number of hours in each reading determined
reading_length_hours_use INTEGER;
BEGIN
-- Find the correct number of hours per reading returned.
SELECT * from reading_interval_3d(meter_ids_requested, reading_length_hours) into reading_length_hours_use, reading_length_interval;

-- Loop over all meters.
WHILE current_meter_index <= cardinality(meter_ids_requested) LOOP
-- ID of the current meter in loop
current_meter_id := meter_ids_requested[current_meter_index];

-- Get the range of days requested by calling shrink_tsrange_to_meter_readings_by_day.
-- First make requested range only be full days by dropping any partial days at start/end.
requested_range := shrink_tsrange_to_meter_readings_by_day(tsrange(date_trunc_up('day', start_stamp), date_trunc('day', end_stamp)), current_meter_id);

IF (reading_length_hours_use <= 12) THEN
-- Need to generate_series to group the desired hours together
RETURN QUERY
-- The readings are rates in the hourly table so want to average not sum so
-- work for quantity, flow & raw.
-- The time starts at the time of the generated sequence and ends at the length
-- of each block later. This is the same as the start time of the next value
-- in the sequence (except last one).
SELECT
-- Modified to retrieve converted hourly readings from the materialized view.
mhr.meter_id as meter_id,
AVG(mhr.reading_rate) as reading_rate,
hours.hour AS start_timestamp,
hours.hour + reading_length_interval AS end_timestamp
-- This is the series that starts at the beginning of the desired days,
-- ends at the end of the desired days and steps by the desired interval.
-- You need to subtract from the last interval for the end since generate_series
-- is inclusive.
FROM (
SELECT hour
FROM generate_series(
lower(requested_range),
upper(requested_range) - reading_length_interval,
reading_length_interval
) hours(hour)
) hours(hour),
-- Also need the values in the meter hourly table.
meter_hourly_readings_unit mhr
-- Only want the desired meter
WHERE mhr.meter_id = current_meter_id
-- Only want the desired graphing unit
AND mhr.graphic_unit_id = graphic_unit_id_requested
-- Only want readings that lie within this slice of the desired data
AND lower(mhr.time_interval) >= hours.hour
AND upper(mhr.time_interval) <= hours.hour + reading_length_interval
-- ensures that the start of the reading time intervals does not exceed the end of the current generated interval
AND lower(mhr.time_interval) <= hours.hour + reading_length_interval
-- Group by the start time of the generated series since all points in
-- the desired slice have the same start time for the series.
-- Also group by the meter_id since Postgres wants and desired for graphing
GROUP BY hours.hour, mhr.meter_id
-- Time sort by the meter and start time for graphing.
ORDER BY mhr.meter_id, hours.hour
;
ELSE
-- The reading rate is more than 12 so return a single row with dummy values that easy to detect.
-- The end time differs from the start time by the meter reading frequency or min one for groups.
-- This means the meter reading frequency is too long for a 3D graphic.
RETURN QUERY
SELECT -999, -999::FLOAT, '1900-01-01 00:00:00'::TIMESTAMP, '1900-01-01 00:00:00'::TIMESTAMP + reading_length_interval
;
END IF;

-- Go to the next meter
current_meter_index := current_meter_index + 1;
END LOOP;
END;
$$ LANGUAGE plpgsql;

/* Gets group graphing data for 3D graphic by returning points that span the requested
length of time over the days requested.
*/
CREATE OR REPLACE FUNCTION group_3d_readings_unit (
--Desire group ID
--For 3D graphics, users will only be able to select 1 group to graph.
group_id_requested INTEGER,
-- The desired graphic unit of the returned data
graphic_unit_id_requested INTEGER,
-- The start and end time for the data to return
start_stamp TIMESTAMP,
end_stamp TIMESTAMP,
-- The number of hours in each reading requested
reading_length_hours INTEGER
)
RETURNS TABLE(reading_rate FLOAT, start_timestamp TIMESTAMP, end_timestamp TIMESTAMP)
AS $$
DECLARE
-- Holds the range of dates for returned data that fits the actual data.
requested_range TSRANGE;
--Holds the desired meter IDs in order to call meter_3d_readings_unit in the query below.
meter_ids INTEGER[];
-- The number of hours in each reading determined
reading_length_hours_use INTEGER;
-- The number of hours in each reading determined as an interval
reading_length_interval INTERVAL;
BEGIN
--Get all the meter IDS that will be included in the group being requested.
SELECT array_agg(DISTINCT gdm.meter_id) INTO meter_ids
FROM groups_deep_meters gdm
WHERE group_id = group_id_requested;

-- Find the correct number of hours per reading returned.
SELECT * from reading_interval_3d(meter_ids, reading_length_hours) into reading_length_hours_use, reading_length_interval;
-- Get the range of days requested by calling shrink_tsrange_to_group_readings_by_day.
-- First make requested range only be full days by dropping any partial days at start/end.
requested_range := shrink_tsrange_to_group_readings_by_day(tsrange(date_trunc_up('day', start_stamp), date_trunc('day', end_stamp)), group_id_requested);

IF (reading_length_hours_use <= 12) THEN
-- Need to generate_series to group the desired hours together
RETURN QUERY
-- The readings are rates in the hourly table so want to average not sum so
-- work for quantity, flow & raw.
-- The time starts at the time of the generated sequence and ends at the length
-- of each block later. This is the same as the start time of the next value
-- in the sequence (except last one).
SELECT
AVG(ghr.reading_rate) as reading_rate,
hours.hour AS start_timestamp,
hours.hour + reading_length_interval AS end_timestamp
-- This is the series that starts at the beginning of the desired days,
-- ends at the end of the desired days and steps by the desired interval.
-- You need to subtract from the last interval for the end since generate_series
-- is inclusive.
FROM (
SELECT hour
FROM generate_series(
lower(requested_range),
upper(requested_range) - reading_length_interval,
reading_length_interval
) hours(hour)
) hours(hour),
-- Also need the values in the group hourly table.
group_hourly_readings_unit ghr
-- Only want the desired meter
WHERE ghr.group_id = group_id_requested
-- Only want the desired graphing unit
AND ghr.graphic_unit_id = graphic_unit_id_requested
-- Only want readings that lie within this slice of the desired data
AND lower(ghr.time_interval) >= hours.hour
AND upper(ghr.time_interval) <= hours.hour + reading_length_interval
-- ensures that the start of the reading time intervals does not exceed the end of the current generated interval
AND lower(ghr.time_interval) <= hours.hour + reading_length_interval
-- Group by the start time of the generated series since all points in
-- the desired slice have the same start time for the series.
GROUP BY hours.hour
-- Time sort by the start time for graphing.
ORDER BY hours.hour
;
ELSE
-- The reading rate is more than 12 so return a single row with dummy values that easy to detect.
-- The end time differs from the start time by the meter reading frequency or min one for groups.
-- This means the meter reading frequency is too long for a 3D graphic.
RETURN QUERY
SELECT -999::FLOAT, '1900-01-01 00:00:00'::TIMESTAMP, '1900-01-01 00:00:00'::TIMESTAMP + reading_length_interval
;
END IF;
END;
$$ LANGUAGE 'plpgsql';
Loading