Skip to content

Commit

Permalink
support recording usage from bill
Browse files Browse the repository at this point in the history
  • Loading branch information
dangowans committed Jan 24, 2024
1 parent 244cf5c commit ef14034
Show file tree
Hide file tree
Showing 11 changed files with 345 additions and 133 deletions.
3 changes: 2 additions & 1 deletion data/config.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const config = {
application: {},
reverseProxy: {},
session: {},
parserConfigs: {}
parserConfigs: {},
settings: {}
};
export default config;
3 changes: 2 additions & 1 deletion data/config.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export const config: Config = {
application: {},
reverseProxy: {},
session: {},
parserConfigs: {}
parserConfigs: {},
settings: {}
}

export default config
4 changes: 4 additions & 0 deletions data/config.ssm.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ export const config = Object.assign({}, baseConfig);
config.parserConfigs = config.parserConfigs ?? {};
config.parserConfigs.ssmPuc = ssmPuc;
config.parserConfigs.enbridgeUsageHistory = enbridgeUsageHistory;
config.settings = config.settings ?? {};
config.settings.greenButton = {
usageProperty: 'currentBillingPeriodOverAllConsumption'
};
config.subscriptions = config.subscriptions ?? {};
config.subscriptions.greenButton = config.subscriptions.greenButton ?? {};
export default config;
5 changes: 5 additions & 0 deletions data/config.ssm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ config.parserConfigs = config.parserConfigs ?? {}
config.parserConfigs.ssmPuc = ssmPuc
config.parserConfigs.enbridgeUsageHistory = enbridgeUsageHistory

config.settings = config.settings ?? {}
config.settings.greenButton = {
usageProperty: 'currentBillingPeriodOverAllConsumption'
}

config.subscriptions = config.subscriptions ?? {}
config.subscriptions.greenButton = config.subscriptions.greenButton ?? {}

Expand Down
3 changes: 2 additions & 1 deletion helpers/functions.config.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ADWebAuthConfig } from '@cityssm/ad-web-auth-connector/types.js';
import type { ConfigActiveDirectory, ConfigGreenButtonSubscription, ConfigParserConfiguration, ConfigTemporaryUserCredentials } from '../types/configTypes.js';
import type { ConfigActiveDirectory, ConfigGreenButtonSubscription, ConfigGreenButtonUsageProperty, ConfigParserConfiguration, ConfigTemporaryUserCredentials } from '../types/configTypes.js';
declare const property_session_maxAgeMillis = "session.maxAgeMillis";
export declare function getConfigProperty(propertyName: 'application.applicationName' | 'application.backgroundURL' | 'application.bigLogoURL' | 'application.smallLogoURL' | 'application.userDomain' | 'reverseProxy.urlPrefix' | 'session.cookieName' | 'session.secret'): string;
export declare function getConfigProperty(propertyName: 'application.httpPort' | 'application.maximumProcesses' | typeof property_session_maxAgeMillis | 'settings.reportKeyAccessDays'): number;
Expand All @@ -9,6 +9,7 @@ export declare function getConfigProperty(propertyName: 'activeDirectory'): Conf
export declare function getConfigProperty(propertyName: 'adWebAuthConfig'): ADWebAuthConfig | undefined;
export declare function getConfigProperty(propertyName: 'parserConfigs'): Record<string, ConfigParserConfiguration>;
export declare function getConfigProperty(propertyName: 'subscriptions.greenButton'): Record<string, ConfigGreenButtonSubscription>;
export declare function getConfigProperty(propertyName: 'settings.greenButton.usageProperty'): ConfigGreenButtonUsageProperty;
export declare const keepAliveMillis: number;
declare const _default: {
getConfigProperty: typeof getConfigProperty;
Expand Down
1 change: 1 addition & 0 deletions helpers/functions.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ configFallbackValues.set('session.cookieName', 'emile-user-sid');
configFallbackValues.set('session.secret', 'cityssm/emile');
configFallbackValues.set(property_session_maxAgeMillis, 60 * 60 * 1000);
configFallbackValues.set('session.doKeepAlive', false);
configFallbackValues.set('settings.greenButton.usageProperty', 'intervalReading');
configFallbackValues.set('parserConfigs', {});
configFallbackValues.set('settings.reportKeyAccessDays', 5);
configFallbackValues.set('subscriptions.greenButton', {});
Expand Down
10 changes: 10 additions & 0 deletions helpers/functions.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { config } from '../data/config.js'
import type {
ConfigActiveDirectory,
ConfigGreenButtonSubscription,
ConfigGreenButtonUsageProperty,
ConfigParserConfiguration,
ConfigTemporaryUserCredentials
} from '../types/configTypes.js'
Expand Down Expand Up @@ -40,6 +41,11 @@ configFallbackValues.set('session.secret', 'cityssm/emile')
configFallbackValues.set(property_session_maxAgeMillis, 60 * 60 * 1000)
configFallbackValues.set('session.doKeepAlive', false)

configFallbackValues.set(
'settings.greenButton.usageProperty',
'intervalReading'
)

configFallbackValues.set('parserConfigs', {})

configFallbackValues.set('settings.reportKeyAccessDays', 5)
Expand Down Expand Up @@ -98,6 +104,10 @@ export function getConfigProperty(
propertyName: 'subscriptions.greenButton'
): Record<string, ConfigGreenButtonSubscription>

export function getConfigProperty(
propertyName: 'settings.greenButton.usageProperty'
): ConfigGreenButtonUsageProperty

export function getConfigProperty(propertyName: string): unknown {
const propertyNameSplit = propertyName.split('.')

Expand Down
159 changes: 110 additions & 49 deletions helpers/functions.greenButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getEnergyDataPoint } from '../database/getEnergyData.js';
import { getEnergyDataTypeByGreenButtonIds } from '../database/getEnergyDataType.js';
import { updateEnergyDataValue } from '../database/updateEnergyData.js';
import { getAssetCategories } from './functions.cache.js';
import { getConfigProperty } from './functions.config.js';
import { getConnectionWhenAvailable } from './functions.database.js';
const debug = Debug('emile:functions.greenButton');
const greenButtonAliasTypeKey = 'GreenButtonParser.IntervalBlock.link';
Expand Down Expand Up @@ -90,7 +91,7 @@ async function getEnergyDataTypeAndPowerOfTenMultiplier(greenButtonJson, interva
: powerOfTenMultiplier
};
}
async function getEnergyDataType(greenButtonJson, usageSummaryEntry, connectedEmileDB) {
async function getCurrencyDataType(greenButtonJson, usageSummaryEntry, connectedEmileDB) {
const usagePoint = greenButtonHelpers.getUsagePointEntryFromEntry(greenButtonJson, usageSummaryEntry);
if (usagePoint === undefined) {
throw new Error('Unable to find related UsagePoint entry.');
Expand All @@ -101,58 +102,76 @@ async function getEnergyDataType(greenButtonJson, usageSummaryEntry, connectedEm
commodityId: usageSummaryEntry.content.UsageSummary.commodity?.toString()
}, greenButtonUser, true, connectedEmileDB);
}
async function getUsageDataType(greenButtonJson, usageSummaryEntry, connectedEmileDB) {
const usagePoint = greenButtonHelpers.getUsagePointEntryFromEntry(greenButtonJson, usageSummaryEntry);
if (usagePoint === undefined) {
throw new Error('Unable to find related UsagePoint entry.');
}
return await getEnergyDataTypeByGreenButtonIds({
serviceCategoryId: usagePoint.content.UsagePoint.ServiceCategory?.kind.toString() ?? '',
unitId: usageSummaryEntry.content.UsageSummary.currentBillingPeriodOverAllConsumption?.uom?.toString() ??
'',
commodityId: usageSummaryEntry.content.UsageSummary.commodity?.toString()
}, greenButtonUser, true, connectedEmileDB);
}
export async function recordGreenButtonData(greenButtonJson, options, connectedEmileDB) {
let recordCount = 0;
const intervalBlockEntries = greenButtonHelpers.getEntriesByContentType(greenButtonJson, 'IntervalBlock');
const intervalBlockEntries = getConfigProperty('settings.greenButton.usageProperty') ===
'intervalReading'
? greenButtonHelpers.getEntriesByContentType(greenButtonJson, 'IntervalBlock')
: [];
const usageSummaryEntries = greenButtonHelpers.getEntriesByContentType(greenButtonJson, 'UsageSummary');
if (intervalBlockEntries.length === 0 && usageSummaryEntries.length === 0) {
throw new Error('File contains no IntervalBlock or UsageSummary entries.');
}
const emileDB = connectedEmileDB ?? (await getConnectionWhenAvailable());
try {
for (const intervalBlockEntry of intervalBlockEntries) {
let assetId = options.assetId;
if ((assetId ?? '') === '') {
assetId = await getAssetIdFromIntervalBlock(intervalBlockEntry, emileDB);
}
const energyDataTypeAndPower = await getEnergyDataTypeAndPowerOfTenMultiplier(greenButtonJson, intervalBlockEntry, emileDB);
if (energyDataTypeAndPower?.energyDataType === undefined) {
throw new Error('Unable to retrieve EnergyDataType.');
}
for (const intervalBlock of intervalBlockEntry.content.IntervalBlock) {
for (const intervalReading of intervalBlock.IntervalReading ?? []) {
if (intervalReading.timePeriod !== undefined &&
intervalReading.value !== undefined) {
const currentDataPoint = await getEnergyDataPoint({
assetId: assetId,
dataTypeId: energyDataTypeAndPower.energyDataType
.dataTypeId,
timeSeconds: intervalReading.timePeriod.start,
durationSeconds: intervalReading.timePeriod.duration
}, emileDB);
if (currentDataPoint === undefined) {
await addEnergyData({
assetId,
dataTypeId: energyDataTypeAndPower.energyDataType.dataTypeId,
fileId: options.fileId,
timeSeconds: intervalReading.timePeriod?.start,
durationSeconds: intervalReading.timePeriod?.duration,
dataValue: intervalReading.value,
powerOfTenMultiplier: energyDataTypeAndPower.powerOfTenMultiplier
}, greenButtonUser, emileDB);
recordCount += 1;
}
else if (currentDataPoint.dataValue !== intervalReading.value ||
currentDataPoint.powerOfTenMultiplier !==
energyDataTypeAndPower.powerOfTenMultiplier) {
await updateEnergyDataValue({
dataId: currentDataPoint.dataId,
if (getConfigProperty('settings.greenButton.usageProperty') ===
'intervalReading') {
for (const intervalBlockEntry of intervalBlockEntries) {
let assetId = options.assetId;
if ((assetId ?? '') === '') {
assetId = await getAssetIdFromIntervalBlock(intervalBlockEntry, emileDB);
}
const energyDataTypeAndPower = await getEnergyDataTypeAndPowerOfTenMultiplier(greenButtonJson, intervalBlockEntry, emileDB);
if (energyDataTypeAndPower?.energyDataType === undefined) {
throw new Error('Unable to retrieve EnergyDataType.');
}
for (const intervalBlock of intervalBlockEntry.content.IntervalBlock) {
for (const intervalReading of intervalBlock.IntervalReading ?? []) {
if (intervalReading.timePeriod !== undefined &&
intervalReading.value !== undefined) {
const currentDataPoint = await getEnergyDataPoint({
assetId: assetId,
fileId: options.fileId,
dataValue: intervalReading.value,
powerOfTenMultiplier: energyDataTypeAndPower.powerOfTenMultiplier
}, greenButtonUser, emileDB);
recordCount += 1;
dataTypeId: energyDataTypeAndPower.energyDataType
.dataTypeId,
timeSeconds: intervalReading.timePeriod.start,
durationSeconds: intervalReading.timePeriod.duration
}, emileDB);
if (currentDataPoint === undefined) {
await addEnergyData({
assetId,
dataTypeId: energyDataTypeAndPower.energyDataType.dataTypeId,
fileId: options.fileId,
timeSeconds: intervalReading.timePeriod?.start,
durationSeconds: intervalReading.timePeriod?.duration,
dataValue: intervalReading.value,
powerOfTenMultiplier: energyDataTypeAndPower.powerOfTenMultiplier
}, greenButtonUser, emileDB);
recordCount += 1;
}
else if (currentDataPoint.dataValue !== intervalReading.value ||
currentDataPoint.powerOfTenMultiplier !==
energyDataTypeAndPower.powerOfTenMultiplier) {
await updateEnergyDataValue({
dataId: currentDataPoint.dataId,
assetId: assetId,
fileId: options.fileId,
dataValue: intervalReading.value,
powerOfTenMultiplier: energyDataTypeAndPower.powerOfTenMultiplier
}, greenButtonUser, emileDB);
recordCount += 1;
}
}
}
}
Expand All @@ -163,13 +182,13 @@ export async function recordGreenButtonData(greenButtonJson, options, connectedE
if ((assetId ?? '') === '') {
assetId = await getAssetIdFromUsageSummary(usageSummaryEntry, emileDB);
}
const energyDataType = await getEnergyDataType(greenButtonJson, usageSummaryEntry, emileDB);
if (energyDataType === undefined) {
throw new Error('Unable to retrieve EnergyDataType.');
const currencyDataType = await getCurrencyDataType(greenButtonJson, usageSummaryEntry, emileDB);
if (currencyDataType === undefined) {
throw new Error('Unable to retrieve EnergyDataType for currency.');
}
const currentDataPoint = await getEnergyDataPoint({
assetId: assetId,
dataTypeId: energyDataType.dataTypeId,
dataTypeId: currencyDataType.dataTypeId,
timeSeconds: usageSummaryEntry.content.UsageSummary.billingPeriod.start,
durationSeconds: usageSummaryEntry.content.UsageSummary.billingPeriod.duration
}, emileDB);
Expand All @@ -178,7 +197,7 @@ export async function recordGreenButtonData(greenButtonJson, options, connectedE
if (currentDataPoint === undefined) {
await addEnergyData({
assetId,
dataTypeId: energyDataType.dataTypeId,
dataTypeId: currencyDataType.dataTypeId,
fileId: options.fileId,
timeSeconds: usageSummaryEntry.content.UsageSummary.billingPeriod.start,
durationSeconds: usageSummaryEntry.content.UsageSummary.billingPeriod.duration,
Expand All @@ -198,6 +217,48 @@ export async function recordGreenButtonData(greenButtonJson, options, connectedE
}, greenButtonUser, emileDB);
recordCount += 1;
}
if (getConfigProperty('settings.greenButton.usageProperty') ===
'currentBillingPeriodOverAllConsumption') {
const usageDataType = await getUsageDataType(greenButtonJson, usageSummaryEntry, emileDB);
if (usageDataType === undefined) {
throw new Error('Unable to retrieve EnergyDataType for usage.');
}
const currentDataPoint = await getEnergyDataPoint({
assetId: assetId,
dataTypeId: usageDataType.dataTypeId,
timeSeconds: usageSummaryEntry.content.UsageSummary.billingPeriod.start,
durationSeconds: usageSummaryEntry.content.UsageSummary.billingPeriod.duration
}, emileDB);
const usageDataValue = usageSummaryEntry.content.UsageSummary
.currentBillingPeriodOverAllConsumption?.value ?? 0;
const usagePowerOfTenMultiplier = usageSummaryEntry.content.UsageSummary
.currentBillingPeriodOverAllConsumption?.powerOfTenMultiplier ?? '0';
if (currentDataPoint === undefined) {
await addEnergyData({
assetId,
dataTypeId: usageDataType.dataTypeId,
fileId: options.fileId,
timeSeconds: usageSummaryEntry.content.UsageSummary.billingPeriod.start,
durationSeconds: usageSummaryEntry.content.UsageSummary.billingPeriod.duration,
dataValue: usageDataValue,
powerOfTenMultiplier: typeof usagePowerOfTenMultiplier === 'string'
? Number.parseInt(usagePowerOfTenMultiplier)
: usagePowerOfTenMultiplier
}, greenButtonUser, emileDB);
recordCount += 1;
}
else if (currentDataPoint.dataValue !== dataValue ||
currentDataPoint.powerOfTenMultiplier !== powerOfTenMultiplier) {
await updateEnergyDataValue({
dataId: currentDataPoint.dataId,
assetId: assetId,
fileId: options.fileId,
dataValue,
powerOfTenMultiplier
}, greenButtonUser, emileDB);
recordCount += 1;
}
}
}
}
finally {
Expand Down
Loading

0 comments on commit ef14034

Please sign in to comment.