X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2FChargingStation.ts;h=7d633eb07b97940002922cbefae236dad8e3e39a;hb=4f317101dedf3e41deaa06cc04ef5beaf79af3bd;hp=89fffc3bffc03b3399837d211a9d8d31ea5411c3;hpb=a5e9befcd2d47dc74838776f7a9ee0fea6fef9c6;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 89fffc3b..7d633eb0 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -86,7 +86,7 @@ import SharedLRUCache from './SharedLRUCache'; export default class ChargingStation { public readonly templateFile: string; public stationInfo!: ChargingStationInfo; - public stopped: boolean; + public started: boolean; public authorizedTagsCache: AuthorizedTagsCache; public automaticTransactionGenerator!: AutomaticTransactionGenerator; public ocppConfiguration!: ChargingStationOcppConfiguration; @@ -122,7 +122,7 @@ export default class ChargingStation { this.sharedLRUCache = SharedLRUCache.getInstance(); this.authorizedTagsCache = AuthorizedTagsCache.getInstance(); this.chargingStationWorkerBroadcastChannel = new ChargingStationWorkerBroadcastChannel(this); - this.stopped = false; + this.started = false; this.wsConnectionRestarted = false; this.autoReconnectRetryCount = 0; @@ -233,7 +233,7 @@ export default class ChargingStation { return this.connectors.get(0) ? this.connectors.size - 1 : this.connectors.size; } - public getConnectorStatus(id: number): ConnectorStatus { + public getConnectorStatus(id: number): ConnectorStatus | undefined { return this.connectors.get(id); } @@ -425,13 +425,13 @@ export default class ChargingStation { ); return; } - if (!this.getConnectorStatus(connectorId)?.transactionStarted) { + if (this.getConnectorStatus(connectorId)?.transactionStarted === false) { logger.error( `${this.logPrefix()} Trying to start MeterValues on connector Id ${connectorId} with no transaction started` ); return; } else if ( - this.getConnectorStatus(connectorId)?.transactionStarted && + this.getConnectorStatus(connectorId)?.transactionStarted === true && !this.getConnectorStatus(connectorId)?.transactionId ) { logger.error( @@ -519,9 +519,7 @@ export default class ChargingStation { parentPort.postMessage(MessageChannelUtils.buildStartedMessage(this)); } - public async stop(reason: StopTransactionReason = StopTransactionReason.NONE): Promise { - // Stop message sequence - await this.stopMessageSequence(reason); + public async stop(): Promise { for (const connectorId of this.connectors.keys()) { if (connectorId > 0) { await this.ocppRequestService.requestHandler< @@ -543,12 +541,12 @@ export default class ChargingStation { this.templateFileWatcher.close(); this.sharedLRUCache.deleteChargingStationTemplate(this.stationInfo?.templateHash); this.bootNotificationResponse = null; - this.stopped = true; + this.started = false; parentPort.postMessage(MessageChannelUtils.buildStoppedMessage(this)); } - public async reset(reason?: StopTransactionReason): Promise { - await this.stop(reason); + public async reset(): Promise { + await this.stop(); await Utils.sleep(this.stationInfo.resetTime); this.initialize(); this.start(); @@ -596,7 +594,6 @@ export default class ChargingStation { ? limit : DCElectricUtils.power(this.getVoltageOut(), limit); } - const connectorMaximumPower = this.getMaximumPower() / this.powerDivider; if (limit > connectorMaximumPower) { logger.error( @@ -655,6 +652,7 @@ export default class ChargingStation { this.getConnectorStatus(connectorId).transactionEnergyActiveImportRegisterValue = 0; delete this.getConnectorStatus(connectorId).transactionBeginMeterValue; this.stopMeterValues(connectorId); + parentPort.postMessage(MessageChannelUtils.buildUpdatedMessage(this)); } public hasFeatureProfile(featureProfile: SupportedFeatureProfiles) { @@ -770,6 +768,62 @@ export default class ChargingStation { } } + public getNumberOfRunningTransactions(): number { + let trxCount = 0; + for (const connectorId of this.connectors.keys()) { + if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) { + trxCount++; + } + } + return trxCount; + } + + public async stopRunningTransactions(reason = StopTransactionReason.NONE): Promise { + for (const connectorId of this.connectors.keys()) { + if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) { + await this.stopTransactionOnConnector(connectorId, reason); + } + } + } + + public async stopTransactionOnConnector( + connectorId: number, + reason = StopTransactionReason.NONE + ): Promise { + const transactionId = this.getConnectorStatus(connectorId).transactionId; + if ( + this.getBeginEndMeterValues() && + this.getOcppStrictCompliance() && + !this.getOutOfOrderEndMeterValues() + ) { + // FIXME: Implement OCPP version agnostic helpers + const transactionEndMeterValue = OCPP16ServiceUtils.buildTransactionEndMeterValue( + this, + connectorId, + this.getEnergyActiveImportRegisterByTransactionId(transactionId) + ); + await this.ocppRequestService.requestHandler( + this, + RequestCommand.METER_VALUES, + { + connectorId, + transactionId, + meterValue: [transactionEndMeterValue], + } + ); + } + return this.ocppRequestService.requestHandler( + this, + RequestCommand.STOP_TRANSACTION, + { + transactionId, + meterStop: this.getEnergyActiveImportRegisterByTransactionId(transactionId, true), + idTag: this.getTransactionIdTag(transactionId), + reason, + } + ); + } + private flushMessageBuffer(): void { if (this.messageBuffer.size > 0) { this.messageBuffer.forEach((message) => { @@ -1233,7 +1287,7 @@ export default class ChargingStation { } // Initialize transaction attributes on connectors for (const connectorId of this.connectors.keys()) { - if (connectorId > 0 && !this.getConnectorStatus(connectorId)?.transactionStarted) { + if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === false) { this.initializeConnectorStatus(connectorId); } } @@ -1392,9 +1446,10 @@ export default class ChargingStation { `${this.logPrefix()} Registration failure: max retries reached (${this.getRegistrationMaxRetries()}) or retry disabled (${this.getRegistrationMaxRetries()})` ); } - this.stopped && (this.stopped = false); + this.started === false && (this.started = true); this.autoReconnectRetryCount = 0; this.wsConnectionRestarted = false; + parentPort.postMessage(MessageChannelUtils.buildUpdatedMessage(this)); } else { logger.warn( `${this.logPrefix()} Connection to OCPP server through ${this.wsConnectionUrl.toString()} failed` @@ -1408,22 +1463,24 @@ export default class ChargingStation { case WebSocketCloseEventStatusCode.CLOSE_NORMAL: case WebSocketCloseEventStatusCode.CLOSE_NO_STATUS: logger.info( - `${this.logPrefix()} WebSocket normally closed with status '${ChargingStationUtils.getWebSocketCloseEventStatusString( + `${this.logPrefix()} WebSocket normally closed with status '${Utils.getWebSocketCloseEventStatusString( code )}' and reason '${reason}'` ); this.autoReconnectRetryCount = 0; + await this.stopMessageSequence(StopTransactionReason.OTHER); break; // Abnormal close default: logger.error( - `${this.logPrefix()} WebSocket abnormally closed with status '${ChargingStationUtils.getWebSocketCloseEventStatusString( + `${this.logPrefix()} WebSocket abnormally closed with status '${Utils.getWebSocketCloseEventStatusString( code )}' and reason '${reason}'` ); await this.reconnect(code); break; } + parentPort.postMessage(MessageChannelUtils.buildUpdatedMessage(this)); } private async onMessage(data: Data): Promise { @@ -1606,16 +1663,6 @@ export default class ChargingStation { : true; } - private getNumberOfRunningTransactions(): number { - let trxCount = 0; - for (const connectorId of this.connectors.keys()) { - if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted) { - trxCount++; - } - } - return trxCount; - } - // 0 for disabling private getConnectionTimeout(): number | undefined { if ( @@ -1732,7 +1779,7 @@ export default class ChargingStation { if (connectorId === 0) { continue; } else if ( - !this.stopped && + this.started === true && !this.getConnectorStatus(connectorId)?.status && this.getConnectorStatus(connectorId)?.bootStatus ) { @@ -1748,7 +1795,7 @@ export default class ChargingStation { this.getConnectorStatus(connectorId).status = this.getConnectorStatus(connectorId).bootStatus; } else if ( - this.stopped && + this.started === false && this.getConnectorStatus(connectorId)?.status && this.getConnectorStatus(connectorId)?.bootStatus ) { @@ -1763,7 +1810,7 @@ export default class ChargingStation { }); this.getConnectorStatus(connectorId).status = this.getConnectorStatus(connectorId).bootStatus; - } else if (!this.stopped && this.getConnectorStatus(connectorId)?.status) { + } else if (this.started === true && this.getConnectorStatus(connectorId)?.status) { // Send previous status at template reload await this.ocppRequestService.requestHandler< StatusNotificationRequest, @@ -1804,41 +1851,7 @@ export default class ChargingStation { if (this.automaticTransactionGenerator?.started) { this.stopAutomaticTransactionGenerator(); } else { - for (const connectorId of this.connectors.keys()) { - if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted) { - const transactionId = this.getConnectorStatus(connectorId).transactionId; - if ( - this.getBeginEndMeterValues() && - this.getOcppStrictCompliance() && - !this.getOutOfOrderEndMeterValues() - ) { - // FIXME: Implement OCPP version agnostic helpers - const transactionEndMeterValue = OCPP16ServiceUtils.buildTransactionEndMeterValue( - this, - connectorId, - this.getEnergyActiveImportRegisterByTransactionId(transactionId) - ); - await this.ocppRequestService.requestHandler( - this, - RequestCommand.METER_VALUES, - { - connectorId, - transactionId, - meterValue: [transactionEndMeterValue], - } - ); - } - await this.ocppRequestService.requestHandler< - StopTransactionRequest, - StopTransactionResponse - >(this, RequestCommand.STOP_TRANSACTION, { - transactionId, - meterStop: this.getEnergyActiveImportRegisterByTransactionId(transactionId, true), - idTag: this.getTransactionIdTag(transactionId), - reason, - }); - } - } + await this.stopRunningTransactions(reason); } } } @@ -1984,7 +1997,7 @@ export default class ChargingStation { // Stop heartbeat this.stopHeartbeat(); // Stop the ATG if needed - if (this.automaticTransactionGenerator?.configuration?.stopOnConnectionFailure) { + if (this.automaticTransactionGenerator?.configuration?.stopOnConnectionFailure === true) { this.stopAutomaticTransactionGenerator(); } if ( @@ -2018,6 +2031,7 @@ export default class ChargingStation { ); this.wsConnectionRestarted = true; } else if (this.getAutoReconnectMaxRetries() !== -1) { + await this.stopMessageSequence(StopTransactionReason.OTHER); logger.error( `${this.logPrefix()} WebSocket reconnect failure: maximum retries reached (${ this.autoReconnectRetryCount