feat: enhance PowerClamp service with energy consumption procedures and enums

This commit is contained in:
faris Aljohari
2025-04-24 03:14:03 +03:00
parent f3fd6646a1
commit 881618a4ee
9 changed files with 87 additions and 126 deletions

View File

@ -1,109 +1,61 @@
import { Injectable } from '@nestjs/common';
import {
PowerClampDailyRepository,
PowerClampHourlyRepository,
PowerClampMonthlyRepository,
} from '@app/common/modules/power-clamp/repositories';
import { SqlLoaderService } from './sql-loader.service';
import { DataSource } from 'typeorm';
import { SQL_PROCEDURES_PATH } from '@app/common/constants/sql-query-path';
@Injectable()
export class PowerClampService {
constructor(
private readonly powerClampHourlyRepository: PowerClampHourlyRepository,
private readonly powerClampDailyRepository: PowerClampDailyRepository,
private readonly powerClampMonthlyRepository: PowerClampMonthlyRepository,
private readonly sqlLoader: SqlLoaderService,
private readonly dataSource: DataSource,
) {}
async insertOrUpdatePowerClamp(
deviceUuid: string,
logData: any,
): Promise<void> {
async updateEnergyConsumedHistoricalData(deviceUuid: string): Promise<void> {
try {
await this.insertOrUpdateHourly(deviceUuid, logData);
const now = new Date();
const dateStr = now.toLocaleDateString('en-CA'); // YYYY-MM-DD
const hour = now.getHours();
const monthYear = now
.toLocaleDateString('en-US', {
month: '2-digit',
year: 'numeric',
})
.replace('/', '-'); // MM-YYYY
await this.executeProcedure('fact_hourly_energy_consumed_procedure', [
deviceUuid,
dateStr,
hour,
]);
await this.executeProcedure('fact_daily_energy_consumed_procedure', [
deviceUuid,
dateStr,
]);
await this.executeProcedure('fact_monthly_energy_consumed_procedure', [
deviceUuid,
monthYear,
]);
} catch (err) {
console.error('Failed to insert or update hourly data', err);
console.error('Failed to insert or update energy data:', err);
throw err;
}
}
async insertOrUpdateHourly(
deviceUuid: string,
logData: LogData,
private async executeProcedure(
procedureFileName: string,
params: (string | number | null)[],
): Promise<void> {
try {
const currentDate = new Date().toLocaleDateString('en-CA');
const currentHour = new Date().getHours().toString();
const query = this.loadQuery(procedureFileName);
await this.dataSource.query(query, params);
}
// First try to update existing record
const existingData = await this.powerClampHourlyRepository.findOne({
where: {
deviceUuid,
date: currentDate,
hour: currentHour,
},
});
if (existingData) {
// Create update object only with values that exist in logData
const updateData: Partial<any> = {};
const hasProperty = (code: string) =>
logData.properties.some((p) => p.code === code);
const getValue = (code: string) => {
const prop = logData.properties.find((p) => p.code === code);
return prop ? Number(prop.value) : undefined;
};
if (hasProperty('EnergyConsumedA')) {
updateData.energyConsumedA = String(getValue('EnergyConsumedA'));
}
if (hasProperty('EnergyConsumedB')) {
updateData.energyConsumedB = String(getValue('EnergyConsumedB'));
}
if (hasProperty('EnergyConsumedC')) {
updateData.energyConsumedC = String(getValue('EnergyConsumedC'));
}
if (hasProperty('EnergyConsumed')) {
updateData.energyConsumedKw = String(getValue('EnergyConsumed'));
}
if (Object.keys(updateData).length > 0) {
await this.powerClampHourlyRepository.update(
existingData.uuid,
updateData,
);
}
} else {
// Insert new record with all required fields
const getValue = (code: string) => {
const prop = logData.properties.find((p) => p.code === code);
return prop ? Number(prop.value) : 0; // Default to 0 for required fields
};
await this.powerClampHourlyRepository.insert({
deviceUuid,
date: currentDate,
hour: currentHour,
energyConsumedA: String(getValue('EnergyConsumedA')),
energyConsumedB: String(getValue('EnergyConsumedB')),
energyConsumedC: String(getValue('EnergyConsumedC')),
energyConsumedKw: String(getValue('EnergyConsumed')),
});
}
} catch (err) {
console.error('Failed to insert or update hourly data', err);
throw err;
}
private loadQuery(fileName: string): string {
return this.sqlLoader.loadQuery(
'fact_energy_consumed',
fileName,
SQL_PROCEDURES_PATH,
);
}
}
interface EnergyProperties {
code: string;
dpId: number;
time: number;
value: string | number;
}
interface LogData {
devId: string;
dataId: string;
productId: string;
properties: EnergyProperties[];
}

View File

@ -1,4 +1,3 @@
import { SQL_QUERIES_PATH } from '@app/common/constants/sql-query-path';
import { Injectable, Logger } from '@nestjs/common';
import { readFileSync } from 'fs';
import { join } from 'path';
@ -8,13 +7,8 @@ export class SqlLoaderService {
private readonly logger = new Logger(SqlLoaderService.name);
private readonly sqlRootPath = join(__dirname, '../sql/queries');
loadQuery(module: string, queryName: string): string {
const filePath = join(
process.cwd(),
SQL_QUERIES_PATH,
module,
`${queryName}.sql`,
);
loadQuery(module: string, queryName: string, path: string): string {
const filePath = join(process.cwd(), path, module, `${queryName}.sql`);
try {
return readFileSync(filePath, 'utf8');
} catch (error) {