X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2Focpp%2FOCPPRequestService.ts;h=8eaeb833009be16deaeaece0da07609f84c65448;hb=9f2e313013116428f5bce2be59e2f5c07502c026;hp=363db74420a81f623ad7760cf0233c0f9daf1a30;hpb=6705f49075fbecc3bdaeaba40785f77db2563038;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ocpp/OCPPRequestService.ts b/src/charging-station/ocpp/OCPPRequestService.ts index 363db744..8eaeb833 100644 --- a/src/charging-station/ocpp/OCPPRequestService.ts +++ b/src/charging-station/ocpp/OCPPRequestService.ts @@ -4,34 +4,43 @@ import { DiagnosticsStatus, IncomingRequestCommand, RequestCommand, SendParams } import { BootNotificationResponse } from '../../types/ocpp/Responses'; import { ChargePointErrorCode } from '../../types/ocpp/ChargePointErrorCode'; import { ChargePointStatus } from '../../types/ocpp/ChargePointStatus'; -import ChargingStation from '../ChargingStation'; +import type ChargingStation from '../ChargingStation'; import Constants from '../../utils/Constants'; import { ErrorType } from '../../types/ocpp/ErrorType'; +import { JsonType } from '../../types/JsonType'; import { MessageType } from '../../types/ocpp/MessageType'; import { MeterValue } from '../../types/ocpp/MeterValues'; import OCPPError from '../../exception/OCPPError'; -import OCPPResponseService from './OCPPResponseService'; +import type OCPPResponseService from './OCPPResponseService'; import PerformanceStatistics from '../../performance/PerformanceStatistics'; import Utils from '../../utils/Utils'; import logger from '../../utils/Logger'; export default abstract class OCPPRequestService { - public chargingStation: ChargingStation; - protected ocppResponseService: OCPPResponseService; + private static readonly instances: Map = new Map(); + protected readonly chargingStation: ChargingStation; + private readonly ocppResponseService: OCPPResponseService; - constructor(chargingStation: ChargingStation, ocppResponseService: OCPPResponseService) { + protected constructor(chargingStation: ChargingStation, ocppResponseService: OCPPResponseService) { this.chargingStation = chargingStation; this.ocppResponseService = ocppResponseService; } - public async sendMessage(messageId: string, messageData: any, messageType: MessageType, commandName: RequestCommand | IncomingRequestCommand, + public static getInstance(this: new (chargingStation: ChargingStation, ocppResponseService: OCPPResponseService) => T, chargingStation: ChargingStation, ocppResponseService: OCPPResponseService): T { + if (!OCPPRequestService.instances.has(chargingStation.id)) { + OCPPRequestService.instances.set(chargingStation.id, new this(chargingStation, ocppResponseService)); + } + return OCPPRequestService.instances.get(chargingStation.id) as T; + } + + protected async sendMessage(messageId: string, messageData: JsonType | OCPPError, messageType: MessageType, commandName: RequestCommand | IncomingRequestCommand, params: SendParams = { skipBufferingOnError: false, triggerMessage: false - }): Promise { - if ((this.chargingStation.isInPendingState() && !params.triggerMessage) || this.chargingStation.isInRejectedState()) { - throw new OCPPError(ErrorType.SECURITY_ERROR, 'Cannot send command payload if the charging station is not in accepted state', commandName); - } else if (this.chargingStation.isInAcceptedState() || (this.chargingStation.isInPendingState() && params.triggerMessage)) { + }): Promise { + if ((this.chargingStation.isInUnknownState() && commandName === RequestCommand.BOOT_NOTIFICATION) + || (!this.chargingStation.getOcppStrictCompliance() && this.chargingStation.isInUnknownState()) + || this.chargingStation.isInAcceptedState() || (this.chargingStation.isInPendingState() && params.triggerMessage)) { // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; // Send a message through wsConnection @@ -50,7 +59,7 @@ export default abstract class OCPPRequestService { } else if (!params.skipBufferingOnError) { // Buffer it this.chargingStation.bufferMessage(messageToSend); - const ocppError = new OCPPError(ErrorType.GENERIC_ERROR, `WebSocket closed for buffered message id '${messageId}' with content '${messageToSend}'`, messageData?.details ?? {}); + const ocppError = new OCPPError(ErrorType.GENERIC_ERROR, `WebSocket closed for buffered message id '${messageId}' with content '${messageToSend}'`, commandName, messageData?.details as JsonType ?? {}); if (messageType === MessageType.CALL_MESSAGE) { // Reject it but keep the request in the cache return reject(ocppError); @@ -58,7 +67,7 @@ export default abstract class OCPPRequestService { return rejectCallback(ocppError, false); } else { // Reject it - return rejectCallback(new OCPPError(ErrorType.GENERIC_ERROR, `WebSocket closed for non buffered message id '${messageId}' with content '${messageToSend}'`, messageData?.details ?? {}), false); + return rejectCallback(new OCPPError(ErrorType.GENERIC_ERROR, `WebSocket closed for non buffered message id '${messageId}' with content '${messageToSend}'`, commandName, messageData?.details as JsonType ?? {}), false); } // Response? if (messageType !== MessageType.CALL_MESSAGE) { @@ -72,7 +81,7 @@ export default abstract class OCPPRequestService { * @param payload * @param requestPayload */ - async function responseCallback(payload: Record | string, requestPayload: Record): Promise { + async function responseCallback(payload: JsonType | string, requestPayload: JsonType): Promise { if (self.chargingStation.getEnableStatistics()) { self.chargingStation.performanceStatistics.addRequestStatistic(commandName, MessageType.CALL_RESULT_MESSAGE); } @@ -102,21 +111,20 @@ export default abstract class OCPPRequestService { self.chargingStation.requests.delete(messageId); reject(error); } - }), Constants.OCPP_WEBSOCKET_TIMEOUT, new OCPPError(ErrorType.GENERIC_ERROR, `Timeout for message id '${messageId}'`, messageData?.details ?? {}), () => { + }), Constants.OCPP_WEBSOCKET_TIMEOUT, new OCPPError(ErrorType.GENERIC_ERROR, `Timeout for message id '${messageId}'`, commandName, messageData?.details as JsonType ?? {}), () => { messageType === MessageType.CALL_MESSAGE && this.chargingStation.requests.delete(messageId); }); - } else { - throw new OCPPError(ErrorType.SECURITY_ERROR, 'Cannot send command payload if the charging station is in unknown state', commandName); } + throw new OCPPError(ErrorType.SECURITY_ERROR, `Cannot send command ${commandName} payload when the charging station is in ${this.chargingStation.getRegistrationStatus()} state on the central server`, commandName); } protected handleRequestError(commandName: RequestCommand, error: Error): void { - logger.error(this.chargingStation.logPrefix() + ' Request command ' + commandName + ' error: %j', error); + logger.error(this.chargingStation.logPrefix() + ' Request command %s error: %j', commandName, error); throw error; } - private buildMessageToSend(messageId: string, messageData: Record, messageType: MessageType, commandName: RequestCommand | IncomingRequestCommand, - responseCallback: (payload: Record | string, requestPayload: Record) => Promise, + private buildMessageToSend(messageId: string, messageData: JsonType | OCPPError, messageType: MessageType, commandName: RequestCommand | IncomingRequestCommand, + responseCallback: (payload: JsonType | string, requestPayload: JsonType) => Promise, rejectCallback: (error: OCPPError, requestStatistic?: boolean) => void): string { let messageToSend: string; // Type of message @@ -151,6 +159,6 @@ export default abstract class OCPPRequestService { public abstract sendTransactionBeginMeterValues(connectorId: number, transactionId: number, beginMeterValue: MeterValue): Promise; public abstract sendTransactionEndMeterValues(connectorId: number, transactionId: number, endMeterValue: MeterValue): Promise; public abstract sendDiagnosticsStatusNotification(diagnosticsStatus: DiagnosticsStatus): Promise; - public abstract sendResult(messageId: string, resultMessageData: Record, commandName: RequestCommand | IncomingRequestCommand): Promise; - public abstract sendError(messageId: string, error: OCPPError, commandName: RequestCommand | IncomingRequestCommand): Promise; + public abstract sendResult(messageId: string, resultMessageData: JsonType, commandName: RequestCommand | IncomingRequestCommand): Promise; + public abstract sendError(messageId: string, error: OCPPError, commandName: RequestCommand | IncomingRequestCommand): Promise; }