Fix Json type definition naming
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPRequestService.ts
index 41e7a6eaa5c6f9d4581c6b2f915ab207ccb86570..c19944bace4de2a511e2e8303a258cc51c134633 100644 (file)
@@ -1,28 +1,19 @@
+import { ErrorResponse, Response } from '../../types/ocpp/Responses';
 import {
-  AuthorizeResponse,
-  StartTransactionResponse,
-  StopTransactionReason,
-  StopTransactionResponse,
-} from '../../types/ocpp/Transaction';
-import {
-  DiagnosticsStatus,
   IncomingRequestCommand,
+  OutgoingRequest,
   RequestCommand,
+  RequestParams,
   ResponseType,
-  SendParams,
 } from '../../types/ocpp/Requests';
 
-import { BootNotificationResponse } from '../../types/ocpp/Responses';
-import { ChargePointErrorCode } from '../../types/ocpp/ChargePointErrorCode';
-import { ChargePointStatus } from '../../types/ocpp/ChargePointStatus';
 import type ChargingStation from '../ChargingStation';
 import Constants from '../../utils/Constants';
 import { EmptyObject } from '../../types/EmptyObject';
 import { ErrorType } from '../../types/ocpp/ErrorType';
 import { HandleErrorParams } from '../../types/Error';
-import { JsonType } from '../../types/JsonType';
+import { JsonObject } from '../../types/JsonType';
 import { MessageType } from '../../types/ocpp/MessageType';
-import { MeterValue } from '../../types/ocpp/MeterValues';
 import OCPPError from '../../exception/OCPPError';
 import type OCPPResponseService from './OCPPResponseService';
 import PerformanceStatistics from '../../performance/PerformanceStatistics';
@@ -44,7 +35,9 @@ export default abstract class OCPPRequestService {
   ) {
     this.chargingStation = chargingStation;
     this.ocppResponseService = ocppResponseService;
-    this.sendMessageHandler.bind(this);
+    this.requestHandler.bind(this);
+    this.sendResponse.bind(this);
+    this.sendError.bind(this);
   }
 
   public static getInstance<T extends OCPPRequestService>(
@@ -52,22 +45,22 @@ export default abstract class OCPPRequestService {
     chargingStation: ChargingStation,
     ocppResponseService: OCPPResponseService
   ): T {
-    if (!OCPPRequestService.instances.has(chargingStation.id)) {
+    if (!OCPPRequestService.instances.has(chargingStation.hashId)) {
       OCPPRequestService.instances.set(
-        chargingStation.id,
+        chargingStation.hashId,
         new this(chargingStation, ocppResponseService)
       );
     }
-    return OCPPRequestService.instances.get(chargingStation.id) as T;
+    return OCPPRequestService.instances.get(chargingStation.hashId) as T;
   }
 
-  public async sendResult(
+  public async sendResponse(
     messageId: string,
-    messagePayload: JsonType,
+    messagePayload: JsonObject,
     commandName: IncomingRequestCommand
   ): Promise<ResponseType> {
     try {
-      // Send result message
+      // Send response message
       return await this.internalSendMessage(
         messageId,
         messagePayload,
@@ -82,7 +75,7 @@ export default abstract class OCPPRequestService {
   public async sendError(
     messageId: string,
     ocppError: OCPPError,
-    commandName: IncomingRequestCommand
+    commandName: RequestCommand | IncomingRequestCommand
   ): Promise<ResponseType> {
     try {
       // Send error message
@@ -99,9 +92,9 @@ export default abstract class OCPPRequestService {
 
   protected async sendMessage(
     messageId: string,
-    messagePayload: JsonType,
+    messagePayload: JsonObject,
     commandName: RequestCommand,
-    params: SendParams = {
+    params: RequestParams = {
       skipBufferingOnError: false,
       triggerMessage: false,
     }
@@ -121,10 +114,10 @@ export default abstract class OCPPRequestService {
 
   private async internalSendMessage(
     messageId: string,
-    messagePayload: JsonType | OCPPError,
+    messagePayload: JsonObject | OCPPError,
     messageType: MessageType,
     commandName?: RequestCommand | IncomingRequestCommand,
-    params: SendParams = {
+    params: RequestParams = {
       skipBufferingOnError: false,
       triggerMessage: false,
     }
@@ -135,7 +128,8 @@ export default abstract class OCPPRequestService {
       (!this.chargingStation.getOcppStrictCompliance() &&
         this.chargingStation.isInUnknownState()) ||
       this.chargingStation.isInAcceptedState() ||
-      (this.chargingStation.isInPendingState() && params.triggerMessage)
+      (this.chargingStation.isInPendingState() &&
+        (params.triggerMessage || messageType === MessageType.CALL_RESULT_MESSAGE))
     ) {
       // eslint-disable-next-line @typescript-eslint/no-this-alias
       const self = this;
@@ -148,7 +142,7 @@ export default abstract class OCPPRequestService {
             messageType,
             commandName,
             responseCallback,
-            rejectCallback
+            errorCallback
           );
           if (this.chargingStation.getEnableStatistics()) {
             this.chargingStation.performanceStatistics.addRequestStatistic(
@@ -163,6 +157,11 @@ export default abstract class OCPPRequestService {
             // FIXME: Handle sending error
             this.chargingStation.wsConnection.send(messageToSend);
             PerformanceStatistics.endMeasure(commandName, beginId);
+            logger.debug(
+              `${this.chargingStation.logPrefix()} >> Command '${commandName}' sent ${this.getMessageTypeString(
+                messageType
+              )} payload: ${messageToSend}`
+            );
           } else if (!params.skipBufferingOnError) {
             // Buffer it
             this.chargingStation.bufferMessage(messageToSend);
@@ -170,21 +169,21 @@ export default abstract class OCPPRequestService {
               ErrorType.GENERIC_ERROR,
               `WebSocket closed for buffered message id '${messageId}' with content '${messageToSend}'`,
               commandName,
-              (messagePayload?.details as JsonType) ?? {}
+              (messagePayload?.details as JsonObject) ?? {}
             );
             if (messageType === MessageType.CALL_MESSAGE) {
               // Reject it but keep the request in the cache
               return reject(ocppError);
             }
-            return rejectCallback(ocppError, false);
+            return errorCallback(ocppError, false);
           } else {
             // Reject it
-            return rejectCallback(
+            return errorCallback(
               new OCPPError(
                 ErrorType.GENERIC_ERROR,
                 `WebSocket closed for non buffered message id '${messageId}' with content '${messageToSend}'`,
                 commandName,
-                (messagePayload?.details as JsonType) ?? {}
+                (messagePayload?.details as JsonObject) ?? {}
               ),
               false
             );
@@ -202,8 +201,8 @@ export default abstract class OCPPRequestService {
            * @param requestPayload
            */
           async function responseCallback(
-            payload: JsonType | string,
-            requestPayload: JsonType
+            payload: JsonObject,
+            requestPayload: JsonObject
           ): Promise<void> {
             if (self.chargingStation.getEnableStatistics()) {
               self.chargingStation.performanceStatistics.addRequestStatistic(
@@ -213,7 +212,7 @@ export default abstract class OCPPRequestService {
             }
             // Handle the request's response
             try {
-              await self.ocppResponseService.handleResponse(
+              await self.ocppResponseService.responseHandler(
                 commandName as RequestCommand,
                 payload,
                 requestPayload
@@ -221,7 +220,6 @@ export default abstract class OCPPRequestService {
               resolve(payload);
             } catch (error) {
               reject(error);
-              throw error;
             } finally {
               self.chargingStation.requests.delete(messageId);
             }
@@ -233,7 +231,7 @@ export default abstract class OCPPRequestService {
            * @param error
            * @param requestStatistic
            */
-          function rejectCallback(error: OCPPError, requestStatistic = true): void {
+          function errorCallback(error: OCPPError, requestStatistic = true): void {
             if (requestStatistic && self.chargingStation.getEnableStatistics()) {
               self.chargingStation.performanceStatistics.addRequestStatistic(
                 commandName,
@@ -255,7 +253,7 @@ export default abstract class OCPPRequestService {
           ErrorType.GENERIC_ERROR,
           `Timeout for message id '${messageId}'`,
           commandName,
-          (messagePayload?.details as JsonType) ?? {}
+          (messagePayload?.details as JsonObject) ?? {}
         ),
         () => {
           messageType === MessageType.CALL_MESSAGE &&
@@ -272,11 +270,11 @@ export default abstract class OCPPRequestService {
 
   private buildMessageToSend(
     messageId: string,
-    messagePayload: JsonType | OCPPError,
+    messagePayload: JsonObject | OCPPError,
     messageType: MessageType,
     commandName?: RequestCommand | IncomingRequestCommand,
-    responseCallback?: (payload: JsonType | string, requestPayload: JsonType) => Promise<void>,
-    rejectCallback?: (error: OCPPError, requestStatistic?: boolean) => void
+    responseCallback?: (payload: JsonObject, requestPayload: JsonObject) => Promise<void>,
+    errorCallback?: (error: OCPPError, requestStatistic?: boolean) => void
   ): string {
     let messageToSend: string;
     // Type of message
@@ -286,16 +284,21 @@ export default abstract class OCPPRequestService {
         // Build request
         this.chargingStation.requests.set(messageId, [
           responseCallback,
-          rejectCallback,
+          errorCallback,
           commandName,
-          messagePayload,
+          messagePayload as JsonObject,
         ]);
-        messageToSend = JSON.stringify([messageType, messageId, commandName, messagePayload]);
+        messageToSend = JSON.stringify([
+          messageType,
+          messageId,
+          commandName,
+          messagePayload,
+        ] as OutgoingRequest);
         break;
       // Response
       case MessageType.CALL_RESULT_MESSAGE:
         // Build response
-        messageToSend = JSON.stringify([messageType, messageId, messagePayload]);
+        messageToSend = JSON.stringify([messageType, messageId, messagePayload] as Response);
         break;
       // Error Message
       case MessageType.CALL_ERROR_MESSAGE:
@@ -303,15 +306,26 @@ export default abstract class OCPPRequestService {
         messageToSend = JSON.stringify([
           messageType,
           messageId,
-          messagePayload?.code ?? ErrorType.GENERIC_ERROR,
-          messagePayload?.message ?? '',
-          messagePayload?.details ?? { commandName },
-        ]);
+          (messagePayload as OCPPError)?.code ?? ErrorType.GENERIC_ERROR,
+          (messagePayload as OCPPError)?.message ?? '',
+          (messagePayload as OCPPError)?.details ?? { commandName },
+        ] as ErrorResponse);
         break;
     }
     return messageToSend;
   }
 
+  private getMessageTypeString(messageType: MessageType): string {
+    switch (messageType) {
+      case MessageType.CALL_MESSAGE:
+        return 'request';
+      case MessageType.CALL_RESULT_MESSAGE:
+        return 'response';
+      case MessageType.CALL_ERROR_MESSAGE:
+        return 'error';
+    }
+  }
+
   private handleRequestError(
     commandName: RequestCommand | IncomingRequestCommand,
     error: Error,
@@ -327,44 +341,10 @@ export default abstract class OCPPRequestService {
     }
   }
 
-  public abstract sendMessageHandler(
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
+  public abstract requestHandler<Request extends JsonObject, Response extends JsonObject>(
     commandName: RequestCommand,
-    commandParams?: JsonType,
-    params?: SendParams
-  ): Promise<ResponseType>;
-
-  public abstract sendAuthorize(connectorId: number, idTag?: string): Promise<AuthorizeResponse>;
-  public abstract sendStartTransaction(
-    connectorId: number,
-    idTag?: string
-  ): Promise<StartTransactionResponse>;
-
-  public abstract sendStopTransaction(
-    transactionId: number,
-    meterStop: number,
-    idTag?: string,
-    reason?: StopTransactionReason
-  ): Promise<StopTransactionResponse>;
-
-  public abstract sendMeterValues(
-    connectorId: number,
-    transactionId: number,
-    interval: number
-  ): Promise<void>;
-
-  public abstract sendTransactionBeginMeterValues(
-    connectorId: number,
-    transactionId: number,
-    beginMeterValue: MeterValue
-  ): Promise<void>;
-
-  public abstract sendTransactionEndMeterValues(
-    connectorId: number,
-    transactionId: number,
-    endMeterValue: MeterValue
-  ): Promise<void>;
-
-  public abstract sendDiagnosticsStatusNotification(
-    diagnosticsStatus: DiagnosticsStatus
-  ): Promise<void>;
+    commandParams?: JsonObject,
+    params?: RequestParams
+  ): Promise<Response>;
 }