Permit to run code in async scope in the OCPP stack
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPRequestService.ts
index 6f4e47be04864463f34b6b89fa65bceae9cf614c..68338670aa1c4dd710ec1310568328e7d13dd198 100644 (file)
@@ -1,12 +1,12 @@
-import { JSONSchemaType } from 'ajv';
+import type { JSONSchemaType } from 'ajv';
 import Ajv from 'ajv-draft-04';
 import ajvFormats from 'ajv-formats';
 
 import OCPPError from '../../exception/OCPPError';
 import PerformanceStatistics from '../../performance/PerformanceStatistics';
-import { EmptyObject } from '../../types/EmptyObject';
-import { HandleErrorParams } from '../../types/Error';
-import { JsonObject, JsonType } from '../../types/JsonType';
+import type { EmptyObject } from '../../types/EmptyObject';
+import type { HandleErrorParams } from '../../types/Error';
+import type { JsonObject, JsonType } from '../../types/JsonType';
 import { ErrorType } from '../../types/ocpp/ErrorType';
 import { MessageType } from '../../types/ocpp/MessageType';
 import {
@@ -16,7 +16,7 @@ import {
   RequestParams,
   ResponseType,
 } from '../../types/ocpp/Requests';
-import { ErrorResponse, Response } from '../../types/ocpp/Responses';
+import type { ErrorResponse, Response } from '../../types/ocpp/Responses';
 import Constants from '../../utils/Constants';
 import logger from '../../utils/Logger';
 import Utils from '../../utils/Utils';
@@ -34,11 +34,15 @@ export default abstract class OCPPRequestService {
 
   protected constructor(ocppResponseService: OCPPResponseService) {
     this.ocppResponseService = ocppResponseService;
+    this.ajv = new Ajv();
+    ajvFormats(this.ajv);
     this.requestHandler.bind(this);
+    this.sendMessage.bind(this);
     this.sendResponse.bind(this);
     this.sendError.bind(this);
-    this.ajv = new Ajv();
-    ajvFormats(this.ajv);
+    this.internalSendMessage.bind(this);
+    this.buildMessageToSend.bind(this);
+    this.validateRequestPayload.bind(this);
   }
 
   public static getInstance<T extends OCPPRequestService>(
@@ -67,7 +71,9 @@ export default abstract class OCPPRequestService {
         commandName
       );
     } catch (error) {
-      this.handleRequestError(chargingStation, commandName, error as Error);
+      this.handleSendMessageError(chargingStation, commandName, error as Error, {
+        throwError: true,
+      });
     }
   }
 
@@ -87,7 +93,7 @@ export default abstract class OCPPRequestService {
         commandName
       );
     } catch (error) {
-      this.handleRequestError(chargingStation, commandName, error as Error);
+      this.handleSendMessageError(chargingStation, commandName, error as Error);
     }
   }
 
@@ -111,7 +117,7 @@ export default abstract class OCPPRequestService {
         params
       );
     } catch (error) {
-      this.handleRequestError(chargingStation, commandName, error as Error, { throwError: false });
+      this.handleSendMessageError(chargingStation, commandName, error as Error);
     }
   }
 
@@ -121,7 +127,7 @@ export default abstract class OCPPRequestService {
     schema: JSONSchemaType<T>,
     payload: T
   ): boolean {
-    if (!chargingStation.getPayloadSchemaValidation()) {
+    if (chargingStation.getPayloadSchemaValidation() === false) {
       return true;
     }
     const validate = this.ajv.compile(schema);
@@ -132,6 +138,7 @@ export default abstract class OCPPRequestService {
       `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: Request PDU is invalid: %j`,
       validate.errors
     );
+    // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
     throw new OCPPError(
       OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
       'Request PDU is invalid',
@@ -172,11 +179,11 @@ export default abstract class OCPPRequestService {
             responseCallback,
             errorCallback
           );
-          if (chargingStation.getEnableStatistics()) {
+          if (chargingStation.getEnableStatistics() === true) {
             chargingStation.performanceStatistics.addRequestStatistic(commandName, messageType);
           }
           // Check if wsConnection opened
-          if (chargingStation.isWebSocketConnectionOpened()) {
+          if (chargingStation.isWebSocketConnectionOpened() === true) {
             // Yes: Send Message
             const beginId = PerformanceStatistics.beginMeasure(commandName);
             // FIXME: Handle sending error
@@ -187,7 +194,7 @@ export default abstract class OCPPRequestService {
                 messageType
               )} payload: ${messageToSend}`
             );
-          } else if (!params.skipBufferingOnError) {
+          } else if (params.skipBufferingOnError === false) {
             // Buffer it
             chargingStation.bufferMessage(messageToSend);
             const ocppError = new OCPPError(
@@ -229,7 +236,7 @@ export default abstract class OCPPRequestService {
             payload: JsonType,
             requestPayload: JsonType
           ): Promise<void> {
-            if (chargingStation.getEnableStatistics()) {
+            if (chargingStation.getEnableStatistics() === true) {
               chargingStation.performanceStatistics.addRequestStatistic(
                 commandName,
                 MessageType.CALL_RESULT_MESSAGE
@@ -258,17 +265,17 @@ export default abstract class OCPPRequestService {
            * @param requestStatistic
            */
           function errorCallback(error: OCPPError, requestStatistic = true): void {
-            if (requestStatistic && chargingStation.getEnableStatistics()) {
+            if (requestStatistic === true && chargingStation.getEnableStatistics() === true) {
               chargingStation.performanceStatistics.addRequestStatistic(
                 commandName,
                 MessageType.CALL_ERROR_MESSAGE
               );
             }
             logger.error(
-              `${chargingStation.logPrefix()} Error %j occurred when calling command %s with message data %j`,
-              error,
-              commandName,
-              messagePayload
+              `${chargingStation.logPrefix()} Error occurred when calling command ${commandName} with message data ${JSON.stringify(
+                messagePayload
+              )}:`,
+              error
             );
             chargingStation.requests.delete(messageId);
             reject(error);
@@ -352,23 +359,23 @@ export default abstract class OCPPRequestService {
     }
   }
 
-  private handleRequestError(
+  private handleSendMessageError(
     chargingStation: ChargingStation,
     commandName: RequestCommand | IncomingRequestCommand,
     error: Error,
-    params: HandleErrorParams<EmptyObject> = { throwError: true }
+    params: HandleErrorParams<EmptyObject> = { throwError: false }
   ): void {
-    logger.error(chargingStation.logPrefix() + ' Request command %s error: %j', commandName, error);
-    if (params?.throwError) {
+    logger.error(`${chargingStation.logPrefix()} Request command '${commandName}' error:`, error);
+    if (params?.throwError === true) {
       throw error;
     }
   }
 
   // eslint-disable-next-line @typescript-eslint/no-unused-vars
-  public abstract requestHandler<Request extends JsonType, Response extends JsonType>(
+  public abstract requestHandler<RequestType extends JsonType, ResponseType extends JsonType>(
     chargingStation: ChargingStation,
     commandName: RequestCommand,
     commandParams?: JsonType,
     params?: RequestParams
-  ): Promise<Response>;
+  ): Promise<ResponseType>;
 }