// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
+import { randomInt } from 'node:crypto'
+
import { hoursToMilliseconds, secondsToMilliseconds } from 'date-fns'
-import type { ChargingStation } from './ChargingStation.js'
-import { checkChargingStation } from './Helpers.js'
-import { IdTagsCache } from './IdTagsCache.js'
-import { isIdTagAuthorized } from './ocpp/index.js'
import { BaseError } from '../exception/index.js'
import { PerformanceStatistics } from '../performance/index.js'
import {
type StopTransactionResponse
} from '../types/index.js'
import {
- Constants,
clone,
+ Constants,
convertToDate,
formatDurationMilliSeconds,
- getRandomInteger,
isValidDate,
- logPrefix,
logger,
+ logPrefix,
secureRandom,
sleep
} from '../utils/index.js'
+import type { ChargingStation } from './ChargingStation.js'
+import { checkChargingStation } from './Helpers.js'
+import { IdTagsCache } from './IdTagsCache.js'
+import { isIdTagAuthorized } from './ocpp/index.js'
export class AutomaticTransactionGenerator {
private static readonly instances: Map<string, AutomaticTransactionGenerator> = new Map<
return AutomaticTransactionGenerator.instances.get(chargingStation.stationInfo!.hashId)
}
+ public static deleteInstance (chargingStation: ChargingStation): boolean {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return AutomaticTransactionGenerator.instances.delete(chargingStation.stationInfo!.hashId)
+ }
+
public start (stopAbsoluteDuration?: boolean): void {
if (!checkChargingStation(this.chargingStation, this.logPrefix())) {
return
break
}
const wait = secondsToMilliseconds(
- getRandomInteger(
+ randomInt(
this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
- ?.maxDelayBetweenTwoTransactions,
+ ?.minDelayBetweenTwoTransactions,
this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
- ?.minDelayBetweenTwoTransactions
+ ?.maxDelayBetweenTwoTransactions
)
)
logger.info(`${this.logPrefix(connectorId)} waiting for ${formatDurationMilliSeconds(wait)}`)
if (startResponse?.idTagInfo.status === AuthorizationStatus.ACCEPTED) {
// Wait until end of transaction
const waitTrxEnd = secondsToMilliseconds(
- getRandomInteger(
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.maxDuration,
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.minDuration
+ randomInt(
+ this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.minDuration,
+ this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.maxDuration
)
)
logger.info(
)
return false
}
+ const connectorStatus = this.chargingStation.getConnectorStatus(connectorId)
+ if (connectorStatus?.transactionStarted === true) {
+ logger.info(
+ `${this.logPrefix(connectorId)} entered in transaction loop while a transaction ${
+ connectorStatus.transactionId
+ } is already started on connector ${connectorId}`
+ )
+ return false
+ }
return true
}
while (connectorStatus?.transactionStarted === true) {
if (!logged) {
logger.info(
- `${this.logPrefix(
- connectorId
- )} transaction loop waiting for running transaction ${connectorStatus.transactionId} on connector ${connectorId} to be stopped`
+ `${this.logPrefix(connectorId)} transaction loop waiting for started transaction ${
+ connectorStatus.transactionId
+ } on connector ${connectorId} to be stopped`
)
logged = true
}
)
} else if (this.chargingStation.getAutomaticTransactionGeneratorStatuses() != null) {
logger.warn(
- `${this.logPrefix(connectorId)} no status found for connector #${connectorId} in charging station configuration file. New status will be created`
+ `${this.logPrefix(
+ connectorId
+ )} no status found for connector #${connectorId} in charging station configuration file. New status will be created`
)
}
if (connectorStatus != null) {
logger.info(startTransactionLogMsg)
// Start transaction
startResponse = await this.chargingStation.ocppRequestService.requestHandler<
- StartTransactionRequest,
+ Partial<StartTransactionRequest>,
StartTransactionResponse
>(this.chargingStation, RequestCommand.START_TRANSACTION, {
connectorId,
logger.info(startTransactionLogMsg)
// Start transaction
startResponse = await this.chargingStation.ocppRequestService.requestHandler<
- StartTransactionRequest,
+ Partial<StartTransactionRequest>,
StartTransactionResponse
>(this.chargingStation, RequestCommand.START_TRANSACTION, {
connectorId,
}
logger.info(`${this.logPrefix(connectorId)} start transaction without an idTag`)
startResponse = await this.chargingStation.ocppRequestService.requestHandler<
- StartTransactionRequest,
+ Partial<StartTransactionRequest>,
StartTransactionResponse
- >(this.chargingStation, RequestCommand.START_TRANSACTION, { connectorId })
+ >(this.chargingStation, RequestCommand.START_TRANSACTION, {
+ connectorId
+ })
this.handleStartTransactionResponse(connectorId, startResponse)
PerformanceStatistics.endMeasure(measureId, beginId)
return startResponse