Allow to specify timestamp in OCPP commands payload with the UI Server
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16RequestService.ts
index 3c72faf223eea8f8dca3adf78327cc7d432a7126..77b5cb586d90ed9752ef911c1b9aa25ba53502cd 100644 (file)
@@ -6,6 +6,7 @@ import { fileURLToPath } from 'url';
 
 import type { JSONSchemaType } from 'ajv';
 
+import { OCPP16ServiceUtils } from './OCPP16ServiceUtils';
 import OCPPError from '../../../exception/OCPPError';
 import type { JsonObject, JsonType } from '../../../types/JsonType';
 import type { OCPP16MeterValuesRequest } from '../../../types/ocpp/1.6/MeterValues';
@@ -13,10 +14,10 @@ import {
   type OCPP16BootNotificationRequest,
   type OCPP16DataTransferRequest,
   type OCPP16DiagnosticsStatusNotificationRequest,
+  type OCPP16FirmwareStatusNotificationRequest,
   type OCPP16HeartbeatRequest,
   OCPP16RequestCommand,
   type OCPP16StatusNotificationRequest,
-  type OCPP16UpdateFirmwareRequest,
 } from '../../../types/ocpp/1.6/Requests';
 import type {
   OCPP16AuthorizeRequest,
@@ -31,7 +32,6 @@ import Utils from '../../../utils/Utils';
 import type ChargingStation from '../../ChargingStation';
 import OCPPRequestService from '../OCPPRequestService';
 import type OCPPResponseService from '../OCPPResponseService';
-import { OCPP16ServiceUtils } from './OCPP16ServiceUtils';
 
 const moduleName = 'OCPP16RequestService';
 
@@ -46,123 +46,63 @@ export default class OCPP16RequestService extends OCPPRequestService {
     this.jsonSchemas = new Map<OCPP16RequestCommand, JSONSchemaType<JsonObject>>([
       [
         OCPP16RequestCommand.AUTHORIZE,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/1.6/Authorize.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP16AuthorizeRequest>,
+        this.parseJsonSchemaFile<OCPP16AuthorizeRequest>(
+          '../../../assets/json-schemas/ocpp/1.6/Authorize.json'
+        ),
       ],
       [
         OCPP16RequestCommand.BOOT_NOTIFICATION,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/1.6/BootNotification.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP16BootNotificationRequest>,
+        this.parseJsonSchemaFile<OCPP16BootNotificationRequest>(
+          '../../../assets/json-schemas/ocpp/1.6/BootNotification.json'
+        ),
       ],
       [
         OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP16DiagnosticsStatusNotificationRequest>,
+        this.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationRequest>(
+          '../../../assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json'
+        ),
       ],
       [
         OCPP16RequestCommand.HEARTBEAT,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/1.6/Heartbeat.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP16HeartbeatRequest>,
+        this.parseJsonSchemaFile<OCPP16HeartbeatRequest>(
+          '../../../assets/json-schemas/ocpp/1.6/Heartbeat.json'
+        ),
       ],
       [
         OCPP16RequestCommand.METER_VALUES,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/1.6/MeterValues.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP16MeterValuesRequest>,
+        this.parseJsonSchemaFile<OCPP16MeterValuesRequest>(
+          '../../../assets/json-schemas/ocpp/1.6/MeterValues.json'
+        ),
       ],
       [
         OCPP16RequestCommand.STATUS_NOTIFICATION,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/1.6/StatusNotification.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP16StatusNotificationRequest>,
+        this.parseJsonSchemaFile<OCPP16StatusNotificationRequest>(
+          '../../../assets/json-schemas/ocpp/1.6/StatusNotification.json'
+        ),
       ],
       [
         OCPP16RequestCommand.START_TRANSACTION,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/1.6/StartTransaction.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP16StartTransactionRequest>,
+        this.parseJsonSchemaFile<OCPP16StartTransactionRequest>(
+          '../../../assets/json-schemas/ocpp/1.6/StartTransaction.json'
+        ),
       ],
       [
         OCPP16RequestCommand.STOP_TRANSACTION,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/1.6/StopTransaction.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP16StopTransactionRequest>,
+        this.parseJsonSchemaFile<OCPP16StopTransactionRequest>(
+          '../../../assets/json-schemas/ocpp/1.6/StopTransaction.json'
+        ),
       ],
       [
         OCPP16RequestCommand.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.parseJsonSchemaFile<OCPP16DataTransferRequest>(
+          '../../../assets/json-schemas/ocpp/1.6/DataTransfer.json'
+        ),
       ],
       [
         OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP16UpdateFirmwareRequest>,
+        this.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationRequest>(
+          '../../../assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json'
+        ),
       ],
     ]);
     this.buildRequestPayload.bind(this);
@@ -235,6 +175,7 @@ export default class OCPP16RequestService extends OCPPRequestService {
           }),
         } as unknown as Request;
       case OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION:
+      case OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION:
         return {
           status: commandParams?.status,
         } as unknown as Request;
@@ -261,7 +202,7 @@ export default class OCPP16RequestService extends OCPPRequestService {
           meterStart: chargingStation.getEnergyActiveImportRegisterByConnectorId(
             commandParams?.connectorId as number
           ),
-          timestamp: new Date(),
+          timestamp: commandParams?.timestamp ?? new Date(),
         } as unknown as Request;
       case OCPP16RequestCommand.STOP_TRANSACTION:
         connectorId = chargingStation.getConnectorIdByTransactionId(
@@ -279,7 +220,7 @@ export default class OCPP16RequestService extends OCPPRequestService {
             commandParams?.idTag ??
             chargingStation.getTransactionIdTag(commandParams?.transactionId as number),
           meterStop: commandParams?.meterStop ?? energyActiveImportRegister,
-          timestamp: new Date(),
+          timestamp: commandParams?.timestamp ?? new Date(),
           reason: commandParams?.reason,
           ...(chargingStation.getTransactionDataMeterValues() && {
             transactionData: OCPP16ServiceUtils.buildTransactionDataMeterValues(
@@ -294,10 +235,6 @@ export default class OCPP16RequestService extends OCPPRequestService {
         } as unknown as Request;
       case OCPP16RequestCommand.DATA_TRANSFER:
         return commandParams as unknown as Request;
-      case OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION:
-        return {
-          status: commandParams?.status,
-        } as unknown as Request;
       default:
         // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
         throw new OCPPError(
@@ -309,4 +246,13 @@ export default class OCPP16RequestService extends OCPPRequestService {
         );
     }
   }
+
+  private parseJsonSchemaFile<T extends JsonType>(relativePath: string): JSONSchemaType<T> {
+    return JSON.parse(
+      fs.readFileSync(
+        path.resolve(path.dirname(fileURLToPath(import.meta.url)), relativePath),
+        'utf8'
+      )
+    ) as JSONSchemaType<T>;
+  }
 }