-import { ChargingProfile, ChargingSchedulePeriod } from '../types/ocpp/ChargingProfile';
-import { ChargingProfileKindType, RecurrencyKindType } from '../types/ocpp/1.6/ChargingProfile';
-import ChargingStationTemplate, { AmpereUnits } from '../types/ChargingStationTemplate';
+import crypto from 'node:crypto';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
-import { BootNotificationRequest } from '../types/ocpp/Requests';
-import ChargingStationInfo from '../types/ChargingStationInfo';
-import Configuration from '../utils/Configuration';
-import Constants from '../utils/Constants';
-import Utils from '../utils/Utils';
-import { WebSocketCloseEventStatusString } from '../types/WebSocket';
-import { WorkerProcessType } from '../types/Worker';
-import crypto from 'crypto';
-import logger from '../utils/Logger';
+import chalk from 'chalk';
import moment from 'moment';
+import type { ChargingStation } from './internal';
+import { BaseError } from '../exception';
+import {
+ AmpereUnits,
+ type BootNotificationRequest,
+ BootReasonEnumType,
+ type ChargingProfile,
+ ChargingProfileKindType,
+ ChargingRateUnitType,
+ type ChargingSchedulePeriod,
+ type ChargingStationInfo,
+ type ChargingStationTemplate,
+ CurrentType,
+ type OCPP16BootNotificationRequest,
+ type OCPP20BootNotificationRequest,
+ OCPPVersion,
+ RecurrencyKindType,
+ Voltage,
+} from '../types';
+import {
+ ACElectricUtils,
+ Configuration,
+ Constants,
+ DCElectricUtils,
+ Utils,
+ logger,
+} from '../utils';
+import { WorkerProcessType } from '../worker';
+
+const moduleName = 'ChargingStationUtils';
+
export class ChargingStationUtils {
+ private constructor() {
+ // This is intentional
+ }
+
public static getChargingStationId(
index: number,
stationTemplate: ChargingStationTemplate
): string {
// In case of multiple instances: add instance index to charging station id
const instanceIndex = process.env.CF_INSTANCE_INDEX ?? 0;
- const idSuffix = stationTemplate.nameSuffix ?? '';
- const idStr = '000000000' + index.toString();
- return stationTemplate.fixedName
+ const idSuffix = stationTemplate?.nameSuffix ?? '';
+ const idStr = `000000000${index.toString()}`;
+ return stationTemplate?.fixedName
? stationTemplate.baseName
- : stationTemplate.baseName +
- '-' +
- instanceIndex.toString() +
- idStr.substring(idStr.length - 4) +
- idSuffix;
+ : `${stationTemplate.baseName}-${instanceIndex.toString()}${idStr.substring(
+ idStr.length - 4
+ )}${idSuffix}`;
}
- public static getHashId(stationInfo: ChargingStationInfo): string {
- const hashBootNotificationRequest = {
- chargePointModel: stationInfo.chargePointModel,
- chargePointVendor: stationInfo.chargePointVendor,
- ...(!Utils.isUndefined(stationInfo.chargeBoxSerialNumberPrefix) && {
- chargeBoxSerialNumber: stationInfo.chargeBoxSerialNumberPrefix,
+ public static getHashId(index: number, stationTemplate: ChargingStationTemplate): string {
+ const chargingStationInfo = {
+ chargePointModel: stationTemplate.chargePointModel,
+ chargePointVendor: stationTemplate.chargePointVendor,
+ ...(!Utils.isUndefined(stationTemplate.chargeBoxSerialNumberPrefix) && {
+ chargeBoxSerialNumber: stationTemplate.chargeBoxSerialNumberPrefix,
}),
- ...(!Utils.isUndefined(stationInfo.chargePointSerialNumberPrefix) && {
- chargePointSerialNumber: stationInfo.chargePointSerialNumberPrefix,
+ ...(!Utils.isUndefined(stationTemplate.chargePointSerialNumberPrefix) && {
+ chargePointSerialNumber: stationTemplate.chargePointSerialNumberPrefix,
}),
- ...(!Utils.isUndefined(stationInfo.firmwareVersion) && {
- firmwareVersion: stationInfo.firmwareVersion,
+ ...(!Utils.isUndefined(stationTemplate.meterSerialNumberPrefix) && {
+ meterSerialNumber: stationTemplate.meterSerialNumberPrefix,
}),
- ...(!Utils.isUndefined(stationInfo.iccid) && { iccid: stationInfo.iccid }),
- ...(!Utils.isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi }),
- ...(!Utils.isUndefined(stationInfo.meterSerialNumberPrefix) && {
- meterSerialNumber: stationInfo.meterSerialNumberPrefix,
- }),
- ...(!Utils.isUndefined(stationInfo.meterType) && {
- meterType: stationInfo.meterType,
+ ...(!Utils.isUndefined(stationTemplate.meterType) && {
+ meterType: stationTemplate.meterType,
}),
};
return crypto
.createHash(Constants.DEFAULT_HASH_ALGORITHM)
- .update(JSON.stringify(hashBootNotificationRequest) + stationInfo.chargingStationId)
+ .update(
+ `${JSON.stringify(chargingStationInfo)}${ChargingStationUtils.getChargingStationId(
+ index,
+ stationTemplate
+ )}`
+ )
.digest('hex');
}
- public static createBootNotificationRequest(
- stationInfo: ChargingStationInfo
- ): BootNotificationRequest {
- return {
- chargePointModel: stationInfo.chargePointModel,
- chargePointVendor: stationInfo.chargePointVendor,
- ...(!Utils.isUndefined(stationInfo.chargeBoxSerialNumber) && {
- chargeBoxSerialNumber: stationInfo.chargeBoxSerialNumber,
- }),
- ...(!Utils.isUndefined(stationInfo.chargePointSerialNumber) && {
- chargePointSerialNumber: stationInfo.chargePointSerialNumber,
- }),
- ...(!Utils.isUndefined(stationInfo.firmwareVersion) && {
- firmwareVersion: stationInfo.firmwareVersion,
- }),
- ...(!Utils.isUndefined(stationInfo.iccid) && { iccid: stationInfo.iccid }),
- ...(!Utils.isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi }),
- ...(!Utils.isUndefined(stationInfo.meterSerialNumber) && {
- meterSerialNumber: stationInfo.meterSerialNumber,
- }),
- ...(!Utils.isUndefined(stationInfo.meterType) && {
- meterType: stationInfo.meterType,
- }),
- };
+ public static checkChargingStation(chargingStation: ChargingStation, logPrefix: string): boolean {
+ if (chargingStation.started === false && chargingStation.starting === false) {
+ logger.warn(`${logPrefix} charging station is stopped, cannot proceed`);
+ return false;
+ }
+ return true;
}
- public static workerPoolInUse(): boolean {
- return [WorkerProcessType.DYNAMIC_POOL, WorkerProcessType.STATIC_POOL].includes(
- Configuration.getWorkerProcess()
- );
+ public static getTemplateMaxNumberOfConnectors(stationTemplate: ChargingStationTemplate): number {
+ const templateConnectors = stationTemplate?.Connectors;
+ if (!templateConnectors) {
+ return -1;
+ }
+ return Object.keys(templateConnectors).length;
}
- public static workerDynamicPoolInUse(): boolean {
- return Configuration.getWorkerProcess() === WorkerProcessType.DYNAMIC_POOL;
+ public static checkTemplateMaxConnectors(
+ templateMaxConnectors: number,
+ templateFile: string,
+ logPrefix: string
+ ): void {
+ if (templateMaxConnectors === 0) {
+ logger.warn(
+ `${logPrefix} Charging station information from template ${templateFile} with empty connectors configuration`
+ );
+ } else if (templateMaxConnectors < 0) {
+ logger.error(
+ `${logPrefix} Charging station information from template ${templateFile} with no connectors configuration defined`
+ );
+ }
}
- /**
- * Convert websocket error code to human readable string message
- *
- * @param code websocket error code
- * @returns human readable string message
- */
- public static getWebSocketCloseEventStatusString(code: number): string {
- if (code >= 0 && code <= 999) {
- return '(Unused)';
- } else if (code >= 1016) {
- if (code <= 1999) {
- return '(For WebSocket standard)';
- } else if (code <= 2999) {
- return '(For WebSocket extensions)';
- } else if (code <= 3999) {
- return '(For libraries and frameworks)';
- } else if (code <= 4999) {
- return '(For applications)';
- }
- }
- if (!Utils.isUndefined(WebSocketCloseEventStatusString[code])) {
- return WebSocketCloseEventStatusString[code] as string;
+ public static getConfiguredNumberOfConnectors(stationTemplate: ChargingStationTemplate): number {
+ let configuredMaxConnectors: number;
+ if (Utils.isNotEmptyArray(stationTemplate.numberOfConnectors) === true) {
+ const numberOfConnectors = stationTemplate.numberOfConnectors as number[];
+ configuredMaxConnectors =
+ numberOfConnectors[Math.floor(Utils.secureRandom() * numberOfConnectors.length)];
+ } else if (Utils.isUndefined(stationTemplate.numberOfConnectors) === false) {
+ configuredMaxConnectors = stationTemplate.numberOfConnectors as number;
+ } else {
+ configuredMaxConnectors = stationTemplate?.Connectors[0]
+ ? ChargingStationUtils.getTemplateMaxNumberOfConnectors(stationTemplate) - 1
+ : ChargingStationUtils.getTemplateMaxNumberOfConnectors(stationTemplate);
}
- return '(Unknown)';
+ return configuredMaxConnectors;
}
- public static warnDeprecatedTemplateKey(
- template: ChargingStationTemplate,
- key: string,
+ public static checkConfiguredMaxConnectors(
+ configuredMaxConnectors: number,
templateFile: string,
- logPrefix: string,
- logMsgToAppend = ''
+ logPrefix: string
): void {
- if (!Utils.isUndefined(template[key])) {
- // const logPrefixStr = ` ${chargingStationId} |`;
+ if (configuredMaxConnectors <= 0) {
logger.warn(
- `${logPrefix} Deprecated template key '${key}' usage in file '${templateFile}'${
- logMsgToAppend && '. ' + logMsgToAppend
- }`
+ `${logPrefix} Charging station information from template ${templateFile} with ${configuredMaxConnectors} connectors`
);
}
}
- public static convertDeprecatedTemplateKey(
- template: ChargingStationTemplate,
- deprecatedKey: string,
- key: string
- ): void {
- if (!Utils.isUndefined(template[deprecatedKey])) {
- template[key] = template[deprecatedKey] as unknown;
- delete template[deprecatedKey];
+ public static createBootNotificationRequest(
+ stationInfo: ChargingStationInfo,
+ bootReason: BootReasonEnumType = BootReasonEnumType.PowerUp
+ ): BootNotificationRequest {
+ const ocppVersion = stationInfo.ocppVersion ?? OCPPVersion.VERSION_16;
+ switch (ocppVersion) {
+ case OCPPVersion.VERSION_16:
+ return {
+ chargePointModel: stationInfo.chargePointModel,
+ chargePointVendor: stationInfo.chargePointVendor,
+ ...(!Utils.isUndefined(stationInfo.chargeBoxSerialNumber) && {
+ chargeBoxSerialNumber: stationInfo.chargeBoxSerialNumber,
+ }),
+ ...(!Utils.isUndefined(stationInfo.chargePointSerialNumber) && {
+ chargePointSerialNumber: stationInfo.chargePointSerialNumber,
+ }),
+ ...(!Utils.isUndefined(stationInfo.firmwareVersion) && {
+ firmwareVersion: stationInfo.firmwareVersion,
+ }),
+ ...(!Utils.isUndefined(stationInfo.iccid) && { iccid: stationInfo.iccid }),
+ ...(!Utils.isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi }),
+ ...(!Utils.isUndefined(stationInfo.meterSerialNumber) && {
+ meterSerialNumber: stationInfo.meterSerialNumber,
+ }),
+ ...(!Utils.isUndefined(stationInfo.meterType) && {
+ meterType: stationInfo.meterType,
+ }),
+ } as OCPP16BootNotificationRequest;
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201:
+ return {
+ reason: bootReason,
+ chargingStation: {
+ model: stationInfo.chargePointModel,
+ vendorName: stationInfo.chargePointVendor,
+ ...(!Utils.isUndefined(stationInfo.firmwareVersion) && {
+ firmwareVersion: stationInfo.firmwareVersion,
+ }),
+ ...(!Utils.isUndefined(stationInfo.chargeBoxSerialNumber) && {
+ serialNumber: stationInfo.chargeBoxSerialNumber,
+ }),
+ ...((!Utils.isUndefined(stationInfo.iccid) || !Utils.isUndefined(stationInfo.imsi)) && {
+ modem: {
+ ...(!Utils.isUndefined(stationInfo.iccid) && { iccid: stationInfo.iccid }),
+ ...(!Utils.isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi }),
+ },
+ }),
+ },
+ } as OCPP20BootNotificationRequest;
}
}
- public static createStationInfoHash(stationInfo: ChargingStationInfo): ChargingStationInfo {
- if (!Utils.isEmptyObject(stationInfo)) {
- const previousInfoHash = stationInfo?.infoHash ?? '';
- delete stationInfo.infoHash;
- const currentInfoHash = crypto
- .createHash(Constants.DEFAULT_HASH_ALGORITHM)
- .update(JSON.stringify(stationInfo))
- .digest('hex');
- if (
- Utils.isEmptyString(previousInfoHash) ||
- (!Utils.isEmptyString(previousInfoHash) && currentInfoHash !== previousInfoHash)
- ) {
- stationInfo.infoHash = currentInfoHash;
- } else {
- stationInfo.infoHash = previousInfoHash;
- }
+ public static workerPoolInUse(): boolean {
+ return [WorkerProcessType.dynamicPool, WorkerProcessType.staticPool].includes(
+ Configuration.getWorker().processType
+ );
+ }
+
+ public static workerDynamicPoolInUse(): boolean {
+ return Configuration.getWorker().processType === WorkerProcessType.dynamicPool;
+ }
+
+ public static warnTemplateKeysDeprecation(
+ templateFile: string,
+ stationTemplate: ChargingStationTemplate,
+ logPrefix: string
+ ) {
+ const templateKeys: { key: string; deprecatedKey: string }[] = [
+ { key: 'supervisionUrls', deprecatedKey: 'supervisionUrl' },
+ { key: 'idTagsFile', deprecatedKey: 'authorizationFile' },
+ ];
+ for (const templateKey of templateKeys) {
+ ChargingStationUtils.warnDeprecatedTemplateKey(
+ stationTemplate,
+ templateKey.deprecatedKey,
+ templateFile,
+ logPrefix,
+ `Use '${templateKey.key}' instead`
+ );
+ ChargingStationUtils.convertDeprecatedTemplateKey(
+ stationTemplate,
+ templateKey.deprecatedKey,
+ templateKey.key
+ );
}
- return stationInfo;
+ }
+
+ public static stationTemplateToStationInfo(
+ stationTemplate: ChargingStationTemplate
+ ): ChargingStationInfo {
+ stationTemplate = Utils.cloneObject(stationTemplate);
+ delete stationTemplate.power;
+ delete stationTemplate.powerUnit;
+ delete stationTemplate.Configuration;
+ delete stationTemplate.AutomaticTransactionGenerator;
+ delete stationTemplate.chargeBoxSerialNumberPrefix;
+ delete stationTemplate.chargePointSerialNumberPrefix;
+ delete stationTemplate.meterSerialNumberPrefix;
+ return stationTemplate as unknown as ChargingStationInfo;
+ }
+
+ public static createStationInfoHash(stationInfo: ChargingStationInfo): void {
+ delete stationInfo.infoHash;
+ stationInfo.infoHash = crypto
+ .createHash(Constants.DEFAULT_HASH_ALGORITHM)
+ .update(JSON.stringify(stationInfo))
+ .digest('hex');
}
public static createSerialNumber(
+ stationTemplate: ChargingStationTemplate,
stationInfo: ChargingStationInfo,
- existingStationInfo?: ChargingStationInfo,
- params: { randomSerialNumberUpperCase?: boolean; randomSerialNumber?: boolean } = {
+ params: {
+ randomSerialNumberUpperCase?: boolean;
+ randomSerialNumber?: boolean;
+ } = {
randomSerialNumberUpperCase: true,
randomSerialNumber: true,
}
params = params ?? {};
params.randomSerialNumberUpperCase = params?.randomSerialNumberUpperCase ?? true;
params.randomSerialNumber = params?.randomSerialNumber ?? true;
- if (!Utils.isEmptyObject(existingStationInfo)) {
- existingStationInfo?.chargePointSerialNumber &&
- (stationInfo.chargePointSerialNumber = existingStationInfo.chargePointSerialNumber);
- existingStationInfo?.chargeBoxSerialNumber &&
- (stationInfo.chargeBoxSerialNumber = existingStationInfo.chargeBoxSerialNumber);
- existingStationInfo?.meterSerialNumber &&
- (stationInfo.meterSerialNumber = existingStationInfo.meterSerialNumber);
- } else {
- const serialNumberSuffix = params?.randomSerialNumber
- ? ChargingStationUtils.getRandomSerialNumberSuffix({
- upperCase: params.randomSerialNumberUpperCase,
- })
- : '';
- stationInfo.chargePointSerialNumber =
- stationInfo?.chargePointSerialNumberPrefix &&
- stationInfo.chargePointSerialNumberPrefix + serialNumberSuffix;
- stationInfo.chargeBoxSerialNumber =
- stationInfo?.chargeBoxSerialNumberPrefix &&
- stationInfo.chargeBoxSerialNumberPrefix + serialNumberSuffix;
- stationInfo.meterSerialNumber =
- stationInfo?.meterSerialNumberPrefix &&
- stationInfo.meterSerialNumberPrefix + serialNumberSuffix;
+ const serialNumberSuffix = params?.randomSerialNumber
+ ? ChargingStationUtils.getRandomSerialNumberSuffix({
+ upperCase: params.randomSerialNumberUpperCase,
+ })
+ : '';
+ stationInfo.chargePointSerialNumber = Utils.isNotEmptyString(
+ stationTemplate?.chargePointSerialNumberPrefix
+ )
+ ? `${stationTemplate.chargePointSerialNumberPrefix}${serialNumberSuffix}`
+ : undefined;
+ stationInfo.chargeBoxSerialNumber = Utils.isNotEmptyString(
+ stationTemplate?.chargeBoxSerialNumberPrefix
+ )
+ ? `${stationTemplate.chargeBoxSerialNumberPrefix}${serialNumberSuffix}`
+ : undefined;
+ stationInfo.meterSerialNumber = Utils.isNotEmptyString(stationTemplate?.meterSerialNumberPrefix)
+ ? `${stationTemplate.meterSerialNumberPrefix}${serialNumberSuffix}`
+ : undefined;
+ }
+
+ public static propagateSerialNumber(
+ stationTemplate: ChargingStationTemplate,
+ stationInfoSrc: ChargingStationInfo,
+ stationInfoDst: ChargingStationInfo
+ ) {
+ if (!stationInfoSrc || !stationTemplate) {
+ throw new BaseError(
+ 'Missing charging station template or existing configuration to propagate serial number'
+ );
}
+ stationTemplate?.chargePointSerialNumberPrefix && stationInfoSrc?.chargePointSerialNumber
+ ? (stationInfoDst.chargePointSerialNumber = stationInfoSrc.chargePointSerialNumber)
+ : stationInfoDst?.chargePointSerialNumber && delete stationInfoDst.chargePointSerialNumber;
+ stationTemplate?.chargeBoxSerialNumberPrefix && stationInfoSrc?.chargeBoxSerialNumber
+ ? (stationInfoDst.chargeBoxSerialNumber = stationInfoSrc.chargeBoxSerialNumber)
+ : stationInfoDst?.chargeBoxSerialNumber && delete stationInfoDst.chargeBoxSerialNumber;
+ stationTemplate?.meterSerialNumberPrefix && stationInfoSrc?.meterSerialNumber
+ ? (stationInfoDst.meterSerialNumber = stationInfoSrc.meterSerialNumber)
+ : stationInfoDst?.meterSerialNumber && delete stationInfoDst.meterSerialNumber;
}
public static getAmperageLimitationUnitDivider(stationInfo: ChargingStationInfo): number {
return unitDivider;
}
+ public static getChargingStationConnectorChargingProfilesPowerLimit(
+ chargingStation: ChargingStation,
+ connectorId: number
+ ): number | undefined {
+ let limit: number, matchingChargingProfile: ChargingProfile;
+ // Get charging profiles for connector and sort by stack level
+ const chargingProfiles =
+ Utils.cloneObject(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)?.sort(
+ (a, b) => b.stackLevel - a.stackLevel
+ ) ?? [];
+ // Get profiles on connector 0
+ if (chargingStation.getConnectorStatus(0)?.chargingProfiles) {
+ chargingProfiles.push(
+ ...Utils.cloneObject(chargingStation.getConnectorStatus(0).chargingProfiles).sort(
+ (a, b) => b.stackLevel - a.stackLevel
+ )
+ );
+ }
+ if (Utils.isNotEmptyArray(chargingProfiles)) {
+ const result = ChargingStationUtils.getLimitFromChargingProfiles(
+ chargingProfiles,
+ chargingStation.logPrefix()
+ );
+ if (!Utils.isNullOrUndefined(result)) {
+ limit = result?.limit;
+ matchingChargingProfile = result?.matchingChargingProfile;
+ switch (chargingStation.getCurrentOutType()) {
+ case CurrentType.AC:
+ limit =
+ matchingChargingProfile.chargingSchedule.chargingRateUnit ===
+ ChargingRateUnitType.WATT
+ ? limit
+ : ACElectricUtils.powerTotal(
+ chargingStation.getNumberOfPhases(),
+ chargingStation.getVoltageOut(),
+ limit
+ );
+ break;
+ case CurrentType.DC:
+ limit =
+ matchingChargingProfile.chargingSchedule.chargingRateUnit ===
+ ChargingRateUnitType.WATT
+ ? limit
+ : DCElectricUtils.power(chargingStation.getVoltageOut(), limit);
+ }
+ const connectorMaximumPower =
+ chargingStation.getMaximumPower() / chargingStation.powerDivider;
+ if (limit > connectorMaximumPower) {
+ logger.error(
+ `${chargingStation.logPrefix()} Charging profile id ${
+ matchingChargingProfile.chargingProfileId
+ } limit ${limit} is greater than connector id ${connectorId} maximum ${connectorMaximumPower}: %j`,
+ result
+ );
+ limit = connectorMaximumPower;
+ }
+ }
+ }
+ return limit;
+ }
+
+ public static getDefaultVoltageOut(
+ currentType: CurrentType,
+ templateFile: string,
+ logPrefix: string
+ ): Voltage {
+ const errMsg = `Unknown ${currentType} currentOutType in template file ${templateFile}, cannot define default voltage out`;
+ let defaultVoltageOut: number;
+ switch (currentType) {
+ case CurrentType.AC:
+ defaultVoltageOut = Voltage.VOLTAGE_230;
+ break;
+ case CurrentType.DC:
+ defaultVoltageOut = Voltage.VOLTAGE_400;
+ break;
+ default:
+ logger.error(`${logPrefix} ${errMsg}`);
+ throw new BaseError(errMsg);
+ }
+ return defaultVoltageOut;
+ }
+
+ public static getIdTagsFile(stationInfo: ChargingStationInfo): string | undefined {
+ return (
+ stationInfo.idTagsFile &&
+ path.join(
+ path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../'),
+ 'assets',
+ path.basename(stationInfo.idTagsFile)
+ )
+ );
+ }
+
+ private static warnDeprecatedTemplateKey(
+ template: ChargingStationTemplate,
+ key: string,
+ templateFile: string,
+ logPrefix: string,
+ logMsgToAppend = ''
+ ): void {
+ if (!Utils.isUndefined(template[key])) {
+ const logMsg = `Deprecated template key '${key}' usage in file '${templateFile}'${
+ Utils.isNotEmptyString(logMsgToAppend) ? `. ${logMsgToAppend}` : ''
+ }`;
+ logger.warn(`${logPrefix} ${logMsg}`);
+ console.warn(chalk.yellow(`${logMsg}`));
+ }
+ }
+
+ private static convertDeprecatedTemplateKey(
+ template: ChargingStationTemplate,
+ deprecatedKey: string,
+ key: string
+ ): void {
+ if (!Utils.isUndefined(template[deprecatedKey])) {
+ template[key] = template[deprecatedKey] as unknown;
+ delete template[deprecatedKey];
+ }
+ }
+
/**
* Charging profiles should already be sorted by connectorId and stack level (highest stack level has priority)
*
- * @param {ChargingProfile[]} chargingProfiles
- * @param {string} logPrefix
- * @returns {{ limit, matchingChargingProfile }}
+ * @param chargingProfiles -
+ * @param logPrefix -
+ * @returns
*/
- public static getLimitFromChargingProfiles(
+ private static getLimitFromChargingProfiles(
chargingProfiles: ChargingProfile[],
logPrefix: string
): {
limit: number;
matchingChargingProfile: ChargingProfile;
} | null {
+ const debugLogMsg = `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Matching charging profile found for power limitation: %j`;
+ const currentMoment = moment();
+ const currentDate = new Date();
for (const chargingProfile of chargingProfiles) {
// Set helpers
- const currentMoment = moment();
const chargingSchedule = chargingProfile.chargingSchedule;
+ if (!chargingSchedule?.startSchedule) {
+ logger.warn(
+ `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: startSchedule is not defined in charging profile id ${chargingProfile.chargingProfileId}`
+ );
+ }
// Check type (recurring) and if it is already active
// Adjust the daily recurring schedule to today
if (
chargingProfile.recurrencyKind === RecurrencyKindType.DAILY &&
currentMoment.isAfter(chargingSchedule.startSchedule)
) {
- const currentDate = new Date();
- chargingSchedule.startSchedule = new Date(chargingSchedule.startSchedule);
+ if (!(chargingSchedule?.startSchedule instanceof Date)) {
+ logger.warn(
+ `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: startSchedule is not a Date object in charging profile id ${chargingProfile.chargingProfileId}. Trying to convert it to a Date object`
+ );
+ chargingSchedule.startSchedule = new Date(chargingSchedule.startSchedule);
+ }
chargingSchedule.startSchedule.setFullYear(
currentDate.getFullYear(),
currentDate.getMonth(),
limit: schedulePeriod.limit,
matchingChargingProfile: chargingProfile,
};
- logger.debug(
- `${logPrefix} Matching charging profile found for power limitation: %j`,
- result
- );
+ logger.debug(debugLogMsg, result);
return result;
}
// Find the right schedule period
limit: lastButOneSchedule.limit,
matchingChargingProfile: chargingProfile,
};
- logger.debug(
- `${logPrefix} Matching charging profile found for power limitation: %j`,
- result
- );
+ logger.debug(debugLogMsg, result);
return result;
}
// Keep it
limit: lastButOneSchedule.limit,
matchingChargingProfile: chargingProfile,
};
- logger.debug(
- `${logPrefix} Matching charging profile found for power limitation: %j`,
- result
- );
+ logger.debug(debugLogMsg, result);
return result;
}
}