}
},
"@types/node": {
- "version": "14.17.18",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.18.tgz",
- "integrity": "sha512-haYyibw4pbteEhkSg0xdDLAI3679L75EJ799ymVrPxOA922bPx3ML59SoDsQ//rHlvqpu+e36kcbR3XRQtFblA=="
+ "version": "14.17.19",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.19.tgz",
+ "integrity": "sha512-jjYI6NkyfXykucU6ELEoT64QyKOdvaA6enOqKtP4xUsGY0X0ZUZz29fUmrTRo+7v7c6TgDu82q3GHHaCEkqZwA=="
},
"@types/object-path": {
"version": "0.11.1",
}
},
"expect": {
- "version": "27.2.1",
- "resolved": "https://registry.npmjs.org/expect/-/expect-27.2.1.tgz",
- "integrity": "sha512-ekOA2mBtT2phxcoPVHCXIzbJxCvRXhx2fr7m28IgGdZxUOh8UvxvoRz1FcPlfgZMpE92biHB6woIcAKXqR28hA==",
+ "version": "27.2.2",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-27.2.2.tgz",
+ "integrity": "sha512-sjHBeEk47/eshN9oLbvPJZMgHQihOXXQzSMPCJ4MqKShbU9HOVFSNHEEU4dp4ujzxFSiNvPFzB2AMOFmkizhvA==",
"dev": true,
"requires": {
"@jest/types": "^27.1.1",
"ansi-styles": "^5.0.0",
"jest-get-type": "^27.0.6",
- "jest-matcher-utils": "^27.2.0",
- "jest-message-util": "^27.2.0",
+ "jest-matcher-utils": "^27.2.2",
+ "jest-message-util": "^27.2.2",
"jest-regex-util": "^27.0.6"
},
"dependencies": {
}
},
"jest-diff": {
- "version": "27.2.0",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.2.0.tgz",
- "integrity": "sha512-QSO9WC6btFYWtRJ3Hac0sRrkspf7B01mGrrQEiCW6TobtViJ9RWL0EmOs/WnBsZDsI/Y2IoSHZA2x6offu0sYw==",
+ "version": "27.2.2",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.2.2.tgz",
+ "integrity": "sha512-o3LaDbQDSaMJif4yztJAULI4xVatxbBasbKLbEw3K8CiRdDdbxMrLArS9EKDHQFYh6Tgfrm1PC2mIYR1xhu0hQ==",
"dev": true,
"requires": {
"chalk": "^4.0.0",
"diff-sequences": "^27.0.6",
"jest-get-type": "^27.0.6",
- "pretty-format": "^27.2.0"
+ "pretty-format": "^27.2.2"
}
},
"jest-get-type": {
"dev": true
},
"jest-matcher-utils": {
- "version": "27.2.0",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.2.0.tgz",
- "integrity": "sha512-F+LG3iTwJ0gPjxBX6HCyrARFXq6jjiqhwBQeskkJQgSLeF1j6ui1RTV08SR7O51XTUhtc8zqpDj8iCG4RGmdKw==",
+ "version": "27.2.2",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.2.2.tgz",
+ "integrity": "sha512-xN3wT4p2i9DGB6zmL3XxYp5lJmq9Q6ff8XKlMtVVBS2SAshmgsPBALJFQ8dWRd2G/xf5q/N0SD0Mipt8QBA26A==",
"dev": true,
"requires": {
"chalk": "^4.0.0",
- "jest-diff": "^27.2.0",
+ "jest-diff": "^27.2.2",
"jest-get-type": "^27.0.6",
- "pretty-format": "^27.2.0"
+ "pretty-format": "^27.2.2"
}
},
"jest-message-util": {
- "version": "27.2.0",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.2.0.tgz",
- "integrity": "sha512-y+sfT/94CiP8rKXgwCOzO1mUazIEdEhrLjuiu+RKmCP+8O/TJTSne9dqQRbFIHBtlR2+q7cddJlWGir8UATu5w==",
+ "version": "27.2.2",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.2.2.tgz",
+ "integrity": "sha512-/iS5/m2FSF7Nn6APFoxFymJpyhB/gPf0CJa7uFSkbYaWvrADUfQ9NTsuyjpszKErOS2/huFs44ysWhlQTKvL8Q==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",
"chalk": "^4.0.0",
"graceful-fs": "^4.2.4",
"micromatch": "^4.0.4",
- "pretty-format": "^27.2.0",
+ "pretty-format": "^27.2.2",
"slash": "^3.0.0",
"stack-utils": "^2.0.3"
},
"dev": true
},
"mocha": {
- "version": "9.1.1",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.1.tgz",
- "integrity": "sha512-0wE74YMgOkCgBUj8VyIDwmLUjTsS13WV1Pg7l0SHea2qzZzlq7MDnfbPsHKcELBRk3+izEVkRofjmClpycudCA==",
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.2.tgz",
+ "integrity": "sha512-ta3LtJ+63RIBP03VBjMGtSqbe6cWXRejF9SyM9Zyli1CKZJZ+vfCTj3oW24V7wAphMJdpOFLoMI3hjJ1LWbs0w==",
"dev": true,
"requires": {
"@ungap/promise-all-settled": "1.1.2",
"ansi-colors": "4.1.1",
"browser-stdout": "1.3.1",
"chokidar": "3.5.2",
- "debug": "4.3.1",
+ "debug": "4.3.2",
"diff": "5.0.0",
"escape-string-regexp": "4.0.0",
"find-up": "5.0.0",
"log-symbols": "4.1.0",
"minimatch": "3.0.4",
"ms": "2.1.3",
- "nanoid": "3.1.23",
+ "nanoid": "3.1.25",
"serialize-javascript": "6.0.0",
"strip-json-comments": "3.1.1",
"supports-color": "8.1.1",
"which": "2.0.2",
- "wide-align": "1.1.3",
"workerpool": "6.1.5",
"yargs": "16.2.0",
"yargs-parser": "20.2.4",
},
"dependencies": {
"ansi-regex": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
- "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"ansi-styles": {
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "debug": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
+ "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
+ "nanoid": {
+ "version": "3.1.25",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz",
+ "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==",
+ "dev": true
+ },
"p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
}
},
"string-width": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
- "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.0"
+ "strip-ansi": "^6.0.1"
}
},
"strip-ansi": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
- "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": {
- "ansi-regex": "^5.0.0"
+ "ansi-regex": "^5.0.1"
}
},
"strip-json-comments": {
"dev": true
},
"pretty-format": {
- "version": "27.2.0",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.2.0.tgz",
- "integrity": "sha512-KyJdmgBkMscLqo8A7K77omgLx5PWPiXJswtTtFV7XgVZv2+qPk6UivpXXO+5k6ZEbWIbLoKdx1pZ6ldINzbwTA==",
+ "version": "27.2.2",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.2.2.tgz",
+ "integrity": "sha512-+DdLh+rtaElc2SQOE/YPH8k2g3Rf2OXWEpy06p8Szs3hdVSYD87QOOlYRHWAeb/59XTmeVmRKvDD0svHqf6ycA==",
"dev": true,
"requires": {
"@jest/types": "^27.1.1",
- "ansi-regex": "^5.0.0",
+ "ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
"react-is": "^17.0.1"
},
export default class AutomaticTransactionGenerator {
public started: boolean;
+ private chargingStation: ChargingStation;
+ private connectorsStartStatus: Record<number, boolean>;
private startDate!: Date;
private lastRunDate!: Date;
private stopDate!: Date;
- private chargingStation: ChargingStation;
constructor(chargingStation: ChargingStation) {
this.chargingStation = chargingStation;
+ this.connectorsStartStatus = {} as Record<number, boolean>;
+ this.stopConnectors();
this.started = false;
}
this.stopDate = new Date(this.startDate.getTime()
+ (this.chargingStation.stationInfo?.AutomaticTransactionGenerator?.stopAfterHours ?? Constants.CHARGING_STATION_ATG_DEFAULT_STOP_AFTER_HOURS) * 3600 * 1000
- previousRunDuration);
+ this.startConnectors();
this.started = true;
- for (const connector in this.chargingStation.connectors) {
- if (Utils.convertToInt(connector) > 0) {
- // Avoid hogging the event loop with a busy loop
- setImmediate(() => {
- this.startOnConnector(Utils.convertToInt(connector)).catch(() => { /* This is intentional */ });
- });
- }
- }
logger.info(this.logPrefix() + ' started and will run for ' + Utils.formatDurationMilliSeconds(this.stopDate.getTime() - this.startDate.getTime()));
}
logger.error(`${this.logPrefix()} trying to stop while not started`);
return;
}
+ this.stopConnectors();
this.started = false;
logger.info(`${this.logPrefix()} over and lasted for ${Utils.formatDurationMilliSeconds(this.lastRunDate.getTime() - this.startDate.getTime())}. Stopping all transactions`);
}
- private async startOnConnector(connectorId: number): Promise<void> {
+ private startConnectors(): void {
+ for (const connector in this.chargingStation.connectors) {
+ const connectorId = Utils.convertToInt(connector);
+ if (connectorId > 0) {
+ // Avoid hogging the event loop with a busy loop
+ setImmediate(() => {
+ this.startConnector(connectorId).catch(() => { /* This is intentional */ });
+ });
+ }
+ }
+ }
+
+ private stopConnectors(): void {
+ for (const connector in this.chargingStation.connectors) {
+ const connectorId = Utils.convertToInt(connector);
+ if (connectorId > 0) {
+ this.stopConnector(connectorId);
+ }
+ }
+ }
+
+ private async startConnector(connectorId: number): Promise<void> {
logger.info(this.logPrefix(connectorId) + ' started on connector');
let skippedTransactions = 0;
let skippedTransactionsTotal = 0;
- while (this.started) {
+ this.connectorsStartStatus[connectorId] = true;
+ while (this.connectorsStartStatus[connectorId]) {
if ((new Date()) > this.stopDate) {
this.stop();
break;
await Utils.sleep(Constants.CHARGING_STATION_ATG_INITIALIZATION_TIME);
} while (!this.chargingStation?.ocppRequestService);
}
- const wait = Utils.getRandomInt(this.chargingStation.stationInfo.AutomaticTransactionGenerator.maxDelayBetweenTwoTransactions,
+ const wait = Utils.getRandomInteger(this.chargingStation.stationInfo.AutomaticTransactionGenerator.maxDelayBetweenTwoTransactions,
this.chargingStation.stationInfo.AutomaticTransactionGenerator.minDelayBetweenTwoTransactions) * 1000;
logger.info(this.logPrefix(connectorId) + ' waiting for ' + Utils.formatDurationMilliSeconds(wait));
await Utils.sleep(wait);
await Utils.sleep(Constants.CHARGING_STATION_ATG_WAIT_TIME);
} else {
// Wait until end of transaction
- const waitTrxEnd = Utils.getRandomInt(this.chargingStation.stationInfo.AutomaticTransactionGenerator.maxDuration,
+ const waitTrxEnd = Utils.getRandomInteger(this.chargingStation.stationInfo.AutomaticTransactionGenerator.maxDuration,
this.chargingStation.stationInfo.AutomaticTransactionGenerator.minDuration) * 1000;
logger.info(this.logPrefix(connectorId) + ' transaction ' + this.chargingStation.getConnector(connectorId).transactionId.toString() + ' will stop in ' + Utils.formatDurationMilliSeconds(waitTrxEnd));
await Utils.sleep(waitTrxEnd);
logger.info(this.logPrefix(connectorId) + ' stopped on connector');
}
+ private stopConnector(connectorId: number): void {
+ this.connectorsStartStatus[connectorId] = false;
+ }
+
private async startTransaction(connectorId: number): Promise<StartTransactionResponse | AuthorizeResponse> {
const measureId = 'StartTransaction with ATG';
const beginId = PerformanceStatistics.beginMeasure(measureId);