refactor: add helper to test connector
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPRequestService.ts
index 4ef39b52ebec7e7e843a13b9b388bea1de8ec567..a50500dc24047f7a7eb3276a03d725cedf69fb44 100644 (file)
@@ -1,8 +1,8 @@
 import Ajv, { type JSONSchemaType } from 'ajv';
 import ajvFormats from 'ajv-formats';
 
-import type { OCPPResponseService } from './OCPPResponseService';
-import { OCPPServiceUtils } from './OCPPServiceUtils';
+import { OCPPConstants, type OCPPResponseService, OCPPServiceUtils } from './internal';
+import type { ChargingStation } from '../../charging-station';
 import { OCPPError } from '../../exception';
 import { PerformanceStatistics } from '../../performance';
 import {
@@ -23,10 +23,7 @@ import {
   type ResponseCallback,
   type ResponseType,
 } from '../../types';
-import { Constants } from '../../utils/Constants';
-import { logger } from '../../utils/Logger';
-import { Utils } from '../../utils/Utils';
-import type { ChargingStation } from '../ChargingStation';
+import { Constants, Utils, logger } from '../../utils';
 
 const moduleName = 'OCPPRequestService';
 
@@ -45,14 +42,63 @@ export abstract class OCPPRequestService {
     });
     ajvFormats(this.ajv);
     this.ocppResponseService = ocppResponseService;
-    this.requestHandler.bind(this);
-    this.sendMessage.bind(this);
-    this.sendResponse.bind(this);
-    this.sendError.bind(this);
-    this.internalSendMessage.bind(this);
-    this.buildMessageToSend.bind(this);
-    this.validateRequestPayload.bind(this);
-    this.validateIncomingRequestResponsePayload.bind(this);
+    this.requestHandler = this.requestHandler.bind(this) as <
+      ReqType extends JsonType,
+      ResType extends JsonType
+    >(
+      chargingStation: ChargingStation,
+      commandName: RequestCommand,
+      commandParams?: JsonType,
+      params?: RequestParams
+    ) => Promise<ResType>;
+    this.sendMessage = this.sendMessage.bind(this) as (
+      chargingStation: ChargingStation,
+      messageId: string,
+      messagePayload: JsonType,
+      commandName: RequestCommand,
+      params?: RequestParams
+    ) => Promise<ResponseType>;
+    this.sendResponse = this.sendResponse.bind(this) as (
+      chargingStation: ChargingStation,
+      messageId: string,
+      messagePayload: JsonType,
+      commandName: IncomingRequestCommand
+    ) => Promise<ResponseType>;
+    this.sendError = this.sendError.bind(this) as (
+      chargingStation: ChargingStation,
+      messageId: string,
+      ocppError: OCPPError,
+      commandName: RequestCommand | IncomingRequestCommand
+    ) => Promise<ResponseType>;
+    this.internalSendMessage = this.internalSendMessage.bind(this) as (
+      chargingStation: ChargingStation,
+      messageId: string,
+      messagePayload: JsonType | OCPPError,
+      messageType: MessageType,
+      commandName: RequestCommand | IncomingRequestCommand,
+      params?: RequestParams
+    ) => Promise<ResponseType>;
+    this.buildMessageToSend = this.buildMessageToSend.bind(this) as (
+      chargingStation: ChargingStation,
+      messageId: string,
+      messagePayload: JsonType | OCPPError,
+      messageType: MessageType,
+      commandName: RequestCommand | IncomingRequestCommand,
+      responseCallback: ResponseCallback,
+      errorCallback: ErrorCallback
+    ) => string;
+    this.validateRequestPayload = this.validateRequestPayload.bind(this) as <T extends JsonObject>(
+      chargingStation: ChargingStation,
+      commandName: RequestCommand | IncomingRequestCommand,
+      payload: T
+    ) => boolean;
+    this.validateIncomingRequestResponsePayload = this.validateIncomingRequestResponsePayload.bind(
+      this
+    ) as <T extends JsonObject>(
+      chargingStation: ChargingStation,
+      commandName: RequestCommand | IncomingRequestCommand,
+      payload: T
+    ) => boolean;
   }
 
   public static getInstance<T extends OCPPRequestService>(
@@ -233,6 +279,62 @@ export abstract class OCPPRequestService {
       // Send a message through wsConnection
       return Utils.promiseWithTimeout(
         new Promise((resolve, reject) => {
+          /**
+           * Function that will receive the request's response
+           *
+           * @param payload -
+           * @param requestPayload -
+           */
+          const responseCallback = (payload: JsonType, requestPayload: JsonType): void => {
+            if (chargingStation.getEnableStatistics() === true) {
+              chargingStation.performanceStatistics?.addRequestStatistic(
+                commandName,
+                MessageType.CALL_RESULT_MESSAGE
+              );
+            }
+            // Handle the request's response
+            self.ocppResponseService
+              .responseHandler(
+                chargingStation,
+                commandName as RequestCommand,
+                payload,
+                requestPayload
+              )
+              .then(() => {
+                resolve(payload);
+              })
+              .catch((error) => {
+                reject(error);
+              })
+              .finally(() => {
+                chargingStation.requests.delete(messageId);
+              });
+          };
+
+          /**
+           * Function that will receive the request's error response
+           *
+           * @param error -
+           * @param requestStatistic -
+           */
+          const errorCallback = (error: OCPPError, requestStatistic = true): void => {
+            if (requestStatistic === true && chargingStation.getEnableStatistics() === true) {
+              chargingStation.performanceStatistics?.addRequestStatistic(
+                commandName,
+                MessageType.CALL_ERROR_MESSAGE
+              );
+            }
+            logger.error(
+              `${chargingStation.logPrefix()} Error occurred at ${OCPPServiceUtils.getMessageTypeString(
+                messageType
+              )} command ${commandName} with PDU %j:`,
+              messagePayload,
+              error
+            );
+            chargingStation.requests.delete(messageId);
+            reject(error);
+          };
+
           if (chargingStation.getEnableStatistics() === true) {
             chargingStation.performanceStatistics?.addRequestStatistic(commandName, messageType);
           }
@@ -278,7 +380,7 @@ export abstract class OCPPRequestService {
                 ErrorType.GENERIC_ERROR,
                 `WebSocket closed or errored for buffered message id '${messageId}' with content '${messageToSend}'`,
                 commandName,
-                (messagePayload as JsonObject)?.details ?? {}
+                (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FREEZED_OBJECT
               )
             );
           } else if (wsClosedOrErrored) {
@@ -286,7 +388,7 @@ export abstract class OCPPRequestService {
               ErrorType.GENERIC_ERROR,
               `WebSocket closed or errored for non buffered message id '${messageId}' with content '${messageToSend}'`,
               commandName,
-              (messagePayload as JsonObject)?.details ?? {}
+              (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FREEZED_OBJECT
             );
             // Reject response
             if (messageType !== MessageType.CALL_MESSAGE) {
@@ -299,69 +401,13 @@ export abstract class OCPPRequestService {
           if (messageType !== MessageType.CALL_MESSAGE) {
             return resolve(messagePayload);
           }
-
-          /**
-           * Function that will receive the request's response
-           *
-           * @param payload -
-           * @param requestPayload -
-           */
-          function responseCallback(payload: JsonType, requestPayload: JsonType): void {
-            if (chargingStation.getEnableStatistics() === true) {
-              chargingStation.performanceStatistics?.addRequestStatistic(
-                commandName,
-                MessageType.CALL_RESULT_MESSAGE
-              );
-            }
-            // Handle the request's response
-            self.ocppResponseService
-              .responseHandler(
-                chargingStation,
-                commandName as RequestCommand,
-                payload,
-                requestPayload
-              )
-              .then(() => {
-                resolve(payload);
-              })
-              .catch((error) => {
-                reject(error);
-              })
-              .finally(() => {
-                chargingStation.requests.delete(messageId);
-              });
-          }
-
-          /**
-           * Function that will receive the request's error response
-           *
-           * @param error -
-           * @param requestStatistic -
-           */
-          function errorCallback(error: OCPPError, requestStatistic = true): void {
-            if (requestStatistic === true && chargingStation.getEnableStatistics() === true) {
-              chargingStation.performanceStatistics?.addRequestStatistic(
-                commandName,
-                MessageType.CALL_ERROR_MESSAGE
-              );
-            }
-            logger.error(
-              `${chargingStation.logPrefix()} Error occurred at ${OCPPServiceUtils.getMessageTypeString(
-                messageType
-              )} command ${commandName} with PDU %j:`,
-              messagePayload,
-              error
-            );
-            chargingStation.requests.delete(messageId);
-            reject(error);
-          }
         }),
-        Constants.OCPP_WEBSOCKET_TIMEOUT,
+        OCPPConstants.OCPP_WEBSOCKET_TIMEOUT,
         new OCPPError(
           ErrorType.GENERIC_ERROR,
           `Timeout for message id '${messageId}'`,
           commandName,
-          (messagePayload as JsonObject)?.details ?? {}
+          (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FREEZED_OBJECT
         ),
         () => {
           messageType === MessageType.CALL_MESSAGE && chargingStation.requests.delete(messageId);