X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2FChargingStation.ts;h=c5b89152199f53373bc6680648545c7205edab83;hb=10d244c0aa14bb4839791eea27e1674d87ae4e20;hp=67cd9e9ceed581df5feb33a3374617a091d7198b;hpb=89b7a234c161f2c68b6a9499ff698488e1a35c6b;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 67cd9e9c..c5b89152 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -11,19 +11,19 @@ import WebSocket, { Data, RawData } from 'ws'; import BaseError from '../exception/BaseError'; import OCPPError from '../exception/OCPPError'; import PerformanceStatistics from '../performance/PerformanceStatistics'; -import { AutomaticTransactionGeneratorConfiguration } from '../types/AutomaticTransactionGenerator'; -import ChargingStationConfiguration from '../types/ChargingStationConfiguration'; -import ChargingStationInfo from '../types/ChargingStationInfo'; -import ChargingStationOcppConfiguration from '../types/ChargingStationOcppConfiguration'; +import type { AutomaticTransactionGeneratorConfiguration } from '../types/AutomaticTransactionGenerator'; +import type ChargingStationConfiguration from '../types/ChargingStationConfiguration'; +import type ChargingStationInfo from '../types/ChargingStationInfo'; +import type ChargingStationOcppConfiguration from '../types/ChargingStationOcppConfiguration'; import ChargingStationTemplate, { CurrentType, PowerUnits, WsOptions, } from '../types/ChargingStationTemplate'; import { SupervisionUrlDistribution } from '../types/ConfigurationData'; -import { ConnectorStatus } from '../types/ConnectorStatus'; +import type { ConnectorStatus } from '../types/ConnectorStatus'; import { FileType } from '../types/FileType'; -import { JsonType } from '../types/JsonType'; +import type { JsonType } from '../types/JsonType'; import { ChargePointErrorCode } from '../types/ocpp/ChargePointErrorCode'; import { ChargePointStatus } from '../types/ocpp/ChargePointStatus'; import { ChargingProfile, ChargingRateUnitType } from '../types/ocpp/ChargingProfile'; @@ -79,8 +79,8 @@ import OCPP16IncomingRequestService from './ocpp/1.6/OCPP16IncomingRequestServic import OCPP16RequestService from './ocpp/1.6/OCPP16RequestService'; import OCPP16ResponseService from './ocpp/1.6/OCPP16ResponseService'; import { OCPP16ServiceUtils } from './ocpp/1.6/OCPP16ServiceUtils'; -import OCPPIncomingRequestService from './ocpp/OCPPIncomingRequestService'; -import OCPPRequestService from './ocpp/OCPPRequestService'; +import type OCPPIncomingRequestService from './ocpp/OCPPIncomingRequestService'; +import type OCPPRequestService from './ocpp/OCPPRequestService'; import SharedLRUCache from './SharedLRUCache'; export default class ChargingStation { @@ -336,22 +336,22 @@ export default class ChargingStation { } } - public getEnergyActiveImportRegisterByTransactionId(transactionId: number): number | undefined { + public getEnergyActiveImportRegisterByTransactionId(transactionId: number): number { const transactionConnectorStatus = this.getConnectorStatus( this.getConnectorIdByTransactionId(transactionId) ); if (this.getMeteringPerTransaction()) { - return transactionConnectorStatus?.transactionEnergyActiveImportRegisterValue; + return transactionConnectorStatus?.transactionEnergyActiveImportRegisterValue ?? 0; } - return transactionConnectorStatus?.energyActiveImportRegisterValue; + return transactionConnectorStatus?.energyActiveImportRegisterValue ?? 0; } - public getEnergyActiveImportRegisterByConnectorId(connectorId: number): number | undefined { + public getEnergyActiveImportRegisterByConnectorId(connectorId: number): number { const connectorStatus = this.getConnectorStatus(connectorId); if (this.getMeteringPerTransaction()) { - return connectorStatus?.transactionEnergyActiveImportRegisterValue; + return connectorStatus?.transactionEnergyActiveImportRegisterValue ?? 0; } - return connectorStatus?.energyActiveImportRegisterValue; + return connectorStatus?.energyActiveImportRegisterValue ?? 0; } public getAuthorizeRemoteTxRequests(): boolean { @@ -550,8 +550,8 @@ export default class ChargingStation { this.templateFileWatcher.close(); this.sharedLRUCache.deleteChargingStationTemplate(this.stationInfo?.templateHash); this.bootNotificationResponse = null; - parentPort.postMessage(MessageChannelUtils.buildStoppedMessage(this)); this.stopped = true; + parentPort.postMessage(MessageChannelUtils.buildStoppedMessage(this)); } public async reset(reason?: StopTransactionReason): Promise { @@ -626,7 +626,7 @@ export default class ChargingStation { ); this.getConnectorStatus(connectorId).chargingProfiles = []; } - if (!Array.isArray(this.getConnectorStatus(connectorId).chargingProfiles)) { + if (Array.isArray(this.getConnectorStatus(connectorId).chargingProfiles) === false) { logger.error( `${this.logPrefix()} Trying to set a charging profile on connectorId ${connectorId} with an improper attribute type for the charging profiles array, applying proper type initialization` ); @@ -675,6 +675,74 @@ export default class ChargingStation { this.messageBuffer.add(message); } + public openWSConnection( + options: WsOptions = this.stationInfo?.wsOptions ?? {}, + params: { closeOpened?: boolean; terminateOpened?: boolean } = { + closeOpened: false, + terminateOpened: false, + } + ): void { + options.handshakeTimeout = options?.handshakeTimeout ?? this.getConnectionTimeout() * 1000; + params.closeOpened = params?.closeOpened ?? false; + params.terminateOpened = params?.terminateOpened ?? false; + if ( + !Utils.isNullOrUndefined(this.stationInfo.supervisionUser) && + !Utils.isNullOrUndefined(this.stationInfo.supervisionPassword) + ) { + options.auth = `${this.stationInfo.supervisionUser}:${this.stationInfo.supervisionPassword}`; + } + if (params?.closeOpened) { + this.closeWSConnection(); + } + if (params?.terminateOpened) { + this.terminateWSConnection(); + } + let protocol: string; + switch (this.getOcppVersion()) { + case OCPPVersion.VERSION_16: + protocol = 'ocpp' + OCPPVersion.VERSION_16; + break; + default: + this.handleUnsupportedVersion(this.getOcppVersion()); + break; + } + + logger.info( + this.logPrefix() + ' Open OCPP connection to URL ' + this.wsConnectionUrl.toString() + ); + + this.wsConnection = new WebSocket(this.wsConnectionUrl, protocol, options); + + // Handle WebSocket message + this.wsConnection.on( + 'message', + this.onMessage.bind(this) as (this: WebSocket, data: RawData, isBinary: boolean) => void + ); + // Handle WebSocket error + this.wsConnection.on( + 'error', + this.onError.bind(this) as (this: WebSocket, error: Error) => void + ); + // Handle WebSocket close + this.wsConnection.on( + 'close', + this.onClose.bind(this) as (this: WebSocket, code: number, reason: Buffer) => void + ); + // Handle WebSocket open + this.wsConnection.on('open', this.onOpen.bind(this) as (this: WebSocket) => void); + // Handle WebSocket ping + this.wsConnection.on('ping', this.onPing.bind(this) as (this: WebSocket, data: Buffer) => void); + // Handle WebSocket pong + this.wsConnection.on('pong', this.onPong.bind(this) as (this: WebSocket, data: Buffer) => void); + } + + public closeWSConnection(): void { + if (this.isWebSocketConnectionOpened()) { + this.wsConnection.close(); + this.wsConnection = null; + } + } + private flushMessageBuffer() { if (this.messageBuffer.size > 0) { this.messageBuffer.forEach((message) => { @@ -856,7 +924,7 @@ export default class ChargingStation { this.templateFile }`; logger.error(errMsg); - throw new Error(errMsg); + throw new BaseError(errMsg); } private initialize(): void { @@ -1351,7 +1419,7 @@ export default class ChargingStation { let errMsg: string; try { const request = JSON.parse(data.toString()) as IncomingRequest | Response | ErrorResponse; - if (Utils.isIterable(request)) { + if (Array.isArray(request) === true) { [messageType, messageId] = request; // Check the type of message switch (messageType) { @@ -1388,12 +1456,12 @@ export default class ChargingStation { } // Respond cachedRequest = this.requests.get(messageId); - if (Utils.isIterable(cachedRequest)) { + if (Array.isArray(cachedRequest) === true) { [responseCallback, , requestCommandName, requestPayload] = cachedRequest; } else { throw new OCPPError( ErrorType.PROTOCOL_ERROR, - `Cached request for message id ${messageId} response is not iterable`, + `Cached request for message id ${messageId} response is not an array`, null, cachedRequest as unknown as JsonType ); @@ -1418,12 +1486,12 @@ export default class ChargingStation { ); } cachedRequest = this.requests.get(messageId); - if (Utils.isIterable(cachedRequest)) { + if (Array.isArray(cachedRequest) === true) { [, errorCallback, requestCommandName] = cachedRequest; } else { throw new OCPPError( ErrorType.PROTOCOL_ERROR, - `Cached request for message id ${messageId} error response is not iterable`, + `Cached request for message id ${messageId} error response is not an array`, null, cachedRequest as unknown as JsonType ); @@ -1444,7 +1512,7 @@ export default class ChargingStation { } parentPort.postMessage(MessageChannelUtils.buildUpdatedMessage(this)); } else { - throw new OCPPError(ErrorType.PROTOCOL_ERROR, 'Incoming message is not iterable', null, { + throw new OCPPError(ErrorType.PROTOCOL_ERROR, 'Incoming message is not an array', null, { payload: request, }); } @@ -1868,74 +1936,6 @@ export default class ChargingStation { } } - private openWSConnection( - options: WsOptions = this.stationInfo?.wsOptions ?? {}, - params: { closeOpened?: boolean; terminateOpened?: boolean } = { - closeOpened: false, - terminateOpened: false, - } - ): void { - options.handshakeTimeout = options?.handshakeTimeout ?? this.getConnectionTimeout() * 1000; - params.closeOpened = params?.closeOpened ?? false; - params.terminateOpened = params?.terminateOpened ?? false; - if ( - !Utils.isNullOrUndefined(this.stationInfo.supervisionUser) && - !Utils.isNullOrUndefined(this.stationInfo.supervisionPassword) - ) { - options.auth = `${this.stationInfo.supervisionUser}:${this.stationInfo.supervisionPassword}`; - } - if (params?.closeOpened) { - this.closeWSConnection(); - } - if (params?.terminateOpened) { - this.terminateWSConnection(); - } - let protocol: string; - switch (this.getOcppVersion()) { - case OCPPVersion.VERSION_16: - protocol = 'ocpp' + OCPPVersion.VERSION_16; - break; - default: - this.handleUnsupportedVersion(this.getOcppVersion()); - break; - } - - logger.info( - this.logPrefix() + ' Open OCPP connection to URL ' + this.wsConnectionUrl.toString() - ); - - this.wsConnection = new WebSocket(this.wsConnectionUrl, protocol, options); - - // Handle WebSocket message - this.wsConnection.on( - 'message', - this.onMessage.bind(this) as (this: WebSocket, data: RawData, isBinary: boolean) => void - ); - // Handle WebSocket error - this.wsConnection.on( - 'error', - this.onError.bind(this) as (this: WebSocket, error: Error) => void - ); - // Handle WebSocket close - this.wsConnection.on( - 'close', - this.onClose.bind(this) as (this: WebSocket, code: number, reason: Buffer) => void - ); - // Handle WebSocket open - this.wsConnection.on('open', this.onOpen.bind(this) as (this: WebSocket) => void); - // Handle WebSocket ping - this.wsConnection.on('ping', this.onPing.bind(this) as (this: WebSocket, data: Buffer) => void); - // Handle WebSocket pong - this.wsConnection.on('pong', this.onPong.bind(this) as (this: WebSocket, data: Buffer) => void); - } - - private closeWSConnection(): void { - if (this.isWebSocketConnectionOpened()) { - this.wsConnection.close(); - this.wsConnection = null; - } - } - private terminateWSConnection(): void { if (this.isWebSocketConnectionOpened()) { this.wsConnection.terminate();