Allow to disable statistics at the template level.
[e-mobility-charging-stations-simulator.git] / src / charging-station / AutomaticTransactionGenerator.js
1 const logger = require('../utils/Logger');
2 const Constants = require('../utils/Constants');
3 const Utils = require('../utils/Utils');
4 const {performance, PerformanceObserver} = require('perf_hooks');
5
6 class AutomaticTransactionGenerator {
7 constructor(chargingStation) {
8 this._chargingStation = chargingStation;
9 this._timeToStop = true;
10 if (this._chargingStation.getEnableStatistics()) {
11 this._performanceObserver = new PerformanceObserver((list) => {
12 const entry = list.getEntries()[0];
13 this._chargingStation._statistics.logPerformance(entry, 'AutomaticTransactionGenerator');
14 this._performanceObserver.disconnect();
15 });
16 }
17 }
18
19 get timeToStop() {
20 return this._timeToStop;
21 }
22
23 _logPrefix(connectorId = null) {
24 if (connectorId) {
25 return Utils.logPrefix(' ' + this._chargingStation._stationInfo.name + ' ATG on connector #' + connectorId + ':');
26 }
27 return Utils.logPrefix(' ' + this._chargingStation._stationInfo.name + ' ATG:');
28 }
29
30 async start() {
31 this._timeToStop = false;
32 if (this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAfterHours &&
33 this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAfterHours > 0) {
34 setTimeout(() => {
35 this.stop();
36 }, this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAfterHours * 3600 * 1000);
37 }
38 for (const connector in this._chargingStation._connectors) {
39 if (connector > 0) {
40 this.startConnector(connector);
41 }
42 }
43 logger.info(this._logPrefix() + ' ATG started and will stop in ' + Utils.secondstoHHMMSS(this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAfterHours * 3600));
44 }
45
46 async stop(reason = '') {
47 logger.info(this._logPrefix() + ' ATG OVER => STOPPING ALL TRANSACTIONS');
48 for (const connector in this._chargingStation._connectors) {
49 if (this._chargingStation.getConnector(connector).transactionStarted) {
50 logger.info(this._logPrefix(connector) + ' ATG OVER. Stop transaction ' + this._chargingStation.getConnector(connector).transactionId);
51 await this._chargingStation.sendStopTransaction(this._chargingStation.getConnector(connector).transactionId, reason);
52 }
53 }
54 this._timeToStop = true;
55 }
56
57 async startConnector(connectorId) {
58 do {
59 const wait = Utils.getRandomInt(this._chargingStation._stationInfo.AutomaticTransactionGenerator.maxDelayBetweenTwoTransactions,
60 this._chargingStation._stationInfo.AutomaticTransactionGenerator.minDelayBetweenTwoTransactions) * 1000;
61 logger.info(this._logPrefix(connectorId) + ' wait for ' + Utils.secondstoHHMMSS(wait / 1000));
62 await Utils.sleep(wait);
63 if (this._timeToStop) {
64 logger.debug(this._logPrefix(connectorId) + ' Entered in transaction loop while a request to stop it was made');
65 break;
66 }
67 const start = Math.random();
68 let skip = 0;
69 if (start < this._chargingStation._stationInfo.AutomaticTransactionGenerator.probabilityOfStart) {
70 skip = 0;
71 // Start transaction
72 let startResponse;
73 if (this._chargingStation.getEnableStatistics()) {
74 const startTransaction = performance.timerify(this.startTransaction);
75 this._performanceObserver.observe({entryTypes: ['function']});
76 startResponse = await startTransaction(connectorId, this);
77 } else {
78 startResponse = await this.startTransaction(connectorId, this);
79 }
80 if (startResponse.idTagInfo.status !== 'Accepted') {
81 logger.info(this._logPrefix(connectorId) + ' transaction rejected');
82 await Utils.sleep(Constants.CHARGING_STATION_ATG_WAIT_TIME);
83 } else {
84 // Wait until end of transaction
85 const wait = Utils.getRandomInt(this._chargingStation._stationInfo.AutomaticTransactionGenerator.maxDuration,
86 this._chargingStation._stationInfo.AutomaticTransactionGenerator.minDuration) * 1000;
87 logger.info(this._logPrefix(connectorId) + ' transaction ' + this._chargingStation.getConnector(connectorId).transactionId + ' will stop in ' + Utils.secondstoHHMMSS(wait / 1000));
88 await Utils.sleep(wait);
89 // Stop transaction
90 if (this._chargingStation.getConnector(connectorId).transactionStarted) {
91 logger.info(this._logPrefix(connectorId) + ' stop transaction ' + this._chargingStation.getConnector(connectorId).transactionId);
92 if (this._chargingStation.getEnableStatistics()) {
93 const stopTransaction = performance.timerify(this.stopTransaction);
94 this._performanceObserver.observe({entryTypes: ['function']});
95 await stopTransaction(connectorId, this);
96 } else {
97 await this.stopTransaction(connectorId, this);
98 }
99 }
100 }
101 } else {
102 skip++;
103 logger.info(this._logPrefix(connectorId) + ' transaction skipped ' + skip);
104 }
105 } while (!this._timeToStop);
106 logger.info(this._logPrefix(connectorId) + ' ATG STOPPED on the connector');
107 }
108
109 // eslint-disable-next-line class-methods-use-this
110 async startTransaction(connectorId, self) {
111 if (self._chargingStation.hasAuthorizedTags()) {
112 const tagId = self._chargingStation.getRandomTagId();
113 logger.info(self._logPrefix(connectorId) + ' start transaction for tagID ' + tagId);
114 return self._chargingStation.sendStartTransaction(connectorId, tagId);
115 }
116 return self._chargingStation.sendStartTransaction(connectorId);
117 }
118
119 // eslint-disable-next-line class-methods-use-this
120 async stopTransaction(connectorId, self) {
121 await self._chargingStation.sendStopTransaction(self._chargingStation.getConnector(connectorId).transactionId);
122 }
123 }
124
125 module.exports = AutomaticTransactionGenerator;