-import crypto from 'node:crypto';
-import path from 'node:path';
+import { createHash, randomBytes } from 'node:crypto';
+import type { EventEmitter } from 'node:events';
+import { basename, dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import chalk from 'chalk';
import moment from 'moment';
-import type { ChargingStation } from './internal';
+import type { ChargingStation } from './ChargingStation';
import { BaseError } from '../exception';
import {
AmpereUnits,
type ChargingSchedulePeriod,
type ChargingStationInfo,
type ChargingStationTemplate,
+ ChargingStationWorkerMessageEvents,
ConnectorPhaseRotation,
type ConnectorStatus,
ConnectorStatusEnum,
RecurrencyKindType,
Voltage,
} from '../types';
-import {
- ACElectricUtils,
- Configuration,
- Constants,
- DCElectricUtils,
- Utils,
- logger,
-} from '../utils';
-import { WorkerProcessType } from '../worker';
+import { ACElectricUtils, Constants, DCElectricUtils, Utils, logger } from '../utils';
const moduleName = 'ChargingStationUtils';
)}${idSuffix}`;
}
+ public static countReservableConnectors(connectors: Map<number, ConnectorStatus>) {
+ let reservableConnectors = 0;
+ for (const [connectorId, connectorStatus] of connectors) {
+ if (connectorId === 0) {
+ continue;
+ }
+ if (connectorStatus.status === ConnectorStatusEnum.Available) {
+ ++reservableConnectors;
+ }
+ }
+ return reservableConnectors;
+ }
+
public static getHashId(index: number, stationTemplate: ChargingStationTemplate): string {
const chargingStationInfo = {
chargePointModel: stationTemplate.chargePointModel,
meterType: stationTemplate.meterType,
}),
};
- return crypto
- .createHash(Constants.DEFAULT_HASH_ALGORITHM)
+ return createHash(Constants.DEFAULT_HASH_ALGORITHM)
.update(
`${JSON.stringify(chargingStationInfo)}${ChargingStationUtils.getChargingStationId(
index,
return connectorBootStatus;
}
- public static checkTemplateFile(
+ public static checkTemplate(
stationTemplate: ChargingStationTemplate,
logPrefix: string,
templateFile: string
throw new BaseError(errorMsg);
}
if (Utils.isEmptyObject(stationTemplate.AutomaticTransactionGenerator)) {
- stationTemplate.AutomaticTransactionGenerator = {
- enable: false,
- minDuration: 60,
- maxDuration: 120,
- minDelayBetweenTwoTransactions: 15,
- maxDelayBetweenTwoTransactions: 30,
- probabilityOfStart: 1,
- stopAfterHours: 0.3,
- stopOnConnectionFailure: true,
- };
+ stationTemplate.AutomaticTransactionGenerator = Constants.DEFAULT_ATG_CONFIGURATION;
logger.warn(
- `${logPrefix} Empty automatic transaction generator configuration from template file ${templateFile}, set to default values`
+ `${logPrefix} Empty automatic transaction generator configuration from template file ${templateFile}, set to default: %j`,
+ Constants.DEFAULT_ATG_CONFIGURATION
+ );
+ }
+ if (
+ Utils.isNullOrUndefined(stationTemplate.idTagsFile) ||
+ Utils.isEmptyString(stationTemplate.idTagsFile)
+ ) {
+ logger.warn(
+ `${logPrefix} Missing id tags file in template file ${templateFile}. That can lead to issues with the Automatic Transaction Generator`
);
}
}
}
}
- 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(
stationTemplate: ChargingStationTemplate,
logPrefix: string,
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)
- )
+ join(dirname(fileURLToPath(import.meta.url)), 'assets', basename(stationInfo.idTagsFile))
);
}
+ public static waitForChargingStationEvents = async (
+ emitter: EventEmitter,
+ event: ChargingStationWorkerMessageEvents,
+ eventsToWait: number
+ ): Promise<number> => {
+ return new Promise((resolve) => {
+ let events = 0;
+ if (eventsToWait === 0) {
+ resolve(events);
+ }
+ emitter.on(event, () => {
+ ++events;
+ if (events === eventsToWait) {
+ resolve(events);
+ }
+ });
+ });
+ };
+
private static getConfiguredNumberOfConnectors(stationTemplate: ChargingStationTemplate): number {
let configuredMaxConnectors: number;
if (Utils.isNotEmptyArray(stationTemplate.numberOfConnectors) === true) {
randomBytesLength?: number;
upperCase?: boolean;
}): string {
- const randomSerialNumberSuffix = crypto
- .randomBytes(params?.randomBytesLength ?? 16)
- .toString('hex');
+ const randomSerialNumberSuffix = randomBytes(params?.randomBytesLength ?? 16).toString('hex');
if (params?.upperCase) {
return randomSerialNumberSuffix.toUpperCase();
}