From 3e888c6560f1a59e1d34f06d465e698305c90aea Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sat, 11 Nov 2023 20:05:06 +0100 Subject: [PATCH] fix: make ATG wait for CS/connector availability MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../AutomaticTransactionGenerator.ts | 52 +++++++++++++++---- src/charging-station/ChargingStation.ts | 14 +++-- src/charging-station/ocpp/OCPPServiceUtils.ts | 5 ++ src/types/ChargingStation.ts | 1 + src/utils/Constants.ts | 1 + 5 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/charging-station/AutomaticTransactionGenerator.ts b/src/charging-station/AutomaticTransactionGenerator.ts index f390d55f..ebfd8c19 100644 --- a/src/charging-station/AutomaticTransactionGenerator.ts +++ b/src/charging-station/AutomaticTransactionGenerator.ts @@ -189,20 +189,13 @@ export class AutomaticTransactionGenerator extends AsyncResource { )}`, ); while (this.connectorsStatus.get(connectorId)?.start === true) { + await this.waitChargingStationServiceInitialization(connectorId); + await this.waitChargingStationAvailable(connectorId); + await this.waitConnectorAvailable(connectorId); if (!this.canStartConnector(connectorId)) { this.stopConnector(connectorId); break; } - if (!this.chargingStation?.ocppRequestService) { - logger.info( - `${this.logPrefix( - connectorId, - )} transaction loop waiting for charging station service to be initialized`, - ); - do { - await sleep(Constants.CHARGING_STATION_ATG_INITIALIZATION_TIME); - } while (!this.chargingStation?.ocppRequestService); - } const wait = secondsToMilliseconds( getRandomInteger( this.chargingStation.getAutomaticTransactionGeneratorConfiguration() @@ -326,6 +319,45 @@ export class AutomaticTransactionGenerator extends AsyncResource { return true; } + private async waitChargingStationServiceInitialization(connectorId: number): Promise { + if (!this.chargingStation?.ocppRequestService) { + logger.info( + `${this.logPrefix( + connectorId, + )} transaction loop waiting for charging station service to be initialized`, + ); + do { + await sleep(Constants.CHARGING_STATION_ATG_INITIALIZATION_TIME); + } while (!this.chargingStation?.ocppRequestService); + } + } + + private async waitChargingStationAvailable(connectorId: number): Promise { + if (!this.chargingStation.isChargingStationAvailable()) { + logger.info( + `${this.logPrefix( + connectorId, + )} transaction loop waiting for charging station to be available`, + ); + do { + await sleep(Constants.CHARGING_STATION_ATG_AVAILABILITY_TIME); + } while (!this.chargingStation.isChargingStationAvailable()); + } + } + + private async waitConnectorAvailable(connectorId: number): Promise { + if (!this.chargingStation.isConnectorAvailable(connectorId)) { + logger.info( + `${this.logPrefix( + connectorId, + )} transaction loop waiting for connector ${connectorId} to be available`, + ); + do { + await sleep(Constants.CHARGING_STATION_ATG_AVAILABILITY_TIME); + } while (!this.chargingStation.isConnectorAvailable(connectorId)); + } + } + private initializeConnectorsStatus(): void { if (this.chargingStation.hasEvses) { for (const [evseId, evseStatus] of this.chargingStation.evses) { diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index cd1ec426..8cdde246 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -513,7 +513,7 @@ export class ChargingStation extends EventEmitter { public setSupervisionUrl(url: string): void { if ( - this.stationInfo?.supervisionUrlOcppConfiguration && + this.stationInfo?.supervisionUrlOcppConfiguration === true && isNotEmptyString(this.stationInfo?.supervisionUrlOcppKey) ) { setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey!, url); @@ -1192,7 +1192,7 @@ export class ChargingStation extends EventEmitter { } } - private handleUnsupportedVersion(version: OCPPVersion) { + private handleUnsupportedVersion(version: OCPPVersion | undefined) { const errorMsg = `Unsupported protocol version '${version}' configured in template file ${this.templateFile}`; logger.error(`${this.logPrefix()} ${errorMsg}`); throw new BaseError(errorMsg); @@ -1249,6 +1249,11 @@ export class ChargingStation extends EventEmitter { this.ocppConfiguration = this.getOcppConfiguration(); this.initializeOcppConfiguration(); this.initializeOcppServices(); + this.once(ChargingStationEvents.accepted, () => { + this.startMessageSequence().catch((error) => { + logger.error(`${this.logPrefix()} Error while starting the message sequence:`, error); + }); + }); if (this.stationInfo?.autoRegister === true) { this.bootNotificationResponse = { currentTime: new Date(), @@ -1763,7 +1768,6 @@ export class ChargingStation extends EventEmitter { this.emit(ChargingStationEvents.registered); if (this.inAcceptedState() === true) { this.emit(ChargingStationEvents.accepted); - await this.startMessageSequence(); } } else { logger.error( @@ -2152,12 +2156,12 @@ export class ChargingStation extends EventEmitter { this.stopWebSocketPing(); // Stop heartbeat this.stopHeartbeat(); - // Stop ongoing transactions - stopTransactions && (await this.stopRunningTransactions(reason)); // Stop the ATG if (this.automaticTransactionGenerator?.started === true) { this.stopAutomaticTransactionGenerator(); } + // Stop ongoing transactions + stopTransactions && (await this.stopRunningTransactions(reason)); if (this.hasEvses) { for (const [evseId, evseStatus] of this.evses) { if (evseId > 0) { diff --git a/src/charging-station/ocpp/OCPPServiceUtils.ts b/src/charging-station/ocpp/OCPPServiceUtils.ts index ee4134bb..7da384d3 100644 --- a/src/charging-station/ocpp/OCPPServiceUtils.ts +++ b/src/charging-station/ocpp/OCPPServiceUtils.ts @@ -15,6 +15,7 @@ import { type AuthorizeRequest, type AuthorizeResponse, ChargePointErrorCode, + ChargingStationEvents, type ConnectorStatus, type ConnectorStatusEnum, ErrorType, @@ -226,6 +227,10 @@ export class OCPPServiceUtils { ); } chargingStation.getConnectorStatus(connectorId)!.status = status; + chargingStation.emit(ChargingStationEvents.connectorStatusChanged, { + connectorId, + ...chargingStation.getConnectorStatus(connectorId), + }); } public static async isIdTagAuthorized( diff --git a/src/types/ChargingStation.ts b/src/types/ChargingStation.ts index cdd3a5e0..f7980b47 100644 --- a/src/types/ChargingStation.ts +++ b/src/types/ChargingStation.ts @@ -4,4 +4,5 @@ export enum ChargingStationEvents { registered = 'registered', accepted = 'accepted', updated = 'updated', + connectorStatusChanged = 'connectorStatusChanged', } diff --git a/src/utils/Constants.ts b/src/utils/Constants.ts index 93c5bd9f..2a184016 100644 --- a/src/utils/Constants.ts +++ b/src/utils/Constants.ts @@ -6,6 +6,7 @@ export class Constants { static readonly DEFAULT_METER_VALUES_INTERVAL = 60000; // Ms static readonly CHARGING_STATION_DEFAULT_RESET_TIME = 60000; // Ms + static readonly CHARGING_STATION_ATG_AVAILABILITY_TIME = 1000; // Ms static readonly CHARGING_STATION_ATG_INITIALIZATION_TIME = 1000; // Ms static readonly DEFAULT_ATG_CONFIGURATION: AutomaticTransactionGeneratorConfiguration = -- 2.34.1