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