X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2FChargingStation.ts;h=e217991ac8aad3c7c4256010687929df0f0162a3;hb=b3e297931b16fbd02794e62bdea7077419e07097;hp=def985c0447a4a6df065b32a8af94281d337c6e8;hpb=4c6f35659fb67d395adc035ef80c566eb6eef79e;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index def985c0..e217991a 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -120,8 +120,9 @@ import { createSerialNumber, getAmperageLimitationUnitDivider, getBootConnectorStatus, - getChargingStationConnectorChargingProfilesPowerLimit, + getChargingStationChargingProfilesLimit, getChargingStationId, + getConnectorChargingProfilesLimit, getDefaultVoltageOut, getHashId, getIdTagsFile, @@ -131,6 +132,7 @@ import { hasFeatureProfile, hasReservationExpired, initializeConnectorsMapStatus, + prepareConnectorStatus, propagateSerialNumber, setChargingStationOptions, stationTemplateToStationInfo, @@ -181,7 +183,6 @@ export class ChargingStation extends EventEmitter { private ocppIncomingRequestService!: OCPPIncomingRequestService private readonly messageBuffer: Set private configuredSupervisionUrl!: URL - private wsConnectionRetried: boolean private wsConnectionRetryCount: number private templateFileWatcher?: FSWatcher private templateFileHash!: string @@ -196,7 +197,6 @@ export class ChargingStation extends EventEmitter { this.starting = false this.stopping = false this.wsConnection = null - this.wsConnectionRetried = false this.wsConnectionRetryCount = 0 this.index = index this.templateFile = templateFile @@ -225,16 +225,16 @@ export class ChargingStation extends EventEmitter { }) this.on(ChargingStationEvents.accepted, () => { this.startMessageSequence( - this.wsConnectionRetried + this.wsConnectionRetryCount > 0 ? true : this.getAutomaticTransactionGeneratorConfiguration()?.stopAbsoluteDuration ).catch((error: unknown) => { logger.error(`${this.logPrefix()} Error while starting the message sequence:`, error) }) - this.wsConnectionRetried = false + this.wsConnectionRetryCount = 0 }) this.on(ChargingStationEvents.rejected, () => { - this.wsConnectionRetried = false + this.wsConnectionRetryCount = 0 }) this.on(ChargingStationEvents.connected, () => { if (this.wsPingSetInterval == null) { @@ -392,14 +392,14 @@ export class ChargingStation extends EventEmitter { } public getConnectorMaximumAvailablePower (connectorId: number): number { - let connectorAmperageLimitationPowerLimit: number | undefined + let connectorAmperageLimitationLimit: number | undefined const amperageLimitation = this.getAmperageLimitation() if ( amperageLimitation != null && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion amperageLimitation < this.stationInfo!.maximumAmperage! ) { - connectorAmperageLimitationPowerLimit = + connectorAmperageLimitationLimit = (this.stationInfo?.currentOutType === CurrentType.AC ? ACElectricUtils.powerTotal( this.getNumberOfPhases(), @@ -415,20 +415,25 @@ export class ChargingStation extends EventEmitter { } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const connectorMaximumPower = this.stationInfo!.maximumPower! / this.powerDivider! - const connectorChargingProfilesPowerLimit = - getChargingStationConnectorChargingProfilesPowerLimit(this, connectorId) + const chargingStationChargingProfilesLimit = + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + getChargingStationChargingProfilesLimit(this)! / this.powerDivider! + const connectorChargingProfilesLimit = getConnectorChargingProfilesLimit(this, connectorId) return min( isNaN(connectorMaximumPower) ? Number.POSITIVE_INFINITY : connectorMaximumPower, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - isNaN(connectorAmperageLimitationPowerLimit!) + isNaN(connectorAmperageLimitationLimit!) ? Number.POSITIVE_INFINITY : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - connectorAmperageLimitationPowerLimit!, + connectorAmperageLimitationLimit!, + isNaN(chargingStationChargingProfilesLimit) + ? Number.POSITIVE_INFINITY + : chargingStationChargingProfilesLimit, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - isNaN(connectorChargingProfilesPowerLimit!) + isNaN(connectorChargingProfilesLimit!) ? Number.POSITIVE_INFINITY : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - connectorChargingProfilesPowerLimit! + connectorChargingProfilesLimit! ) } @@ -672,6 +677,11 @@ export class ChargingStation extends EventEmitter { } } + public restartMeterValues (connectorId: number, interval: number): void { + this.stopMeterValues(connectorId) + this.startMeterValues(connectorId, interval) + } + private add (): void { this.emit(ChargingStationEvents.added) } @@ -1474,7 +1484,10 @@ export class ChargingStation extends EventEmitter { private initializeConnectorsOrEvsesFromFile (configuration: ChargingStationConfiguration): void { if (configuration.connectorsStatus != null && configuration.evsesStatus == null) { for (const [connectorId, connectorStatus] of configuration.connectorsStatus.entries()) { - this.connectors.set(connectorId, clone(connectorStatus)) + this.connectors.set( + connectorId, + prepareConnectorStatus(clone(connectorStatus)) + ) } } else if (configuration.evsesStatus != null && configuration.connectorsStatus == null) { for (const [evseId, evseStatusConfiguration] of configuration.evsesStatus.entries()) { @@ -1486,7 +1499,7 @@ export class ChargingStation extends EventEmitter { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion evseStatusConfiguration.connectorsStatus!.map((connectorStatus, connectorId) => [ connectorId, - connectorStatus + prepareConnectorStatus(connectorStatus) ]) ) }) @@ -1839,20 +1852,16 @@ export class ChargingStation extends EventEmitter { if (!this.isRegistered()) { // Send BootNotification do { - // FIXME: duplicated assignment with the boot notification response handler - this.bootNotificationResponse = await this.ocppRequestService.requestHandler< + await this.ocppRequestService.requestHandler< BootNotificationRequest, BootNotificationResponse >(this, RequestCommand.BOOT_NOTIFICATION, this.bootNotificationRequest, { skipBufferingOnError: true }) - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (this.bootNotificationResponse?.currentTime != null) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.bootNotificationResponse.currentTime = convertToDate( - this.bootNotificationResponse.currentTime - )! - } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.bootNotificationResponse!.currentTime = convertToDate( + this.bootNotificationResponse?.currentTime + )! if (!this.isRegistered()) { this.stationInfo?.registrationMaxRetries !== -1 && ++registrationRetryCount await sleep( @@ -1876,7 +1885,6 @@ export class ChargingStation extends EventEmitter { })` ) } - this.wsConnectionRetryCount = 0 this.emit(ChargingStationEvents.updated) } else { logger.warn( @@ -1928,7 +1936,7 @@ export class ChargingStation extends EventEmitter { } throw new OCPPError( ErrorType.PROTOCOL_ERROR, - `Cached request for message id ${messageId} ${getMessageTypeString( + `Cached request for message id '${messageId}' ${getMessageTypeString( messageType )} is not an array`, undefined, @@ -1938,6 +1946,14 @@ export class ChargingStation extends EventEmitter { private async handleIncomingMessage (request: IncomingRequest): Promise { const [messageType, messageId, commandName, commandPayload] = request + if (this.requests.has(messageId)) { + throw new OCPPError( + ErrorType.SECURITY_ERROR, + `Received message with duplicate message id '${messageId}'`, + commandName, + commandPayload + ) + } if (this.stationInfo?.enableStatistics === true) { this.performanceStatistics?.addRequestStatistic(commandName, messageType) } @@ -1962,7 +1978,7 @@ export class ChargingStation extends EventEmitter { // Error throw new OCPPError( ErrorType.INTERNAL_ERROR, - `Response for unknown message id ${messageId}`, + `Response for unknown message id '${messageId}'`, undefined, commandPayload ) @@ -1987,7 +2003,7 @@ export class ChargingStation extends EventEmitter { // Error throw new OCPPError( ErrorType.INTERNAL_ERROR, - `Error response for unknown message id ${messageId}`, + `Error response for unknown message id '${messageId}'`, undefined, { errorType, errorMessage, errorDetails } ) @@ -2072,10 +2088,10 @@ export class ChargingStation extends EventEmitter { } if (!(error instanceof OCPPError)) { logger.warn( - `${this.logPrefix()} Error thrown at incoming OCPP command '${ + `${this.logPrefix()} Error thrown at incoming OCPP command ${ commandName ?? requestCommandName ?? Constants.UNKNOWN_OCPP_COMMAND // eslint-disable-next-line @typescript-eslint/no-base-to-string - }' message '${data.toString()}' handling is not an OCPPError:`, + } message '${data.toString()}' handling is not an OCPPError:`, error ) } @@ -2422,7 +2438,6 @@ export class ChargingStation extends EventEmitter { this.wsConnectionRetryCount < this.stationInfo!.autoReconnectMaxRetries! || this.stationInfo?.autoReconnectMaxRetries === -1 ) { - this.wsConnectionRetried = true ++this.wsConnectionRetryCount const reconnectDelay = this.stationInfo?.reconnectExponentialDelay === true