X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2FChargingStation.ts;h=028de5918c9f38cc7d9dd4281b589611d19b19a4;hb=9f2e313013116428f5bce2be59e2f5c07502c026;hp=99e8f5ee6aaf91b923c8da8d491e4ba383381e12;hpb=d18886407cdb8b8148c87492f2c953075e708401;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 99e8f5ee..028de591 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -42,6 +42,7 @@ import { parentPort } from 'worker_threads'; import path from 'path'; export default class ChargingStation { + public readonly id: string; public readonly stationTemplateFile: string; public authorizedTags: string[]; public stationInfo!: ChargingStationInfo; @@ -66,18 +67,16 @@ export default class ChargingStation { private webSocketPingSetInterval!: NodeJS.Timeout; constructor(index: number, stationTemplateFile: string) { + this.id = Utils.generateUUID(); this.index = index; this.stationTemplateFile = stationTemplateFile; - this.connectors = new Map(); - this.initialize(); - this.stopped = false; this.wsConnectionRestarted = false; this.autoReconnectRetryCount = 0; - + this.connectors = new Map(); this.requests = new Map(); this.messageBuffer = new Set(); - + this.initialize(); this.authorizedTags = this.getAuthorizedTags(); } @@ -123,6 +122,14 @@ export default class ChargingStation { return this?.wsConnection?.readyState === OPEN; } + public getRegistrationStatus(): RegistrationStatus { + return this?.bootNotificationResponse?.status; + } + + public isInUnknownState(): boolean { + return Utils.isNullOrUndefined(this?.bootNotificationResponse?.status); + } + public isInPendingState(): boolean { return this?.bootNotificationResponse?.status === RegistrationStatus.PENDING; } @@ -136,7 +143,7 @@ export default class ChargingStation { } public isRegistered(): boolean { - return this.isInAcceptedState() || this.isInPendingState(); + return !this.isInUnknownState() && (this.isInAcceptedState() || this.isInPendingState()); } public isChargingStationAvailable(): boolean { @@ -144,7 +151,7 @@ export default class ChargingStation { } public isConnectorAvailable(id: number): boolean { - return this.getConnectorStatus(id).availability === AvailabilityType.OPERATIVE; + return id > 0 && this.getConnectorStatus(id).availability === AvailabilityType.OPERATIVE; } public getNumberOfConnectors(): number { @@ -159,6 +166,10 @@ export default class ChargingStation { return this.stationInfo.currentOutType ?? CurrentType.AC; } + public getOcppStrictCompliance(): boolean { + return this.stationInfo.ocppStrictCompliance ?? false; + } + public getVoltageOut(): number | undefined { const errMsg = `${this.logPrefix()} Unknown ${this.getCurrentOutType()} currentOutType in template file ${this.stationTemplateFile}, cannot define default voltage out`; let defaultVoltageOut: number; @@ -577,8 +588,8 @@ export default class ChargingStation { this.wsConfiguredConnectionUrl = new URL(this.getConfiguredSupervisionUrl().href + '/' + this.stationInfo.chargingStationId); switch (this.getOcppVersion()) { case OCPPVersion.VERSION_16: - this.ocppIncomingRequestService = new OCPP16IncomingRequestService(this); - this.ocppRequestService = new OCPP16RequestService(this, new OCPP16ResponseService(this)); + this.ocppIncomingRequestService = OCPP16IncomingRequestService.getInstance(this); + this.ocppRequestService = OCPP16RequestService.getInstance(this, OCPP16ResponseService.getInstance(this)); break; default: this.handleUnsupportedVersion(this.getOcppVersion()); @@ -595,7 +606,7 @@ export default class ChargingStation { } this.stationInfo.powerDivider = this.getPowerDivider(); if (this.getEnableStatistics()) { - this.performanceStatistics = new PerformanceStatistics(this.stationInfo.chargingStationId, this.wsConnectionUrl); + this.performanceStatistics = PerformanceStatistics.getInstance(this.id, this.stationInfo.chargingStationId, this.wsConnectionUrl); } } @@ -641,21 +652,17 @@ export default class ChargingStation { private async onOpen(): Promise { logger.info(`${this.logPrefix()} Connected to OCPP server through ${this.wsConnectionUrl.toString()}`); - if (!this.isRegistered()) { + if (!this.isInAcceptedState()) { // Send BootNotification let registrationRetryCount = 0; do { this.bootNotificationResponse = await this.ocppRequestService.sendBootNotification(this.bootNotificationRequest.chargePointModel, this.bootNotificationRequest.chargePointVendor, this.bootNotificationRequest.chargeBoxSerialNumber, this.bootNotificationRequest.firmwareVersion); - if (!this.isRegistered()) { - registrationRetryCount++; + if (!this.isInAcceptedState()) { + this.getRegistrationMaxRetries() !== -1 && registrationRetryCount++; await Utils.sleep(this.bootNotificationResponse?.interval ? this.bootNotificationResponse.interval * 1000 : Constants.OCPP_DEFAULT_BOOT_NOTIFICATION_INTERVAL); } - } while (!this.isRegistered() && (registrationRetryCount <= this.getRegistrationMaxRetries() || this.getRegistrationMaxRetries() === -1)); - } - if (this.isRegistered() && this.stationInfo.autoRegister) { - await this.ocppRequestService.sendBootNotification(this.bootNotificationRequest.chargePointModel, - this.bootNotificationRequest.chargePointVendor, this.bootNotificationRequest.chargeBoxSerialNumber, this.bootNotificationRequest.firmwareVersion); + } while (!this.isInAcceptedState() && (registrationRetryCount <= this.getRegistrationMaxRetries() || this.getRegistrationMaxRetries() === -1)); } if (this.isInAcceptedState()) { await this.startMessageSequence(); @@ -663,16 +670,6 @@ export default class ChargingStation { if (this.wsConnectionRestarted && this.isWebSocketConnectionOpened()) { this.flushMessageBuffer(); } - } else if (this.isInPendingState()) { - // The central server shall issue a TriggerMessage to the charging station for the boot notification at the end of its configuration process - while (!this.isInAcceptedState()) { - await Utils.sleep(Constants.CHARGING_STATION_DEFAULT_START_SEQUENCE_DELAY); - } - await this.startMessageSequence(); - this.stopped && (this.stopped = false); - if (this.wsConnectionRestarted && this.isWebSocketConnectionOpened()) { - this.flushMessageBuffer(); - } } else { logger.error(`${this.logPrefix()} Registration failure: max retries reached (${this.getRegistrationMaxRetries()}) or retry disabled (${this.getRegistrationMaxRetries()})`); } @@ -876,6 +873,10 @@ export default class ChargingStation { } private async startMessageSequence(): Promise { + if (this.stationInfo.autoRegister) { + await this.ocppRequestService.sendBootNotification(this.bootNotificationRequest.chargePointModel, + this.bootNotificationRequest.chargePointVendor, this.bootNotificationRequest.chargeBoxSerialNumber, this.bootNotificationRequest.firmwareVersion); + } // Start WebSocket ping this.startWebSocketPing(); // Start heartbeat @@ -923,8 +924,7 @@ export default class ChargingStation { this.stopHeartbeat(); // Stop the ATG if (this.stationInfo.AutomaticTransactionGenerator.enable && - this.automaticTransactionGenerator && - this.automaticTransactionGenerator.started) { + this.automaticTransactionGenerator?.started) { this.automaticTransactionGenerator.stop(); } else { for (const connectorId of this.connectors.keys()) { @@ -1115,8 +1115,7 @@ export default class ChargingStation { // Stop the ATG if needed if (this.stationInfo.AutomaticTransactionGenerator.enable && this.stationInfo.AutomaticTransactionGenerator.stopOnConnectionFailure && - this.automaticTransactionGenerator && - this.automaticTransactionGenerator.started) { + this.automaticTransactionGenerator?.started) { this.automaticTransactionGenerator.stop(); } if (this.autoReconnectRetryCount < this.getAutoReconnectMaxRetries() || this.getAutoReconnectMaxRetries() === -1) {