refactor: cleanup boot notification response assignation
[e-mobility-charging-stations-simulator.git] / src / charging-station / broadcast-channel / ChargingStationWorkerBroadcastChannel.ts
index 2407418601bacbbc4cc4bdf290c1f1477ed04a61..9b6621343a4afcfa36958f11c29bee35888cdbf3 100644 (file)
@@ -1,6 +1,6 @@
 import { secondsToMilliseconds } from 'date-fns'
+import { isEmpty } from 'rambda'
 
-import { WorkerBroadcastChannel } from './WorkerBroadcastChannel.js'
 import { BaseError, type OCPPError } from '../../exception/index.js'
 import {
   AuthorizationStatus,
@@ -37,10 +37,11 @@ import {
   type StopTransactionRequest,
   type StopTransactionResponse
 } from '../../types/index.js'
-import { Constants, convertToInt, isEmptyObject, logger } from '../../utils/index.js'
+import { Constants, convertToInt, isAsyncFunction, logger } from '../../utils/index.js'
 import type { ChargingStation } from '../ChargingStation.js'
 import { getConfigurationKey } from '../ConfigurationKeyUtils.js'
 import { buildMeterValue } from '../ocpp/index.js'
+import { WorkerBroadcastChannel } from './WorkerBroadcastChannel.js'
 
 const moduleName = 'ChargingStationWorkerBroadcastChannel'
 
@@ -56,7 +57,7 @@ type CommandResponse =
 type CommandHandler = (
   requestPayload?: BroadcastChannelRequestPayload
   // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
-) => Promise<CommandResponse | void> | void
+) => Promise<CommandResponse | void> | CommandResponse | void
 
 export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChannel {
   private readonly commandHandlers: Map<BroadcastChannelProcedureName, CommandHandler>
@@ -80,6 +81,12 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
           await this.chargingStation.stop()
         }
       ],
+      [
+        BroadcastChannelProcedureName.DELETE_CHARGING_STATIONS,
+        async (requestPayload?: BroadcastChannelRequestPayload) => {
+          await this.chargingStation.delete(requestPayload?.deleteConfiguration as boolean)
+        }
+      ],
       [
         BroadcastChannelProcedureName.OPEN_CONNECTION,
         () => {
@@ -129,8 +136,7 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
             RequestCommand.STOP_TRANSACTION,
             {
               meterStop: this.chargingStation.getEnergyActiveImportRegisterByTransactionId(
-                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-                requestPayload!.transactionId!,
+                requestPayload?.transactionId,
                 true
               ),
               ...requestPayload
@@ -149,22 +155,21 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
       [
         BroadcastChannelProcedureName.BOOT_NOTIFICATION,
         async (requestPayload?: BroadcastChannelRequestPayload) => {
-          this.chargingStation.bootNotificationResponse =
-            await this.chargingStation.ocppRequestService.requestHandler<
-            BootNotificationRequest,
-            BootNotificationResponse
-            >(
-              this.chargingStation,
-              RequestCommand.BOOT_NOTIFICATION,
-              {
-                ...this.chargingStation.bootNotificationRequest,
-                ...requestPayload
-              },
-              {
-                skipBufferingOnError: true,
-                throwError: true
-              }
-            )
+          await this.chargingStation.ocppRequestService.requestHandler<
+          BootNotificationRequest,
+          BootNotificationResponse
+          >(
+            this.chargingStation,
+            RequestCommand.BOOT_NOTIFICATION,
+            {
+              ...this.chargingStation.bootNotificationRequest,
+              ...requestPayload
+            },
+            {
+              skipBufferingOnError: true,
+              throwError: true
+            }
+          )
           return this.chargingStation.bootNotificationResponse
         }
       ],
@@ -174,12 +179,7 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
           await this.chargingStation.ocppRequestService.requestHandler<
           StatusNotificationRequest,
           StatusNotificationResponse
-          >(
-            this.chargingStation,
-            RequestCommand.STATUS_NOTIFICATION,
-            requestPayload,
-            requestParams
-          )
+          >(this.chargingStation, RequestCommand.STATUS_NOTIFICATION, requestPayload, requestParams)
       ],
       [
         BroadcastChannelProcedureName.HEARTBEAT,
@@ -262,7 +262,7 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
     this.onmessageerror = this.messageErrorHandler.bind(this) as (message: unknown) => void
   }
 
-  private async requestHandler (messageEvent: MessageEvent): Promise<void> {
+  private requestHandler (messageEvent: MessageEvent): void {
     const validatedMessageEvent = this.validateMessageEvent(messageEvent)
     if (validatedMessageEvent === false) {
       return
@@ -285,42 +285,40 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
       return
     }
     let responsePayload: BroadcastChannelResponsePayload | undefined
-    // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
-    let commandResponse: CommandResponse | void
-    try {
-      commandResponse = await this.commandHandler(command, requestPayload)
-      if (commandResponse == null || isEmptyObject(commandResponse)) {
+    this.commandHandler(command, requestPayload)
+      .then(commandResponse => {
+        if (commandResponse == null || isEmpty(commandResponse)) {
+          responsePayload = {
+            hashId: this.chargingStation.stationInfo?.hashId,
+            status: ResponseStatus.SUCCESS
+          }
+        } else {
+          responsePayload = this.commandResponseToResponsePayload(
+            command,
+            requestPayload,
+            commandResponse
+          )
+        }
+      })
+      .catch((error: unknown) => {
+        logger.error(
+          `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: Handle request error:`,
+          error
+        )
         responsePayload = {
           hashId: this.chargingStation.stationInfo?.hashId,
-          status: ResponseStatus.SUCCESS
-        }
-      } else {
-        responsePayload = this.commandResponseToResponsePayload(
+          status: ResponseStatus.FAILURE,
           command,
           requestPayload,
-          commandResponse
-        )
-      }
-    } catch (error) {
-      logger.error(
-        `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: Handle request error:`,
-        error
-      )
-      responsePayload = {
-        hashId: this.chargingStation.stationInfo?.hashId,
-        status: ResponseStatus.FAILURE,
-        command,
-        requestPayload,
+          errorMessage: (error as OCPPError).message,
+          errorStack: (error as OCPPError).stack,
+          errorDetails: (error as OCPPError).details
+        } satisfies BroadcastChannelResponsePayload
+      })
+      .finally(() => {
         // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        commandResponse: commandResponse!,
-        errorMessage: (error as OCPPError).message,
-        errorStack: (error as OCPPError).stack,
-        errorDetails: (error as OCPPError).details
-      }
-    } finally {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      this.sendResponse([uuid, responsePayload!])
-    }
+        this.sendResponse([uuid, responsePayload!])
+      })
   }
 
   private messageErrorHandler (messageEvent: MessageEvent): void {
@@ -338,7 +336,16 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
     if (this.commandHandlers.has(command)) {
       this.cleanRequestPayload(command, requestPayload)
       // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      return await this.commandHandlers.get(command)!(requestPayload)
+      const commandHandler = this.commandHandlers.get(command)!
+      if (isAsyncFunction(commandHandler)) {
+        return await commandHandler(requestPayload)
+      }
+      return (
+        commandHandler as (
+          requestPayload?: BroadcastChannelRequestPayload
+          // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
+        ) => CommandResponse | void
+      )(requestPayload)
     }
     throw new BaseError(`Unknown worker broadcast channel command: '${command}'`)
   }
@@ -407,7 +414,7 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
         return ResponseStatus.FAILURE
       case BroadcastChannelProcedureName.STATUS_NOTIFICATION:
       case BroadcastChannelProcedureName.METER_VALUES:
-        if (isEmptyObject(commandResponse)) {
+        if (isEmpty(commandResponse)) {
           return ResponseStatus.SUCCESS
         }
         return ResponseStatus.FAILURE