1 import { PerformanceObserver
, performance
} from
'perf_hooks';
3 import ChargingStation from
'./ChargingStation';
4 import Constants from
'../utils/Constants';
5 import Utils from
'../utils/Utils';
6 import logger from
'../utils/Logger';
8 export default class AutomaticTransactionGenerator
{
9 private _chargingStation
: ChargingStation
;
10 private _timeToStop
: boolean;
11 private _performanceObserver
: PerformanceObserver
;
13 constructor(chargingStation
: ChargingStation
) {
14 this._chargingStation
= chargingStation
;
15 this._timeToStop
= true;
16 if (this._chargingStation
.getEnableStatistics()) {
17 this._performanceObserver
= new PerformanceObserver((list
) => {
18 const entry
= list
.getEntries()[0];
19 this._chargingStation
.statistics
.logPerformance(entry
, Constants
.ENTITY_AUTOMATIC_TRANSACTION_GENERATOR
);
20 this._performanceObserver
.disconnect();
25 get
timeToStop(): boolean {
26 return this._timeToStop
;
29 _logPrefix(connectorId
: number = null): string {
31 return Utils
.logPrefix(' ' + this._chargingStation
.stationInfo
.name
+ ' ATG on connector #' + connectorId
+ ':');
33 return Utils
.logPrefix(' ' + this._chargingStation
.stationInfo
.name
+ ' ATG:');
37 this._timeToStop
= false;
38 if (this._chargingStation
.stationInfo
.AutomaticTransactionGenerator
.stopAfterHours
&&
39 this._chargingStation
.stationInfo
.AutomaticTransactionGenerator
.stopAfterHours
> 0) {
42 }, this._chargingStation
.stationInfo
.AutomaticTransactionGenerator
.stopAfterHours
* 3600 * 1000);
44 for (const connector
in this._chargingStation
.connectors
) {
45 if (Utils
.convertToInt(connector
) > 0) {
46 this.startConnector(Utils
.convertToInt(connector
));
49 logger
.info(this._logPrefix() + ' ATG started and will stop in ' + Utils
.secondstoHHMMSS(this._chargingStation
.stationInfo
.AutomaticTransactionGenerator
.stopAfterHours
* 3600));
52 async stop(reason
= ''): Promise
<void> {
53 logger
.info(this._logPrefix() + ' ATG OVER => STOPPING ALL TRANSACTIONS');
54 for (const connector
in this._chargingStation
.connectors
) {
55 if (this._chargingStation
.getConnector(Utils
.convertToInt(connector
)).transactionStarted
) {
56 logger
.info(this._logPrefix(Utils
.convertToInt(connector
)) + ' ATG OVER. Stop transaction ' + this._chargingStation
.getConnector(Utils
.convertToInt(connector
)).transactionId
);
57 await this._chargingStation
.sendStopTransaction(this._chargingStation
.getConnector(Utils
.convertToInt(connector
)).transactionId
, reason
);
60 this._timeToStop
= true;
63 async startConnector(connectorId
: number): Promise
<void> {
65 const wait
= Utils
.getRandomInt(this._chargingStation
.stationInfo
.AutomaticTransactionGenerator
.maxDelayBetweenTwoTransactions
,
66 this._chargingStation
.stationInfo
.AutomaticTransactionGenerator
.minDelayBetweenTwoTransactions
) * 1000;
67 logger
.info(this._logPrefix(connectorId
) + ' wait for ' + Utils
.secondstoHHMMSS(wait
/ 1000));
68 await Utils
.sleep(wait
);
69 if (this._timeToStop
) {
70 logger
.debug(this._logPrefix(connectorId
) + ' Entered in transaction loop while a request to stop it was made');
73 const start
= Math.random();
75 if (start
< this._chargingStation
.stationInfo
.AutomaticTransactionGenerator
.probabilityOfStart
) {
79 if (this._chargingStation
.getEnableStatistics()) {
80 const startTransaction
= performance
.timerify(this.startTransaction
);
81 this._performanceObserver
.observe({ entryTypes
: ['function'] });
82 startResponse
= await startTransaction(connectorId
, this);
84 startResponse
= await this.startTransaction(connectorId
, this);
86 if (startResponse
.idTagInfo
.status !== 'Accepted') {
87 logger
.info(this._logPrefix(connectorId
) + ' transaction rejected');
88 await Utils
.sleep(Constants
.CHARGING_STATION_ATG_WAIT_TIME
);
90 // Wait until end of transaction
91 const waitTrxEnd
= Utils
.getRandomInt(this._chargingStation
.stationInfo
.AutomaticTransactionGenerator
.maxDuration
,
92 this._chargingStation
.stationInfo
.AutomaticTransactionGenerator
.minDuration
) * 1000;
93 logger
.info(this._logPrefix(connectorId
) + ' transaction ' + this._chargingStation
.getConnector(connectorId
).transactionId
+ ' will stop in ' + Utils
.secondstoHHMMSS(waitTrxEnd
/ 1000));
94 await Utils
.sleep(waitTrxEnd
);
96 if (this._chargingStation
.getConnector(connectorId
).transactionStarted
) {
97 logger
.info(this._logPrefix(connectorId
) + ' stop transaction ' + this._chargingStation
.getConnector(connectorId
).transactionId
);
98 if (this._chargingStation
.getEnableStatistics()) {
99 const stopTransaction
= performance
.timerify(this.stopTransaction
);
100 this._performanceObserver
.observe({ entryTypes
: ['function'] });
101 await stopTransaction(connectorId
, this);
103 await this.stopTransaction(connectorId
, this);
109 logger
.info(this._logPrefix(connectorId
) + ' transaction skipped ' + skip
.toString());
111 } while (!this._timeToStop
);
112 logger
.info(this._logPrefix(connectorId
) + ' ATG STOPPED on the connector');
115 // eslint-disable-next-line consistent-this
116 async startTransaction(connectorId
: number, self: AutomaticTransactionGenerator
): Promise
<unknown
> {
117 if (self._chargingStation
.hasAuthorizedTags()) {
118 const tagId
= self._chargingStation
.getRandomTagId();
119 logger
.info(self._logPrefix(connectorId
) + ' start transaction for tagID ' + tagId
);
120 return await self._chargingStation
.sendStartTransaction(connectorId
, tagId
);
122 logger
.info(self._logPrefix(connectorId
) + ' start transaction without a tagID');
123 return await self._chargingStation
.sendStartTransaction(connectorId
);
126 // eslint-disable-next-line consistent-this
127 async stopTransaction(connectorId
: number, self: AutomaticTransactionGenerator
): Promise
<void> {
128 await self._chargingStation
.sendStopTransaction(self._chargingStation
.getConnector(connectorId
).transactionId
);