1 import { AuthorizeResponse
, StartTransactionResponse
, StopTransactionReason
, StopTransactionResponse
} from
'../../types/ocpp/Transaction';
2 import { DiagnosticsStatus
, IncomingRequestCommand
, RequestCommand
} from
'../../types/ocpp/Requests';
4 import { BootNotificationResponse
} from
'../../types/ocpp/Responses';
5 import { ChargePointErrorCode
} from
'../../types/ocpp/ChargePointErrorCode';
6 import { ChargePointStatus
} from
'../../types/ocpp/ChargePointStatus';
7 import ChargingStation from
'../ChargingStation';
8 import Constants from
'../../utils/Constants';
9 import { ErrorType
} from
'../../types/ocpp/ErrorType';
10 import { MessageType
} from
'../../types/ocpp/MessageType';
11 import { MeterValue
} from
'../../types/ocpp/MeterValues';
12 import OCPPError from
'./OCPPError';
13 import OCPPResponseService from
'./OCPPResponseService';
14 import PerformanceStatistics from
'../../performance/PerformanceStatistics';
15 import logger from
'../../utils/Logger';
17 export default abstract class OCPPRequestService
{
18 public chargingStation
: ChargingStation
;
19 protected ocppResponseService
: OCPPResponseService
;
21 constructor(chargingStation
: ChargingStation
, ocppResponseService
: OCPPResponseService
) {
22 this.chargingStation
= chargingStation
;
23 this.ocppResponseService
= ocppResponseService
;
26 public async sendMessage(messageId
: string, commandParams
: any, messageType
: MessageType
, commandName
: RequestCommand
| IncomingRequestCommand
,
27 skipBufferingOnError
= false): Promise
<unknown
> {
28 // eslint-disable-next-line @typescript-eslint/no-this-alias
30 // Send a message through wsConnection
31 return new Promise((resolve
, reject
) => {
32 const messageToSend
= this.buildMessageToSend(messageId
, commandParams
, messageType
, commandName
, responseCallback
, rejectCallback
);
33 if (this.chargingStation
.getEnableStatistics()) {
34 this.chargingStation
.performanceStatistics
.addRequestStatistic(commandName
, messageType
);
36 // Check if wsConnection opened
37 if (this.chargingStation
.isWebSocketConnectionOpened()) {
39 const beginId
= PerformanceStatistics
.beginMeasure(commandName
);
40 // FIXME: Handle sending error
41 this.chargingStation
.wsConnection
.send(messageToSend
);
42 PerformanceStatistics
.endMeasure(commandName
, beginId
);
43 } else if (!skipBufferingOnError
) {
45 this.chargingStation
.addToMessageQueue(messageToSend
);
46 const ocppError
= new OCPPError(ErrorType
.GENERIC_ERROR
, `WebSocket closed for buffered message id '${messageId}' with content '${messageToSend}'`, commandParams
?.details
?? {});
47 if (messageType
=== MessageType
.CALL_MESSAGE
) {
48 // Reject it but keep the request in the cache
49 return reject(ocppError
);
51 return rejectCallback(ocppError
, false);
54 return rejectCallback(new OCPPError(ErrorType
.GENERIC_ERROR
, `WebSocket closed for non buffered message id '${messageId}' with content '${messageToSend}'`, commandParams
?.details
?? {}), false);
57 if (messageType
!== MessageType
.CALL_MESSAGE
) {
59 resolve(commandParams
);
62 setTimeout(() => rejectCallback(new OCPPError(ErrorType
.GENERIC_ERROR
, `Timeout for message id '${messageId}' with content '${messageToSend}'`, commandParams
?.details
?? {}), false), Constants
.OCPP_SOCKET_TIMEOUT
);
66 * Function that will receive the request's response
69 * @param requestPayload
71 async function responseCallback(payload
: Record
<string, unknown
> | string, requestPayload
: Record
<string, unknown
>): Promise
<void> {
72 if (self.chargingStation
.getEnableStatistics()) {
73 self.chargingStation
.performanceStatistics
.addRequestStatistic(commandName
, MessageType
.CALL_RESULT_MESSAGE
);
76 await self.ocppResponseService
.handleResponse(commandName
as RequestCommand
, payload
, requestPayload
);
77 self.chargingStation
.requests
.delete(messageId
);
82 * Function that will receive the request's error response
85 * @param requestStatistic
87 function rejectCallback(error
: OCPPError
, requestStatistic
= true): void {
88 if (requestStatistic
&& self.chargingStation
.getEnableStatistics()) {
89 self.chargingStation
.performanceStatistics
.addRequestStatistic(commandName
, MessageType
.CALL_ERROR_MESSAGE
);
91 logger
.error(`${self.chargingStation.logPrefix()} Error %j occurred when calling command %s with parameters %j`, error
, commandName
, commandParams
);
92 self.chargingStation
.requests
.delete(messageId
);
98 protected handleRequestError(commandName
: RequestCommand
, error
: Error): void {
99 logger
.error(this.chargingStation
.logPrefix() + ' Request command ' + commandName
+ ' error: %j', error
);
103 private buildMessageToSend(messageId
: string, commandParams
: Record
<string, unknown
>, messageType
: MessageType
, commandName
: RequestCommand
| IncomingRequestCommand
,
104 responseCallback
: (payload
: Record
<string, unknown
> | string, requestPayload
: Record
<string, unknown
>) => Promise
<void>, rejectCallback
: (error
: OCPPError
) => void): string {
105 let messageToSend
: string;
107 switch (messageType
) {
109 case MessageType
.CALL_MESSAGE
:
111 this.chargingStation
.requests
.set(messageId
, [responseCallback
, rejectCallback
, commandName
, commandParams
]);
112 messageToSend
= JSON
.stringify([messageType
, messageId
, commandName
, commandParams
]);
115 case MessageType
.CALL_RESULT_MESSAGE
:
117 messageToSend
= JSON
.stringify([messageType
, messageId
, commandParams
]);
120 case MessageType
.CALL_ERROR_MESSAGE
:
121 // Build Error Message
122 messageToSend
= JSON
.stringify([messageType
, messageId
, commandParams
?.code
?? ErrorType
.GENERIC_ERROR
, commandParams
?.message
?? '', commandParams
?.details
?? {}]);
125 return messageToSend
;
128 public abstract sendHeartbeat(): Promise
<void>;
129 public abstract sendBootNotification(chargePointModel
: string, chargePointVendor
: string, chargeBoxSerialNumber
?: string, firmwareVersion
?: string, chargePointSerialNumber
?: string, iccid
?: string, imsi
?: string, meterSerialNumber
?: string, meterType
?: string): Promise
<BootNotificationResponse
>;
130 public abstract sendStatusNotification(connectorId
: number, status: ChargePointStatus
, errorCode
?: ChargePointErrorCode
): Promise
<void>;
131 public abstract sendAuthorize(connectorId
: number, idTag
?: string): Promise
<AuthorizeResponse
>;
132 public abstract sendStartTransaction(connectorId
: number, idTag
?: string): Promise
<StartTransactionResponse
>;
133 public abstract sendStopTransaction(transactionId
: number, meterStop
: number, idTag
?: string, reason
?: StopTransactionReason
): Promise
<StopTransactionResponse
>;
134 public abstract sendMeterValues(connectorId
: number, transactionId
: number, interval
: number): Promise
<void>;
135 public abstract sendTransactionBeginMeterValues(connectorId
: number, transactionId
: number, beginMeterValue
: MeterValue
): Promise
<void>;
136 public abstract sendTransactionEndMeterValues(connectorId
: number, transactionId
: number, endMeterValue
: MeterValue
): Promise
<void>;
137 public abstract sendDiagnosticsStatusNotification(diagnosticsStatus
: DiagnosticsStatus
): Promise
<void>;
138 public abstract sendError(messageId
: string, error
: OCPPError
, commandName
: RequestCommand
| IncomingRequestCommand
): Promise
<unknown
>;