frost-event-detector 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/.env +10 -0
  2. package/.eslintrc.js +14 -0
  3. package/.husky/pre-commit +4 -0
  4. package/.husky/pre-push +4 -0
  5. package/.prettierrc.js +12 -0
  6. package/.vscode/launch.json.example +28 -0
  7. package/README.md +29 -0
  8. package/bitbucket-pipelines.yml +48 -0
  9. package/context.json +1 -0
  10. package/dev.env +10 -0
  11. package/dist/src/calculate.js +195 -0
  12. package/dist/src/calculate.js.map +1 -0
  13. package/dist/src/constants.js +10 -0
  14. package/dist/src/constants.js.map +1 -0
  15. package/dist/src/db.js +79 -0
  16. package/dist/src/db.js.map +1 -0
  17. package/dist/src/evaluate.js +170 -0
  18. package/dist/src/evaluate.js.map +1 -0
  19. package/dist/src/index.js +75 -0
  20. package/dist/src/index.js.map +1 -0
  21. package/dist/src/repository/coldstore.repository.js +215 -0
  22. package/dist/src/repository/coldstore.repository.js.map +1 -0
  23. package/dist/src/repository/timeseries.repository.js +248 -0
  24. package/dist/src/repository/timeseries.repository.js.map +1 -0
  25. package/dist/src/timeSeries.js +233 -0
  26. package/dist/src/timeSeries.js.map +1 -0
  27. package/dist/src/utils.js +33 -0
  28. package/dist/src/utils.js.map +1 -0
  29. package/dist/test/int/lambda.test.js +36 -0
  30. package/dist/test/int/lambda.test.js.map +1 -0
  31. package/dist/test/unit/db.test.js +154 -0
  32. package/dist/test/unit/db.test.js.map +1 -0
  33. package/dist/test/unit/evaluate.test.js +76 -0
  34. package/dist/test/unit/evaluate.test.js.map +1 -0
  35. package/dist/test/unit/fps.test.js +84 -0
  36. package/dist/test/unit/fps.test.js.map +1 -0
  37. package/dist/test/unit/runtime.test.js +84 -0
  38. package/dist/test/unit/runtime.test.js.map +1 -0
  39. package/dist/test/unit/timeSeries.test.js +81 -0
  40. package/dist/test/unit/timeSeries.test.js.map +1 -0
  41. package/dist/test/unit/utils.test.js +64 -0
  42. package/dist/test/unit/utils.test.js.map +1 -0
  43. package/dist/tsconfig.tsbuildinfo +1 -0
  44. package/event.json +6 -0
  45. package/jest-int.config.ts +18 -0
  46. package/jest-unit.config.ts +25 -0
  47. package/jest.config.ts +30 -0
  48. package/lint-staged.config.js +10 -0
  49. package/package.json +61 -0
  50. package/prod.env +10 -0
  51. package/src/calculate.ts +389 -0
  52. package/src/constants.ts +15 -0
  53. package/src/db.ts +134 -0
  54. package/src/evaluate.ts +272 -0
  55. package/src/index.ts +104 -0
  56. package/src/repository/coldstore.repository.ts +238 -0
  57. package/src/repository/timeseries.repository.ts +273 -0
  58. package/src/types.d.ts +68 -0
  59. package/src/utils.ts +47 -0
  60. package/test/int/lambda.test.ts +46 -0
  61. package/test/unit/db.test.ts +188 -0
  62. package/test/unit/evaluate.test.ts +85 -0
  63. package/test/unit/fps.test.ts +97 -0
  64. package/test/unit/json/currentCandidates.json +44 -0
  65. package/test/unit/json/dayEvent.json +169 -0
  66. package/test/unit/json/eventCandidates.json +68 -0
  67. package/test/unit/json/eventDay.json +891 -0
  68. package/test/unit/json/frost_protection_score.json +800 -0
  69. package/test/unit/json/frost_protection_score_2_fans.json +1615 -0
  70. package/test/unit/json/runtime_high.json +458 -0
  71. package/test/unit/json/runtime_negative.json +772 -0
  72. package/test/unit/runtime.test.ts +96 -0
  73. package/test/unit/timeSeries.test.ts +88 -0
  74. package/test/unit/utils.test.ts +76 -0
  75. package/tsconfig.json +32 -0
package/.env ADDED
@@ -0,0 +1,10 @@
1
+ AWS_ROLE_ARN=arn:aws:iam::045197510462:role/lambda_basic_vpc_execution
2
+ AWS_REGION=ap-southeast-2
3
+ AWS_FUNCTION_NAME=frost-event-detector
4
+ AWS_HANDLER=dist/src/index.handler
5
+ AWS_MEMORY_SIZE=512
6
+ AWS_TIMEOUT=900
7
+ AWS_DESCRIPTION=Function to find frost events
8
+ AWS_RUNTIME=nodejs20.x
9
+ AWS_VPC_SUBNETS=subnet-03d05ce3d18cdcc6e,subnet-01d335c6dde9a6cbf,subnet-0413bf072d758981a
10
+ AWS_VPC_SECURITY_GROUPS=sg-0ef60c0fcc95b260f
package/.eslintrc.js ADDED
@@ -0,0 +1,14 @@
1
+ module.exports = {
2
+ "extends": ["@frostsmart/eslint-config-loncel/node-config-ts"],
3
+ "parser": "@typescript-eslint/parser",
4
+ "settings": {
5
+ "import/resolver": {
6
+ "node": {
7
+ "extensions": [".js", ".json", ".d.ts"]
8
+ }
9
+ }
10
+ },
11
+ "rules": {
12
+ // Rules that you want to override or new ones
13
+ }
14
+ };
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env sh
2
+ . "$(dirname -- "$0")/_/husky.sh"
3
+
4
+ npm run lint-staged
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env sh
2
+ . "$(dirname -- "$0")/_/husky.sh"
3
+
4
+ git diff HEAD --quiet && npm run test:unit
package/.prettierrc.js ADDED
@@ -0,0 +1,12 @@
1
+ module.exports = {
2
+ bracketSameLine: true,
3
+ bracketSpacing: true,
4
+ singleQuote: true,
5
+ trailingComma: 'all',
6
+ printWidth: 100,
7
+ tabWidth: 2,
8
+ useTabs: false,
9
+ semi: true,
10
+ arrowParens: "always",
11
+ quoteProps: "consistent"
12
+ };
@@ -0,0 +1,28 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "type": "node",
6
+ "request": "launch",
7
+ "name": "Debug with node-lambda",
8
+ "program": "${workspaceFolder}/node_modules/node-lambda/bin/node-lambda",
9
+ "args": ["run", "--handler", "dist/src/index.handler"],
10
+ "sourceMaps": true,
11
+ "cwd": "${workspaceFolder}",
12
+ "console": "integratedTerminal",
13
+ "internalConsoleOptions": "neverOpen",
14
+ "disableOptimisticBPs": true
15
+ },
16
+ {
17
+ "type": "node",
18
+ "request": "launch",
19
+ "name": "Debug with jest",
20
+ "program": "${workspaceFolder}/node_modules/jest/bin/jest",
21
+ "args": ["--runInBand", "test/unit/fps.test.ts"],
22
+ "cwd": "${workspaceFolder}",
23
+ "console": "integratedTerminal",
24
+ "internalConsoleOptions": "neverOpen",
25
+ "disableOptimisticBPs": true
26
+ }
27
+ ]
28
+ }
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # README
2
+
3
+ ## What is this repository for?
4
+
5
+ This lambda function usually runs a part of a step function and is designed to run from scratch, meaning going through all the history of data and determine all frost events for an area. Once it has established the history, it always starts from the last recorded event.
6
+ And to be current and expand on currently happening events, there is a current mode, that only picks up on todays events.
7
+
8
+ ### What is actually a frost event
9
+
10
+ This is actually not as trivial as it sounds. The most basic condition is, that it needs to be cold and the fan is running at the time.
11
+ Only running is not enough, as fans can also run for cooling operations in summer. So it must be cold at the same time.
12
+ But even then you have the so called ice bucket tests, done by installers. They prove that a fan is actually automatically starting once the temperature drops
13
+ below a certain threshold. These tests are usually performed during the day.
14
+
15
+ So this leaves the following conditions that determine a frost event:
16
+
17
+ - Fan(s) must be running
18
+ - The temperature must be below 2.5 degrees while the fan is running
19
+ - An event is only recorded from 6pm in the evening to 10am in the morning
20
+
21
+ ### What is recorded for a frost event
22
+
23
+ Per event we record:
24
+
25
+ - Area of the event
26
+ - Start and stop time of the event
27
+ - ids of the fans involved
28
+ - min temperature recorded
29
+ - Total hrs of run time amoung all fans
@@ -0,0 +1,48 @@
1
+ image: sleavely/node-awscli:20.x
2
+
3
+ definitions:
4
+ scripts:
5
+ - script:
6
+ &build
7
+ npm config set @${NPM_SCOPE}:registry https://registry.npmjs.org/ &&
8
+ npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" &&
9
+ npm i --location=global @frostsmart/devops node-lambda ts-node typescript husky &&
10
+ npm install &&
11
+ npx tsc &&
12
+ node-lambda package -A .lambda
13
+ pipelines:
14
+ pull-requests:
15
+ '**':
16
+ - step:
17
+ name: Build and test
18
+ script:
19
+ - apt-get update
20
+ - *build
21
+ - npm run test:unit
22
+ branches:
23
+ master:
24
+ - step:
25
+ caches:
26
+ - node
27
+ name: Deploy to loncel, frost environment
28
+ script:
29
+ - *build
30
+ # deploy into frost_dev
31
+ - devops deploy-direct -e dev -p FROST_DEV
32
+ # unit test
33
+ - npm run test:unit
34
+ # deploy into frost_stage
35
+ - devops deploy-direct -e dev -p FROST_STAGE
36
+ # run the int test
37
+ - export aws_role="arn:aws:iam::$FROST_STAGE_ACCOUNT:role/$AWS_CI_ROLE_NAME"
38
+ - export creds=$(aws sts assume-role --role-arn $aws_role --role-session-name "bitbucket" --external-id $FROST_STAGE_EXTERNAL_ID)
39
+ - export AWS_ACCESS_KEY_ID=$(echo $creds | jq -r .Credentials.AccessKeyId)
40
+ - export AWS_SECRET_ACCESS_KEY=$(echo $creds | jq -r .Credentials.SecretAccessKey)
41
+ - export AWS_SESSION_TOKEN=$(echo $creds | jq -r .Credentials.SessionToken)
42
+ - npm run test:int
43
+ - step:
44
+ name: Deploy to frost prod environment
45
+ script:
46
+ - *build
47
+ # deploy into frost_prod
48
+ - devops deploy-direct -e prod -p FROST_PROD
package/context.json ADDED
@@ -0,0 +1 @@
1
+ {"invokedFunctionArn":"arn:aws:lambda:ap-southeast-2:045197510462:function:dummy"}
package/dev.env ADDED
@@ -0,0 +1,10 @@
1
+ AWS_ROLE_ARN='arn:aws:iam::221392187604:role/lambda_basic_vpc_execution'
2
+ AWS_REGION=us-west-2
3
+ AWS_FUNCTION_NAME=frost-event-detector
4
+ AWS_HANDLER=dist/src/index.handler
5
+ AWS_MEMORY_SIZE=200
6
+ AWS_TIMEOUT=600
7
+ AWS_DESCRIPTION="Function to find frost events"
8
+ AWS_RUNTIME=nodejs20.x
9
+ AWS_VPC_SUBNETS=subnet-5845de3c,subnet-de46ddba,subnet-7d45de19
10
+ AWS_VPC_SECURITY_GROUPS=sg-cbcd25ad
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.calculateFPS = exports.calculateDurationBelowThreshold = exports.calculateFPSInput = exports.calculateFansStartTemp = exports.calculateInversion = exports.calculateTripHours = exports.calculatesMinTemperature = void 0;
7
+ const underscore_1 = require("underscore");
8
+ const moment_1 = __importDefault(require("moment"));
9
+ const binary_search_1 = __importDefault(require("binary-search"));
10
+ const constants_1 = __importDefault(require("./constants"));
11
+ const db_1 = require("./db");
12
+ const calculatesMinTemperature = (eventDay, startTime, endTime, fans) => {
13
+ const { tempSeries } = eventDay;
14
+ const minTemp = (0, underscore_1.reduce)(tempSeries, (memo, tempGroup) => {
15
+ if (tempGroup.group_by &&
16
+ (0, underscore_1.find)(fans, (id) => id === Number(tempGroup.group_by[0].group.section)))
17
+ return Math.min(memo, (0, underscore_1.min)((0, underscore_1.map)(tempGroup.values, (value) => value[0] >= startTime && value[0] <= endTime ? value[1] : memo)));
18
+ return memo;
19
+ }, constants_1.default.MAX_TEMPERATURE);
20
+ return minTemp;
21
+ };
22
+ exports.calculatesMinTemperature = calculatesMinTemperature;
23
+ const calculateTripHours = (eventDay, frostStartTime, frostEndTime, fans) => {
24
+ const oneHour = 60;
25
+ const timeBetweenIntervals = 5;
26
+ const intervalsPerHour = oneHour / timeBetweenIntervals;
27
+ const { engineSeries, runSeries } = eventDay;
28
+ const tripHours = runSeries.reduce((memo, runGroup) => {
29
+ if (runGroup.group_by && fans.find((id) => id === Number(runGroup.group_by[0].group.section))) {
30
+ const engineGroup = engineSeries.find((engineGroup) => engineGroup.group_by &&
31
+ engineGroup.group_by[0].group.section === runGroup.group_by[0].group.section);
32
+ if (!engineGroup) {
33
+ return memo + Math.max(runGroup.values.length - 1, 1) / intervalsPerHour;
34
+ }
35
+ const startIndex = (0, underscore_1.findIndex)(engineGroup.values, (value) => value[0] >= frostStartTime);
36
+ const endIndex = Math.max((0, underscore_1.findIndex)(engineGroup.values, (value) => value[0] >= frostEndTime), engineGroup.values.length - 1);
37
+ if (startIndex > -1 &&
38
+ -1 < endIndex &&
39
+ endIndex < engineGroup.values.length &&
40
+ engineGroup.values[startIndex][0] <= engineGroup.values[endIndex][0]) {
41
+ if (engineGroup.values[engineGroup.values.length - 1][1] === 0) {
42
+ return memo + Math.max(runGroup.values.length - 1, 1) / intervalsPerHour;
43
+ }
44
+ const lastEngineHoursValue = engineGroup.values[Math.min(endIndex + 1, engineGroup.values.length - 1)][1];
45
+ const firstEngineHoursValue = engineGroup.values[Math.max(startIndex - 1, 0)][1];
46
+ const engineHoursDelta = lastEngineHoursValue - firstEngineHoursValue;
47
+ const hoursOfEngineEvent = (0, moment_1.default)(engineGroup.values[endIndex][0]).diff((0, moment_1.default)(engineGroup.values[startIndex][0]), 'minutes') / 60;
48
+ if (engineHoursDelta < 0 || engineHoursDelta > hoursOfEngineEvent) {
49
+ return memo + Math.max(runGroup.values.length - 1, 1) / 12;
50
+ }
51
+ return memo + engineHoursDelta;
52
+ }
53
+ }
54
+ return memo;
55
+ }, 0);
56
+ return tripHours;
57
+ };
58
+ exports.calculateTripHours = calculateTripHours;
59
+ const calculateInversion = async (client, eventDay, startTime) => {
60
+ const { tempSeries, towerSeries } = eventDay;
61
+ const fans = (0, underscore_1.compact)(tempSeries.map((tempGroup) => {
62
+ if (tempGroup.group_by && Number(tempGroup.group_by[0].group.section)) {
63
+ return Number(tempGroup.group_by[0].group.section);
64
+ }
65
+ return null;
66
+ }));
67
+ const fansWithTowerTemp = await (0, db_1.fetchFansWithTowerTempFor)(client, fans);
68
+ if (!fansWithTowerTemp.length)
69
+ return null;
70
+ const inversionDeltas = (0, underscore_1.reduce)(fansWithTowerTemp, (memo, fanId) => {
71
+ const tempGroup = (0, underscore_1.find)(tempSeries, (_series) => _series.group_by && Number(_series.group_by[0].group.section) === fanId);
72
+ const towerGroup = (0, underscore_1.find)(towerSeries, (_series) => _series.group_by && Number(_series.group_by[0].group.section) === fanId);
73
+ if (!tempGroup || !towerGroup)
74
+ return memo;
75
+ const canopy = (0, underscore_1.find)(tempGroup.values, (value) => {
76
+ const ts = new Date(value[0]).getTime();
77
+ return ts <= startTime && ts >= startTime - 5 * 60 * 1000;
78
+ });
79
+ const tower = (0, underscore_1.find)(towerGroup.values, (value) => {
80
+ const ts = new Date(value[0]).getTime();
81
+ return ts <= startTime && ts >= startTime - 5 * 60 * 1000;
82
+ });
83
+ if (canopy && tower)
84
+ memo.push(tower[1] - canopy[1]);
85
+ return memo;
86
+ }, []);
87
+ const percentageToRemove = 0.05;
88
+ const elementsToRemove = Math.ceil(inversionDeltas.length * percentageToRemove);
89
+ const inversionDeltasSorted = (0, underscore_1.sortBy)(inversionDeltas);
90
+ const trimmedResult = inversionDeltasSorted.length > 2
91
+ ? inversionDeltasSorted.slice(elementsToRemove, -elementsToRemove)
92
+ : inversionDeltasSorted;
93
+ return trimmedResult.length
94
+ ? (0, underscore_1.reduce)(inversionDeltas, (memo, value) => memo + value, 0) / inversionDeltas.length
95
+ : null;
96
+ };
97
+ exports.calculateInversion = calculateInversion;
98
+ const calculateFansStartTemp = (startTempSeries, fans) => {
99
+ const fanStartTemp = fans.reduce((memo, fanId) => {
100
+ const fanStartTempGroup = startTempSeries.find((tempGroup) => tempGroup?.group_by && Number(tempGroup?.group_by[0]?.group?.section) === fanId);
101
+ if (fanStartTempGroup?.values?.length) {
102
+ const startTempValue = fanStartTempGroup.values[fanStartTempGroup.values.length - 1][1];
103
+ if (startTempValue != null) {
104
+ return Math.min(memo, startTempValue);
105
+ }
106
+ }
107
+ return memo;
108
+ }, constants_1.default.MAX_TEMPERATURE);
109
+ if (fanStartTemp < constants_1.default.MAX_TEMPERATURE) {
110
+ return fanStartTemp;
111
+ }
112
+ const seriesStartTemp = startTempSeries.reduce((memo, startTempGroup) => {
113
+ if (startTempGroup?.values?.length) {
114
+ const startTempValue = startTempGroup.values[startTempGroup.values.length - 1][1];
115
+ if (startTempValue != null) {
116
+ return Math.min(memo, startTempValue);
117
+ }
118
+ }
119
+ return memo;
120
+ }, constants_1.default.MAX_TEMPERATURE);
121
+ return seriesStartTemp < constants_1.default.MAX_TEMPERATURE ? seriesStartTemp : null;
122
+ };
123
+ exports.calculateFansStartTemp = calculateFansStartTemp;
124
+ const calculateFPSInput = (event, fans, tempThreshold) => {
125
+ const { tempSeries, runSeries } = event;
126
+ return runSeries.reduce((memo, runGroup) => {
127
+ if (runGroup.values.length === 0) {
128
+ return memo;
129
+ }
130
+ if (runGroup.group_by &&
131
+ (0, underscore_1.find)(fans, (id) => id === Number(runGroup.group_by[0].group.section))) {
132
+ const tempGroup = (0, underscore_1.find)(tempSeries, (_series) => _series?.group_by[0].group.section === runGroup.group_by[0].group.section);
133
+ if (!tempGroup) {
134
+ return memo;
135
+ }
136
+ let timeBelowThreshold = 0;
137
+ const temperatures = [];
138
+ runGroup.values.forEach((run) => {
139
+ const index = (0, binary_search_1.default)(tempGroup.values, run, (element, needle) => element[0] - needle[0]);
140
+ if (index > -1) {
141
+ const currentTemp = tempGroup.values[index][1];
142
+ const tempDelta = currentTemp - tempThreshold;
143
+ temperatures.push(tempDelta);
144
+ if (currentTemp < tempThreshold)
145
+ timeBelowThreshold += 5;
146
+ }
147
+ });
148
+ memo = {
149
+ tempValues: [...memo.tempValues, ...temperatures],
150
+ totalTimeBelow: memo.totalTimeBelow + timeBelowThreshold,
151
+ maxFanBelow: Math.max(memo.maxFanBelow, timeBelowThreshold),
152
+ };
153
+ }
154
+ return memo;
155
+ }, {
156
+ tempValues: [],
157
+ totalTimeBelow: 0,
158
+ maxFanBelow: 0,
159
+ });
160
+ };
161
+ exports.calculateFPSInput = calculateFPSInput;
162
+ const calculateDurationBelowThreshold = (event, startTime, endTime, threshold) => {
163
+ const { tempSeries } = event;
164
+ let totalBelowThresholdDurationMs = 0;
165
+ let validGroupCount = 0;
166
+ for (const tempGroup of tempSeries) {
167
+ let groupDuration = 0;
168
+ let prevTimestamp = null;
169
+ let prevTemp = null;
170
+ if (!tempGroup.values.length) {
171
+ continue;
172
+ }
173
+ for (const [timestamp, temp] of tempGroup.values) {
174
+ if (timestamp >= startTime && timestamp <= endTime) {
175
+ if (prevTimestamp !== null && prevTemp < threshold && temp < threshold) {
176
+ groupDuration += timestamp - prevTimestamp;
177
+ }
178
+ prevTimestamp = timestamp;
179
+ prevTemp = temp;
180
+ }
181
+ }
182
+ totalBelowThresholdDurationMs += groupDuration;
183
+ validGroupCount++;
184
+ }
185
+ const avgBelowThresholdMinutes = validGroupCount > 0 ? totalBelowThresholdDurationMs / validGroupCount / (1000 * 60) : 0;
186
+ return avgBelowThresholdMinutes;
187
+ };
188
+ exports.calculateDurationBelowThreshold = calculateDurationBelowThreshold;
189
+ const calculateFPS = (cat, totalTimeBelow, maxFanBelow, totalFans) => {
190
+ const avgCriticalScore = totalTimeBelow / totalFans / 60;
191
+ const maxImpactScore = (maxFanBelow - totalTimeBelow / totalFans) / totalFans / 60;
192
+ return cat - avgCriticalScore - maxImpactScore;
193
+ };
194
+ exports.calculateFPS = calculateFPS;
195
+ //# sourceMappingURL=calculate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calculate.js","sourceRoot":"","sources":["../../src/calculate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const constants = {
4
+ MAX_TEMPERATURE: 5.0,
5
+ MIN_TEMPERATURE: -30.0,
6
+ EVENT_WINDOW_START_HOUR: 18,
7
+ EVENT_WINDOW_END_HOUR: 10,
8
+ };
9
+ exports.default = constants;
10
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":";;AAOA,MAAM,SAAS,GAAG;IAChB,eAAe,EAAE,GAAG;IACpB,eAAe,EAAE,CAAC,IAAI;IACtB,uBAAuB,EAAE,EAAE;IAC3B,qBAAqB,EAAE,EAAE;CACjB,CAAC;AAEX,kBAAe,SAAS,CAAC"}
package/dist/src/db.js ADDED
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.recordFor = exports.fetchFansWithTowerTempFor = exports.fetchFrostAreasFor = void 0;
7
+ const moment_timezone_1 = __importDefault(require("moment-timezone"));
8
+ const getFrostTableName = (useReplica) => {
9
+ return useReplica ? 'lcloud.frost_event_replica' : 'lcloud.frost_event';
10
+ };
11
+ const fetchFrostAreasFor = async (client, siteId, useReplica = false) => {
12
+ const result = await client.raw(`
13
+ SELECT area.id, COALESCE(site.config->>'timezone','Pacific/Auckland') as timezone,
14
+ (SELECT json_build_object('id', id, 'startTime', start_time, 'endTime', end_time, 'fans', fans)
15
+ FROM ${getFrostTableName(useReplica)}
16
+ WHERE area = area.id
17
+ ORDER BY start_time DESC
18
+ LIMIT 1) AS "lastEvent"
19
+ FROM lcloud.area INNER JOIN lcloud.site on site.id = area.site
20
+ WHERE site = ? AND (site.tags ->> 'internal' IS NULL OR site.tags ->> 'internal' = 'false')
21
+ AND application_type = 'frost'`, [siteId]);
22
+ return result.rows;
23
+ };
24
+ exports.fetchFrostAreasFor = fetchFrostAreasFor;
25
+ const fetchFansWithTowerTempFor = async (client, fans) => {
26
+ const { rows } = await client.raw(`
27
+ SELECT area, array_agg(section) as fans
28
+ FROM lcloud.sensor WHERE section = ANY(?) AND type = 'frostFan' and (config->>'ntc2')::boolean IS NOT TRUE
29
+ GROUP BY area
30
+ `, [fans]);
31
+ return rows.length ? rows[0].fans : [];
32
+ };
33
+ exports.fetchFansWithTowerTempFor = fetchFansWithTowerTempFor;
34
+ const recordFor = async (client, area, event, useReplica = false) => {
35
+ const tableName = getFrostTableName(useReplica);
36
+ const { lastEvent } = area;
37
+ const { startTime, endTime, fans, minTemp, tripHours, inversion, cat, totalTimeBelow, maxFanBelow, startTemp, fps, durationBelowThreshold, } = event;
38
+ const eventStart = (0, moment_timezone_1.default)(startTime).tz('Pacific/Auckland');
39
+ if (lastEvent &&
40
+ (0, moment_timezone_1.default)(lastEvent.startTime)
41
+ .tz('Pacific/Auckland')
42
+ .isBetween(eventStart, eventStart.clone().add(1, 'day'), null, '[]')) {
43
+ if (endTime !== (0, moment_timezone_1.default)(lastEvent.endTime).valueOf()) {
44
+ await client.raw(`UPDATE ${tableName} SET end_time = ?, fans = ?, min_temp = ?, runtime = ?, inversion = ?, cat = ?, total_time_below = ?, max_fan_below = ?, start_temp = ?, fps = ?, duration_below_start = ? WHERE id = ? returning id`, [
45
+ (0, moment_timezone_1.default)(endTime).tz('Pacific/Auckland').format(),
46
+ fans,
47
+ minTemp,
48
+ tripHours,
49
+ inversion,
50
+ cat,
51
+ totalTimeBelow,
52
+ maxFanBelow,
53
+ startTemp,
54
+ fps,
55
+ durationBelowThreshold ?? [0, 0, 0, 0, 0, 0],
56
+ lastEvent.id,
57
+ ]);
58
+ }
59
+ }
60
+ else if (!lastEvent || eventStart > (0, moment_timezone_1.default)(lastEvent.startTime).tz('Pacific/Auckland')) {
61
+ await client.raw(`INSERT INTO ${tableName} (start_time, end_time, fans, min_temp, runtime, inversion, area, cat, total_time_below, max_fan_below, start_temp, fps, duration_below_start) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) returning id`, [
62
+ (0, moment_timezone_1.default)(startTime).tz('Pacific/Auckland').format(),
63
+ (0, moment_timezone_1.default)(endTime).tz('Pacific/Auckland').format(),
64
+ fans,
65
+ minTemp,
66
+ tripHours,
67
+ inversion,
68
+ area.id,
69
+ cat,
70
+ totalTimeBelow,
71
+ maxFanBelow,
72
+ startTemp,
73
+ fps,
74
+ durationBelowThreshold ?? [0, 0, 0, 0, 0, 0],
75
+ ]);
76
+ }
77
+ };
78
+ exports.recordFor = recordFor;
79
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"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"}