refactor: remove unneeded try {} catch {}
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16IncomingRequestService.ts
index 6937f2bde3fe335b40f01b5b651a0a5149d9fac1..2af366f9cfbd4ac6945dc6262352e8493a3c98eb 100644 (file)
@@ -1,10 +1,10 @@
-// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
+// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
 
 import { createWriteStream, readdirSync } from 'node:fs'
 import { dirname, join, resolve } from 'node:path'
 import { URL, fileURLToPath } from 'node:url'
 
-import type { JSONSchemaType } from 'ajv'
+import type { ValidateFunction } from 'ajv'
 import { Client, type FTPResponse } from 'basic-ftp'
 import {
   type Interval,
@@ -113,7 +113,8 @@ import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js'
 const moduleName = 'OCPP16IncomingRequestService'
 
 export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
-  protected jsonSchemas: Map<OCPP16IncomingRequestCommand, JSONSchemaType<JsonType>>
+  protected payloadValidateFunctions: Map<OCPP16IncomingRequestCommand, ValidateFunction<JsonType>>
+
   private readonly incomingRequestHandlers: Map<
   OCPP16IncomingRequestCommand,
   IncomingRequestHandler
@@ -194,149 +195,350 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         this.handleRequestCancelReservation.bind(this) as unknown as IncomingRequestHandler
       ]
     ])
-    this.jsonSchemas = new Map<OCPP16IncomingRequestCommand, JSONSchemaType<JsonType>>([
+    this.payloadValidateFunctions = new Map<
+    OCPP16IncomingRequestCommand,
+    ValidateFunction<JsonType>
+    >([
       [
         OCPP16IncomingRequestCommand.RESET,
-        OCPP16ServiceUtils.parseJsonSchemaFile<ResetRequest>(
-          'assets/json-schemas/ocpp/1.6/Reset.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<ResetRequest>(
+              'assets/json-schemas/ocpp/1.6/Reset.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.CLEAR_CACHE,
-        OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearCacheRequest>(
-          'assets/json-schemas/ocpp/1.6/ClearCache.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearCacheRequest>(
+              'assets/json-schemas/ocpp/1.6/ClearCache.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
-        OCPP16ServiceUtils.parseJsonSchemaFile<UnlockConnectorRequest>(
-          'assets/json-schemas/ocpp/1.6/UnlockConnector.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<UnlockConnectorRequest>(
+              'assets/json-schemas/ocpp/1.6/UnlockConnector.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.GET_CONFIGURATION,
-        OCPP16ServiceUtils.parseJsonSchemaFile<GetConfigurationRequest>(
-          'assets/json-schemas/ocpp/1.6/GetConfiguration.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<GetConfigurationRequest>(
+              'assets/json-schemas/ocpp/1.6/GetConfiguration.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
-        OCPP16ServiceUtils.parseJsonSchemaFile<ChangeConfigurationRequest>(
-          'assets/json-schemas/ocpp/1.6/ChangeConfiguration.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<ChangeConfigurationRequest>(
+              'assets/json-schemas/ocpp/1.6/ChangeConfiguration.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
-        OCPP16ServiceUtils.parseJsonSchemaFile<GetDiagnosticsRequest>(
-          'assets/json-schemas/ocpp/1.6/GetDiagnostics.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<GetDiagnosticsRequest>(
+              'assets/json-schemas/ocpp/1.6/GetDiagnostics.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
-        OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16GetCompositeScheduleRequest>(
-          'assets/json-schemas/ocpp/1.6/GetCompositeSchedule.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16GetCompositeScheduleRequest>(
+              'assets/json-schemas/ocpp/1.6/GetCompositeSchedule.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
-        OCPP16ServiceUtils.parseJsonSchemaFile<SetChargingProfileRequest>(
-          'assets/json-schemas/ocpp/1.6/SetChargingProfile.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<SetChargingProfileRequest>(
+              'assets/json-schemas/ocpp/1.6/SetChargingProfile.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
-        OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearChargingProfileRequest>(
-          'assets/json-schemas/ocpp/1.6/ClearChargingProfile.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearChargingProfileRequest>(
+              'assets/json-schemas/ocpp/1.6/ClearChargingProfile.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
-        OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ChangeAvailabilityRequest>(
-          'assets/json-schemas/ocpp/1.6/ChangeAvailability.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ChangeAvailabilityRequest>(
+              'assets/json-schemas/ocpp/1.6/ChangeAvailability.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
-        OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStartTransactionRequest>(
-          'assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStartTransactionRequest>(
+              'assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
-        OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStopTransactionRequest>(
-          'assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStopTransactionRequest>(
+              'assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
-        OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16TriggerMessageRequest>(
-          'assets/json-schemas/ocpp/1.6/TriggerMessage.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16TriggerMessageRequest>(
+              'assets/json-schemas/ocpp/1.6/TriggerMessage.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.DATA_TRANSFER,
-        OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
-          'assets/json-schemas/ocpp/1.6/DataTransfer.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
+              'assets/json-schemas/ocpp/1.6/DataTransfer.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
-        OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16UpdateFirmwareRequest>(
-          'assets/json-schemas/ocpp/1.6/UpdateFirmware.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16UpdateFirmwareRequest>(
+              'assets/json-schemas/ocpp/1.6/UpdateFirmware.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.RESERVE_NOW,
-        OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ReserveNowRequest>(
-          'assets/json-schemas/ocpp/1.6/ReserveNow.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ReserveNowRequest>(
+              'assets/json-schemas/ocpp/1.6/ReserveNow.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ],
       [
         OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
-        OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16CancelReservationRequest>(
-          'assets/json-schemas/ocpp/1.6/CancelReservation.json',
-          moduleName,
-          'constructor'
-        )
+        this.ajv
+          .compile(
+            OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16CancelReservationRequest>(
+              'assets/json-schemas/ocpp/1.6/CancelReservation.json',
+              moduleName,
+              'constructor'
+            )
+          )
+          .bind(this)
       ]
     ])
-    this.validatePayload = this.validatePayload.bind(this) as (
-      chargingStation: ChargingStation,
-      commandName: OCPP16IncomingRequestCommand,
-      commandPayload: JsonType
-    ) => boolean
+    this.on(
+      OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
+      (chargingStation: ChargingStation, connectorId: number, idTag: string) => {
+        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+        chargingStation.getConnectorStatus(connectorId)!.transactionRemoteStarted = true
+        chargingStation.ocppRequestService
+          .requestHandler<OCPP16StartTransactionRequest, OCPP16StartTransactionResponse>(
+          chargingStation,
+          OCPP16RequestCommand.START_TRANSACTION,
+          {
+            connectorId,
+            idTag
+          }
+        )
+          .then(response => {
+            if (response.status === OCPP16AuthorizationStatus.ACCEPTED) {
+              logger.debug(
+                `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for idTag '${idTag}'`
+              )
+            } else {
+              logger.debug(
+                `${chargingStation.logPrefix()} Remote start transaction REJECTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for idTag '${idTag}'`
+              )
+            }
+          })
+          .catch(error => {
+            logger.error(
+              `${chargingStation.logPrefix()} ${moduleName}.constructor: Remote start transaction error:`,
+              error
+            )
+          })
+      }
+    )
+    this.on(
+      `Trigger${OCPP16MessageTrigger.BootNotification}`,
+      (chargingStation: ChargingStation) => {
+        chargingStation.ocppRequestService
+          .requestHandler<OCPP16BootNotificationRequest, OCPP16BootNotificationResponse>(
+          chargingStation,
+          OCPP16RequestCommand.BOOT_NOTIFICATION,
+          chargingStation.bootNotificationRequest,
+          { skipBufferingOnError: true, triggerMessage: true }
+        )
+          .then(response => {
+            chargingStation.bootNotificationResponse = response
+          })
+          .catch(error => {
+            logger.error(
+              `${chargingStation.logPrefix()} ${moduleName}.constructor: Trigger boot notification error:`,
+              error
+            )
+          })
+      }
+    )
+    this.on(`Trigger${OCPP16MessageTrigger.Heartbeat}`, (chargingStation: ChargingStation) => {
+      chargingStation.ocppRequestService
+        .requestHandler<OCPP16HeartbeatRequest, OCPP16HeartbeatResponse>(
+        chargingStation,
+        OCPP16RequestCommand.HEARTBEAT,
+        undefined,
+        {
+          triggerMessage: true
+        }
+      )
+        .catch(error => {
+          logger.error(
+            `${chargingStation.logPrefix()} ${moduleName}.constructor: Trigger heartbeat error:`,
+            error
+          )
+        })
+    })
+    this.on(
+      `$Trigger${OCPP16MessageTrigger.StatusNotification}`,
+      (chargingStation: ChargingStation, connectorId?: number) => {
+        const errorHandler = (error: Error): void => {
+          logger.error(
+            `${chargingStation.logPrefix()} ${moduleName}.constructor: Trigger status notification error:`,
+            error
+          )
+        }
+        if (connectorId != null) {
+          chargingStation.ocppRequestService
+            .requestHandler<OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse>(
+            chargingStation,
+            OCPP16RequestCommand.STATUS_NOTIFICATION,
+            {
+              connectorId,
+              errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
+              status: chargingStation.getConnectorStatus(connectorId)?.status
+            },
+            {
+              triggerMessage: true
+            }
+          )
+            .catch(errorHandler)
+        } else if (chargingStation.hasEvses) {
+          for (const evseStatus of chargingStation.evses.values()) {
+            for (const [id, connectorStatus] of evseStatus.connectors) {
+              chargingStation.ocppRequestService
+                .requestHandler<OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse>(
+                chargingStation,
+                OCPP16RequestCommand.STATUS_NOTIFICATION,
+                {
+                  connectorId: id,
+                  errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
+                  status: connectorStatus.status
+                },
+                {
+                  triggerMessage: true
+                }
+              )
+                .catch(errorHandler)
+            }
+          }
+        } else {
+          for (const [id, connectorStatus] of chargingStation.connectors) {
+            chargingStation.ocppRequestService
+              .requestHandler<OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse>(
+              chargingStation,
+              OCPP16RequestCommand.STATUS_NOTIFICATION,
+              {
+                connectorId: id,
+                errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
+                status: connectorStatus.status
+              },
+              {
+                triggerMessage: true
+              }
+            )
+              .catch(errorHandler)
+          }
+        }
+      }
+    )
+    this.validatePayload = this.validatePayload.bind(this)
   }
 
   public async incomingRequestHandler<ReqType extends JsonType, ResType extends JsonType>(
@@ -427,17 +629,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
     commandName: OCPP16IncomingRequestCommand,
     commandPayload: JsonType
   ): boolean {
-    if (this.jsonSchemas.has(commandName)) {
-      return this.validateIncomingRequestPayload(
-        chargingStation,
-        commandName,
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        this.jsonSchemas.get(commandName)!,
-        commandPayload
-      )
+    if (this.payloadValidateFunctions.has(commandName)) {
+      return this.validateIncomingRequestPayload(chargingStation, commandName, commandPayload)
     }
     logger.warn(
-      `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`
+      `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
     )
     return false
   }
@@ -726,10 +922,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
             chargingProfile.chargingProfileId
           } startSchedule property is not a Date instance. Trying to convert it to a Date instance`
         )
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
         chargingProfile.chargingSchedule.startSchedule = convertToDate(
           chargingProfile.chargingSchedule.startSchedule
-        )!
+        )
       }
       if (chargingProfile.chargingSchedule.duration == null) {
         logger.debug(
@@ -740,7 +935,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         // OCPP specifies that if duration is not defined, it should be infinite
         chargingProfile.chargingSchedule.duration = differenceInSeconds(
           maxTime,
-          chargingProfile.chargingSchedule.startSchedule
+          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+          chargingProfile.chargingSchedule.startSchedule!
         )
       }
       if (
@@ -772,8 +968,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
     if (compositeSchedule != null) {
       return {
         status: GenericStatus.Accepted,
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        scheduleStart: compositeSchedule.startSchedule!,
+        scheduleStart: compositeSchedule.startSchedule,
         connectorId,
         chargingSchedule: compositeSchedule
       }
@@ -805,8 +1000,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
     const connectorStatus = chargingStation.getConnectorStatus(connectorId!)
     if (connectorId != null && isNotEmptyArray(connectorStatus?.chargingProfiles)) {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      connectorStatus!.chargingProfiles = []
+      connectorStatus.chargingProfiles = []
       logger.debug(
         `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${connectorId}`
       )
@@ -921,95 +1115,47 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         idTag
       )
     }
-    const remoteStartTransactionLogMsg = `
-      ${chargingStation.logPrefix()} Transaction remotely STARTED on ${
-        chargingStation.stationInfo?.chargingStationId
-      }#${transactionConnectorId} for idTag '${idTag}'`
-    await OCPP16ServiceUtils.sendAndSetConnectorStatus(
-      chargingStation,
-      transactionConnectorId,
-      OCPP16ChargePointStatus.Preparing
-    )
-    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId)!
-    // Authorization check required
+    // idTag authorization check required
     if (
       chargingStation.getAuthorizeRemoteTxRequests() &&
-      (await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, transactionConnectorId, idTag))
+      !(await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, transactionConnectorId, idTag))
     ) {
-      // Authorization successful, start transaction
-      if (
-        (chargingProfile != null &&
-          this.setRemoteStartTransactionChargingProfile(
-            chargingStation,
-            transactionConnectorId,
-            chargingProfile
-          )) ||
-        chargingProfile == null
-      ) {
-        connectorStatus.transactionRemoteStarted = true
-        if (
-          (
-            await chargingStation.ocppRequestService.requestHandler<
-            OCPP16StartTransactionRequest,
-            OCPP16StartTransactionResponse
-            >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
-              connectorId: transactionConnectorId,
-              idTag
-            })
-          ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
-        ) {
-          logger.debug(remoteStartTransactionLogMsg)
-          return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
-        }
-        return await this.notifyRemoteStartTransactionRejected(
-          chargingStation,
-          transactionConnectorId,
-          idTag
-        )
-      }
       return await this.notifyRemoteStartTransactionRejected(
         chargingStation,
         transactionConnectorId,
         idTag
       )
     }
-    // No authorization check required, start transaction
+    await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+      chargingStation,
+      transactionConnectorId,
+      OCPP16ChargePointStatus.Preparing
+    )
     if (
-      (chargingProfile != null &&
-        this.setRemoteStartTransactionChargingProfile(
-          chargingStation,
-          transactionConnectorId,
-          chargingProfile
-        )) ||
-      chargingProfile == null
+      chargingProfile != null &&
+      !this.setRemoteStartTransactionChargingProfile(
+        chargingStation,
+        transactionConnectorId,
+        chargingProfile
+      )
     ) {
-      connectorStatus.transactionRemoteStarted = true
-      if (
-        (
-          await chargingStation.ocppRequestService.requestHandler<
-          OCPP16StartTransactionRequest,
-          OCPP16StartTransactionResponse
-          >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
-            connectorId: transactionConnectorId,
-            idTag
-          })
-        ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
-      ) {
-        logger.debug(remoteStartTransactionLogMsg)
-        return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
-      }
       return await this.notifyRemoteStartTransactionRejected(
         chargingStation,
         transactionConnectorId,
         idTag
       )
     }
-    return await this.notifyRemoteStartTransactionRejected(
-      chargingStation,
-      transactionConnectorId,
-      idTag
-    )
+    Promise.resolve()
+      .then(() =>
+        this.emit(
+          OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
+          chargingStation,
+          transactionConnectorId,
+          idTag
+        )
+      )
+      .catch(Constants.EMPTY_FUNCTION)
+    return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
   }
 
   private async notifyRemoteStartTransactionRejected (
@@ -1026,7 +1172,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       )
     }
     logger.warn(
-      `${chargingStation.logPrefix()} Remote starting transaction REJECTED on connector id ${connectorId}, idTag '${idTag}', availability '${connectorStatus?.availability}', status '${connectorStatus?.status}'`
+      `${chargingStation.logPrefix()} Remote start transaction REJECTED on connector id ${connectorId}, idTag '${idTag}', availability '${connectorStatus?.availability}', status '${connectorStatus?.status}'`
     )
     return OCPP16Constants.OCPP_RESPONSE_REJECTED
   }
@@ -1407,110 +1553,30 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
     ) {
       return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED
     }
-    try {
-      switch (requestedMessage) {
-        case OCPP16MessageTrigger.BootNotification:
-          setTimeout(() => {
-            chargingStation.ocppRequestService
-              .requestHandler<OCPP16BootNotificationRequest, OCPP16BootNotificationResponse>(
+    switch (requestedMessage) {
+      case OCPP16MessageTrigger.BootNotification:
+        Promise.resolve()
+          .then(() => this.emit(`Trigger${OCPP16MessageTrigger.BootNotification}`, chargingStation))
+          .catch(Constants.EMPTY_FUNCTION)
+        return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
+      case OCPP16MessageTrigger.Heartbeat:
+        Promise.resolve()
+          .then(() => this.emit(`Trigger${OCPP16MessageTrigger.Heartbeat}`, chargingStation))
+          .catch(Constants.EMPTY_FUNCTION)
+        return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
+      case OCPP16MessageTrigger.StatusNotification:
+        Promise.resolve()
+          .then(() =>
+            this.emit(
+              `Trigger${OCPP16MessageTrigger.StatusNotification}`,
               chargingStation,
-              OCPP16RequestCommand.BOOT_NOTIFICATION,
-              chargingStation.bootNotificationRequest,
-              { skipBufferingOnError: true, triggerMessage: true }
+              connectorId
             )
-              .then(response => {
-                chargingStation.bootNotificationResponse = response
-              })
-              .catch(Constants.EMPTY_FUNCTION)
-          }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY)
-          return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
-        case OCPP16MessageTrigger.Heartbeat:
-          setTimeout(() => {
-            chargingStation.ocppRequestService
-              .requestHandler<OCPP16HeartbeatRequest, OCPP16HeartbeatResponse>(
-              chargingStation,
-              OCPP16RequestCommand.HEARTBEAT,
-              undefined,
-              {
-                triggerMessage: true
-              }
-            )
-              .catch(Constants.EMPTY_FUNCTION)
-          }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY)
-          return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
-        case OCPP16MessageTrigger.StatusNotification:
-          setTimeout(() => {
-            if (connectorId != null) {
-              chargingStation.ocppRequestService
-                .requestHandler<OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse>(
-                chargingStation,
-                OCPP16RequestCommand.STATUS_NOTIFICATION,
-                {
-                  connectorId,
-                  errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-                  status: chargingStation.getConnectorStatus(connectorId)?.status
-                },
-                {
-                  triggerMessage: true
-                }
-              )
-                .catch(Constants.EMPTY_FUNCTION)
-            } else if (chargingStation.hasEvses) {
-              for (const evseStatus of chargingStation.evses.values()) {
-                for (const [id, connectorStatus] of evseStatus.connectors) {
-                  chargingStation.ocppRequestService
-                    .requestHandler<
-                  OCPP16StatusNotificationRequest,
-                  OCPP16StatusNotificationResponse
-                  >(
-                    chargingStation,
-                    OCPP16RequestCommand.STATUS_NOTIFICATION,
-                    {
-                      connectorId: id,
-                      errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-                      status: connectorStatus.status
-                    },
-                    {
-                      triggerMessage: true
-                    }
-                  )
-                    .catch(Constants.EMPTY_FUNCTION)
-                }
-              }
-            } else {
-              for (const [id, connectorStatus] of chargingStation.connectors) {
-                chargingStation.ocppRequestService
-                  .requestHandler<
-                OCPP16StatusNotificationRequest,
-                OCPP16StatusNotificationResponse
-                >(
-                  chargingStation,
-                  OCPP16RequestCommand.STATUS_NOTIFICATION,
-                  {
-                    connectorId: id,
-                    errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-                    status: connectorStatus.status
-                  },
-                  {
-                    triggerMessage: true
-                  }
-                )
-                  .catch(Constants.EMPTY_FUNCTION)
-              }
-            }
-          }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY)
-          return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
-        default:
-          return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED
-      }
-    } catch (error) {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      return this.handleIncomingRequestError<OCPP16TriggerMessageResponse>(
-        chargingStation,
-        OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
-        error as Error,
-        { errorResponse: OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED }
-      )!
+          )
+          .catch(Constants.EMPTY_FUNCTION)
+        return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
+      default:
+        return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED
     }
   }