Hook the OCPP 2.0 stack into the main code
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16IncomingRequestService.ts
index 0af87023faf37e425e6f975e80d9e7eab29e5c6f..420edf86b5e5f1af369b354e6540eb178716e9ca 100644 (file)
@@ -1,11 +1,11 @@
-// Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
+// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
 
 import fs from 'fs';
 import path from 'path';
 import { URL, fileURLToPath } from 'url';
 
 import type { JSONSchemaType } from 'ajv';
-import { Client, FTPResponse } from 'basic-ftp';
+import { Client, type FTPResponse } from 'basic-ftp';
 import tar from 'tar';
 
 import OCPPError from '../../../exception/OCPPError';
@@ -14,7 +14,7 @@ import { OCPP16ChargePointErrorCode } from '../../../types/ocpp/1.6/ChargePointE
 import { OCPP16ChargePointStatus } from '../../../types/ocpp/1.6/ChargePointStatus';
 import {
   ChargingProfilePurposeType,
-  OCPP16ChargingProfile,
+  type OCPP16ChargingProfile,
 } from '../../../types/ocpp/1.6/ChargingProfile';
 import {
   OCPP16StandardParametersKey,
@@ -22,47 +22,53 @@ import {
 } from '../../../types/ocpp/1.6/Configuration';
 import { OCPP16DiagnosticsStatus } from '../../../types/ocpp/1.6/DiagnosticsStatus';
 import {
-  ChangeAvailabilityRequest,
-  ChangeConfigurationRequest,
-  ClearChargingProfileRequest,
-  DiagnosticsStatusNotificationRequest,
-  GetConfigurationRequest,
-  GetDiagnosticsRequest,
+  type ChangeAvailabilityRequest,
+  type ChangeConfigurationRequest,
+  type ClearChargingProfileRequest,
+  type DiagnosticsStatusNotificationRequest,
+  type GetConfigurationRequest,
+  type GetDiagnosticsRequest,
   OCPP16AvailabilityType,
-  OCPP16BootNotificationRequest,
-  OCPP16ClearCacheRequest,
-  OCPP16HeartbeatRequest,
+  type OCPP16BootNotificationRequest,
+  type OCPP16ClearCacheRequest,
+  type OCPP16DataTransferRequest,
+  OCPP16DataTransferVendorId,
+  type OCPP16HeartbeatRequest,
   OCPP16IncomingRequestCommand,
   OCPP16MessageTrigger,
   OCPP16RequestCommand,
-  OCPP16StatusNotificationRequest,
-  OCPP16TriggerMessageRequest,
-  RemoteStartTransactionRequest,
-  RemoteStopTransactionRequest,
-  ResetRequest,
-  SetChargingProfileRequest,
-  UnlockConnectorRequest,
+  type OCPP16StatusNotificationRequest,
+  type OCPP16TriggerMessageRequest,
+  type OCPP16UpdateFirmwareRequest,
+  type RemoteStartTransactionRequest,
+  type RemoteStopTransactionRequest,
+  type ResetRequest,
+  type SetChargingProfileRequest,
+  type UnlockConnectorRequest,
 } from '../../../types/ocpp/1.6/Requests';
-import type {
-  ChangeAvailabilityResponse,
-  ChangeConfigurationResponse,
-  ClearChargingProfileResponse,
-  DiagnosticsStatusNotificationResponse,
-  GetConfigurationResponse,
-  GetDiagnosticsResponse,
-  OCPP16BootNotificationResponse,
-  OCPP16HeartbeatResponse,
-  OCPP16StatusNotificationResponse,
-  OCPP16TriggerMessageResponse,
-  SetChargingProfileResponse,
-  UnlockConnectorResponse,
+import {
+  type ChangeAvailabilityResponse,
+  type ChangeConfigurationResponse,
+  type ClearChargingProfileResponse,
+  type DiagnosticsStatusNotificationResponse,
+  type GetConfigurationResponse,
+  type GetDiagnosticsResponse,
+  type OCPP16BootNotificationResponse,
+  type OCPP16DataTransferResponse,
+  OCPP16DataTransferStatus,
+  type OCPP16HeartbeatResponse,
+  type OCPP16StatusNotificationResponse,
+  type OCPP16TriggerMessageResponse,
+  type OCPP16UpdateFirmwareResponse,
+  type SetChargingProfileResponse,
+  type UnlockConnectorResponse,
 } from '../../../types/ocpp/1.6/Responses';
 import {
   OCPP16AuthorizationStatus,
-  OCPP16AuthorizeRequest,
-  OCPP16AuthorizeResponse,
-  OCPP16StartTransactionRequest,
-  OCPP16StartTransactionResponse,
+  type OCPP16AuthorizeRequest,
+  type OCPP16AuthorizeResponse,
+  type OCPP16StartTransactionRequest,
+  type OCPP16StartTransactionResponse,
   OCPP16StopTransactionReason,
 } from '../../../types/ocpp/1.6/Transaction';
 import type { OCPPConfigurationKey } from '../../../types/ocpp/Configuration';
@@ -123,6 +129,8 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer
       ],
       [OCPP16IncomingRequestCommand.GET_DIAGNOSTICS, this.handleRequestGetDiagnostics.bind(this)],
       [OCPP16IncomingRequestCommand.TRIGGER_MESSAGE, this.handleRequestTriggerMessage.bind(this)],
+      [OCPP16IncomingRequestCommand.DATA_TRANSFER, this.handleRequestDataTransfer.bind(this)],
+      // [OCPP16IncomingRequestCommand.UPDATE_FIRMWARE, this.handleRequestUpdateFirmware.bind(this)],
     ]);
     this.jsonSchemas = new Map<OCPP16IncomingRequestCommand, JSONSchemaType<JsonObject>>([
       [
@@ -269,6 +277,18 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer
           )
         ) as JSONSchemaType<OCPP16TriggerMessageRequest>,
       ],
+      [
+        OCPP16IncomingRequestCommand.DATA_TRANSFER,
+        JSON.parse(
+          fs.readFileSync(
+            path.resolve(
+              path.dirname(fileURLToPath(import.meta.url)),
+              '../../../assets/json-schemas/ocpp/1.6/DataTransfer.json'
+            ),
+            'utf8'
+          )
+        ) as JSONSchemaType<OCPP16DataTransferRequest>,
+      ],
     ]);
     this.validatePayload.bind(this);
   }
@@ -989,6 +1009,28 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer
     return Constants.OCPP_RESPONSE_REJECTED;
   }
 
+  private handleRequestUpdateFirmware(
+    chargingStation: ChargingStation,
+    commandPayload: OCPP16UpdateFirmwareRequest
+  ): OCPP16UpdateFirmwareResponse {
+    if (
+      OCPP16ServiceUtils.checkFeatureProfile(
+        chargingStation,
+        OCPP16SupportedFeatureProfiles.FirmwareManagement,
+        OCPP16IncomingRequestCommand.UPDATE_FIRMWARE
+      ) === false
+    ) {
+      return Constants.OCPP_RESPONSE_EMPTY;
+    }
+    logger.debug(
+      chargingStation.logPrefix() +
+        ' ' +
+        OCPP16IncomingRequestCommand.UPDATE_FIRMWARE +
+        ' request received: %j',
+      commandPayload
+    );
+  }
+
   private async handleRequestGetDiagnostics(
     chargingStation: ChargingStation,
     commandPayload: GetDiagnosticsRequest
@@ -1127,7 +1169,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer
       return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED;
     }
     if (
-      OCPP16ServiceUtils.isConnectorIdValid(
+      !OCPP16ServiceUtils.isConnectorIdValid(
         chargingStation,
         OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
         commandPayload.connectorId
@@ -1226,4 +1268,27 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer
       );
     }
   }
+
+  private handleRequestDataTransfer(
+    chargingStation: ChargingStation,
+    commandPayload: OCPP16DataTransferRequest
+  ): OCPP16DataTransferResponse {
+    try {
+      if (Object.values(OCPP16DataTransferVendorId).includes(commandPayload.vendorId)) {
+        return {
+          status: OCPP16DataTransferStatus.ACCEPTED,
+        };
+      }
+      return {
+        status: OCPP16DataTransferStatus.UNKNOWN_VENDOR_ID,
+      };
+    } catch (error) {
+      return this.handleIncomingRequestError(
+        chargingStation,
+        OCPP16IncomingRequestCommand.DATA_TRANSFER,
+        error as Error,
+        { errorResponse: Constants.OCPP_DATA_TRANSFER_RESPONSE_REJECTED }
+      );
+    }
+  }
 }