fix: handle not found hashId in UI server
[e-mobility-charging-stations-simulator.git] / src / charging-station / ui-server / ui-services / AbstractUIService.ts
index 0caf003e17039b0ad11f5e6f059e2d95d34cc3e6..d7595c26db164589e1cfb807812fab72be7a3c0b 100644 (file)
@@ -19,34 +19,40 @@ import type { AbstractUIServer } from '../AbstractUIServer';
 const moduleName = 'AbstractUIService';
 
 export abstract class AbstractUIService {
-  protected static readonly ProcedureNameToBroadCastChannelProcedureNameMapping: Omit<
-    Record<ProcedureName, BroadcastChannelProcedureName>,
-    | ProcedureName.START_SIMULATOR
-    | ProcedureName.STOP_SIMULATOR
-    | ProcedureName.LIST_CHARGING_STATIONS
-  > = {
-    [ProcedureName.START_CHARGING_STATION]: BroadcastChannelProcedureName.START_CHARGING_STATION,
-    [ProcedureName.STOP_CHARGING_STATION]: BroadcastChannelProcedureName.STOP_CHARGING_STATION,
-    [ProcedureName.CLOSE_CONNECTION]: BroadcastChannelProcedureName.CLOSE_CONNECTION,
-    [ProcedureName.OPEN_CONNECTION]: BroadcastChannelProcedureName.OPEN_CONNECTION,
-    [ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR]:
+  protected static readonly ProcedureNameToBroadCastChannelProcedureNameMapping = new Map<
+    ProcedureName,
+    BroadcastChannelProcedureName
+  >([
+    [ProcedureName.START_CHARGING_STATION, BroadcastChannelProcedureName.START_CHARGING_STATION],
+    [ProcedureName.STOP_CHARGING_STATION, BroadcastChannelProcedureName.STOP_CHARGING_STATION],
+    [ProcedureName.CLOSE_CONNECTION, BroadcastChannelProcedureName.CLOSE_CONNECTION],
+    [ProcedureName.OPEN_CONNECTION, BroadcastChannelProcedureName.OPEN_CONNECTION],
+    [
+      ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
       BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
-    [ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR]:
+    ],
+    [
+      ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
       BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
-    [ProcedureName.SET_SUPERVISION_URL]: BroadcastChannelProcedureName.SET_SUPERVISION_URL,
-    [ProcedureName.START_TRANSACTION]: BroadcastChannelProcedureName.START_TRANSACTION,
-    [ProcedureName.STOP_TRANSACTION]: BroadcastChannelProcedureName.STOP_TRANSACTION,
-    [ProcedureName.AUTHORIZE]: BroadcastChannelProcedureName.AUTHORIZE,
-    [ProcedureName.BOOT_NOTIFICATION]: BroadcastChannelProcedureName.BOOT_NOTIFICATION,
-    [ProcedureName.STATUS_NOTIFICATION]: BroadcastChannelProcedureName.STATUS_NOTIFICATION,
-    [ProcedureName.HEARTBEAT]: BroadcastChannelProcedureName.HEARTBEAT,
-    [ProcedureName.METER_VALUES]: BroadcastChannelProcedureName.METER_VALUES,
-    [ProcedureName.DATA_TRANSFER]: BroadcastChannelProcedureName.DATA_TRANSFER,
-    [ProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION]:
+    ],
+    [ProcedureName.SET_SUPERVISION_URL, BroadcastChannelProcedureName.SET_SUPERVISION_URL],
+    [ProcedureName.START_TRANSACTION, BroadcastChannelProcedureName.START_TRANSACTION],
+    [ProcedureName.STOP_TRANSACTION, BroadcastChannelProcedureName.STOP_TRANSACTION],
+    [ProcedureName.AUTHORIZE, BroadcastChannelProcedureName.AUTHORIZE],
+    [ProcedureName.BOOT_NOTIFICATION, BroadcastChannelProcedureName.BOOT_NOTIFICATION],
+    [ProcedureName.STATUS_NOTIFICATION, BroadcastChannelProcedureName.STATUS_NOTIFICATION],
+    [ProcedureName.HEARTBEAT, BroadcastChannelProcedureName.HEARTBEAT],
+    [ProcedureName.METER_VALUES, BroadcastChannelProcedureName.METER_VALUES],
+    [ProcedureName.DATA_TRANSFER, BroadcastChannelProcedureName.DATA_TRANSFER],
+    [
+      ProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION,
       BroadcastChannelProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION,
-    [ProcedureName.FIRMWARE_STATUS_NOTIFICATION]:
+    ],
+    [
+      ProcedureName.FIRMWARE_STATUS_NOTIFICATION,
       BroadcastChannelProcedureName.FIRMWARE_STATUS_NOTIFICATION,
-  };
+    ],
+  ]);
 
   protected readonly requestHandlers: Map<ProcedureName, ProtocolRequestHandler>;
   private readonly version: ProtocolVersion;
@@ -78,7 +84,7 @@ export abstract class AbstractUIService {
         throw new BaseError(
           `${command} is not implemented to handle message payload ${JSON.stringify(
             requestPayload,
-            null,
+            undefined,
             2,
           )}`,
         );
@@ -99,8 +105,8 @@ export abstract class AbstractUIService {
         command,
         requestPayload,
         responsePayload,
-        errorMessage: (error as Error).message,
-        errorStack: (error as Error).stack,
+        errorMessage: (error as OCPPError).message,
+        errorStack: (error as OCPPError).stack,
         errorDetails: (error as OCPPError).details,
       };
     }
@@ -144,9 +150,7 @@ export abstract class AbstractUIService {
   ): void {
     this.sendBroadcastChannelRequest(
       uuid,
-      AbstractUIService.ProcedureNameToBroadCastChannelProcedureNameMapping[
-        procedureName
-      ] as BroadcastChannelProcedureName,
+      AbstractUIService.ProcedureNameToBroadCastChannelProcedureNameMapping.get(procedureName)!,
       payload,
     );
   }
@@ -158,18 +162,21 @@ export abstract class AbstractUIService {
   ): void {
     if (isNotEmptyArray(payload.hashIds)) {
       payload.hashIds = payload.hashIds
-        ?.filter((hashId) => !isNullOrUndefined(hashId))
         ?.map((hashId) => {
           if (this.uiServer.chargingStations.has(hashId) === true) {
             return hashId;
           }
-          logger.warn(
-            `${this.logPrefix(
-              moduleName,
-              'sendBroadcastChannelRequest',
-            )} Charging station with hashId '${hashId}' not found`,
-          );
-        }) as string[];
+          const msg = `${this.logPrefix(
+            moduleName,
+            'sendBroadcastChannelRequest',
+          )} Charging station with hashId '${hashId}' not found`;
+          if (payload.hashIds?.length === 1) {
+            throw new BaseError(msg);
+          } else {
+            logger.warn(msg);
+          }
+        })
+        ?.filter((hashId) => !isNullOrUndefined(hashId)) as string[];
     }
     const expectedNumberOfResponses = isNotEmptyArray(payload.hashIds)
       ? payload.hashIds!.length
@@ -189,7 +196,7 @@ export abstract class AbstractUIService {
     try {
       await Bootstrap.getInstance().start();
       return { status: ResponseStatus.SUCCESS };
-    } catch (error) {
+    } catch {
       return { status: ResponseStatus.FAILURE };
     }
   }
@@ -198,7 +205,7 @@ export abstract class AbstractUIService {
     try {
       await Bootstrap.getInstance().stop();
       return { status: ResponseStatus.SUCCESS };
-    } catch (error) {
+    } catch {
       return { status: ResponseStatus.FAILURE };
     }
   }