build(deps-dev): apply updates
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 2.0 / OCPP20ResponseService.ts
index 15b355a5b0862e1de4e851e84d36070c376663d4..aefd93dc454907632987f7ad433bb8eb9859dfaa 100644 (file)
@@ -1,33 +1,31 @@
 // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
 
-import fs from 'fs';
-import path from 'path';
-import { fileURLToPath } from 'url';
-
 import type { JSONSchemaType } from 'ajv';
 
-import OCPPError from '../../../exception/OCPPError';
-import type { JsonObject, JsonType } from '../../../types/JsonType';
+import { OCPP20ServiceUtils } from './OCPP20ServiceUtils';
+import { type ChargingStation, ChargingStationConfigurationUtils } from '../../../charging-station';
+import { OCPPError } from '../../../exception';
 import {
+  ErrorType,
+  type JsonObject,
+  type JsonType,
+  type OCPP20BootNotificationResponse,
+  type OCPP20ClearCacheResponse,
+  type OCPP20HeartbeatResponse,
   OCPP20IncomingRequestCommand,
+  OCPP20OptionalVariableName,
   OCPP20RequestCommand,
-} from '../../../types/ocpp/2.0/Requests';
-import type {
-  OCPP20BootNotificationResponse,
-  OCPP20ClearCacheResponse,
-  OCPP20HeartbeatResponse,
-} from '../../../types/ocpp/2.0/Responses';
-import { ErrorType } from '../../../types/ocpp/ErrorType';
-import { OCPPVersion } from '../../../types/ocpp/OCPPVersion';
-import { RegistrationStatusEnumType, ResponseHandler } from '../../../types/ocpp/Responses';
-import logger from '../../../utils/Logger';
-import type ChargingStation from '../../ChargingStation';
-import OCPPResponseService from '../OCPPResponseService';
-import { OCPP20ServiceUtils } from './OCPP20ServiceUtils';
+  type OCPP20StatusNotificationResponse,
+  OCPPVersion,
+  RegistrationStatusEnumType,
+  type ResponseHandler,
+} from '../../../types';
+import { logger } from '../../../utils';
+import { OCPPResponseService } from '../OCPPResponseService';
 
 const moduleName = 'OCPP20ResponseService';
 
-export default class OCPP20ResponseService extends OCPPResponseService {
+export class OCPP20ResponseService extends OCPPResponseService {
   public jsonIncomingRequestResponseSchemas: Map<
     OCPP20IncomingRequestCommand,
     JSONSchemaType<JsonObject>
@@ -37,62 +35,63 @@ export default class OCPP20ResponseService extends OCPPResponseService {
   private jsonSchemas: Map<OCPP20RequestCommand, JSONSchemaType<JsonObject>>;
 
   public constructor() {
-    if (new.target?.name === moduleName) {
-      throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
-    }
+    // if (new.target?.name === moduleName) {
+    //   throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
+    // }
     super(OCPPVersion.VERSION_20);
     this.responseHandlers = new Map<OCPP20RequestCommand, ResponseHandler>([
       [OCPP20RequestCommand.BOOT_NOTIFICATION, this.handleResponseBootNotification.bind(this)],
       [OCPP20RequestCommand.HEARTBEAT, this.emptyResponseHandler.bind(this)],
+      [OCPP20RequestCommand.STATUS_NOTIFICATION, this.emptyResponseHandler.bind(this)],
     ]);
     this.jsonSchemas = new Map<OCPP20RequestCommand, JSONSchemaType<JsonObject>>([
       [
         OCPP20RequestCommand.BOOT_NOTIFICATION,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/2.0/BootNotificationResponse.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP20BootNotificationResponse>,
+        OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20BootNotificationResponse>(
+          'assets/json-schemas/ocpp/2.0/BootNotificationResponse.json',
+          moduleName,
+          'constructor',
+        ),
       ],
       [
         OCPP20RequestCommand.HEARTBEAT,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/2.0/HeartbeatResponse.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP20HeartbeatResponse>,
+        OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20HeartbeatResponse>(
+          'assets/json-schemas/ocpp/2.0/HeartbeatResponse.json',
+          moduleName,
+          'constructor',
+        ),
+      ],
+      [
+        OCPP20RequestCommand.STATUS_NOTIFICATION,
+        OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20StatusNotificationResponse>(
+          'assets/json-schemas/ocpp/2.0/StatusNotificationResponse.json',
+          moduleName,
+          'constructor',
+        ),
       ],
     ]);
     this.jsonIncomingRequestResponseSchemas = new Map([
       [
         OCPP20IncomingRequestCommand.CLEAR_CACHE,
-        JSON.parse(
-          fs.readFileSync(
-            path.resolve(
-              path.dirname(fileURLToPath(import.meta.url)),
-              '../../../assets/json-schemas/ocpp/2.0/ClearCacheResponse.json'
-            ),
-            'utf8'
-          )
-        ) as JSONSchemaType<OCPP20ClearCacheResponse>,
+        OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20ClearCacheResponse>(
+          'assets/json-schemas/ocpp/2.0/ClearCacheResponse.json',
+          moduleName,
+          'constructor',
+        ),
       ],
     ]);
-    this.validatePayload.bind(this);
+    this.validatePayload = this.validatePayload.bind(this) as (
+      chargingStation: ChargingStation,
+      commandName: OCPP20RequestCommand,
+      payload: JsonType,
+    ) => boolean;
   }
 
   public async responseHandler(
     chargingStation: ChargingStation,
     commandName: OCPP20RequestCommand,
     payload: JsonType,
-    requestPayload: JsonType
+    requestPayload: JsonType,
   ): Promise<void> {
     if (
       chargingStation.isRegistered() === true ||
@@ -108,7 +107,7 @@ export default class OCPP20ResponseService extends OCPPResponseService {
         } catch (error) {
           logger.error(
             `${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handle response error:`,
-            error
+            error,
           );
           throw error;
         }
@@ -119,10 +118,10 @@ export default class OCPP20ResponseService extends OCPPResponseService {
           `${commandName} is not implemented to handle response PDU ${JSON.stringify(
             payload,
             null,
-            2
+            2,
           )}`,
           commandName,
-          payload
+          payload,
         );
       }
     } else {
@@ -131,10 +130,10 @@ export default class OCPP20ResponseService extends OCPPResponseService {
         `${commandName} cannot be issued to handle response PDU ${JSON.stringify(
           payload,
           null,
-          2
+          2,
         )} while the charging station is not registered on the central server.`,
         commandName,
-        payload
+        payload,
       );
     }
   }
@@ -142,44 +141,35 @@ export default class OCPP20ResponseService extends OCPPResponseService {
   private validatePayload(
     chargingStation: ChargingStation,
     commandName: OCPP20RequestCommand,
-    payload: JsonType
+    payload: JsonType,
   ): boolean {
     if (this.jsonSchemas.has(commandName) === true) {
       return this.validateResponsePayload(
         chargingStation,
         commandName,
         this.jsonSchemas.get(commandName),
-        payload
+        payload,
       );
     }
     logger.warn(
-      `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`
+      `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`,
     );
     return false;
   }
 
   private handleResponseBootNotification(
     chargingStation: ChargingStation,
-    payload: OCPP20BootNotificationResponse
+    payload: OCPP20BootNotificationResponse,
   ): void {
     if (payload.status === RegistrationStatusEnumType.ACCEPTED) {
-      // ChargingStationConfigurationUtils.addConfigurationKey(
-      //   chargingStation,
-      //   OCPP16StandardParametersKey.HeartbeatInterval,
-      //   payload.interval.toString(),
-      //   {},
-      //   { overwrite: true, save: true }
-      // );
-      // ChargingStationConfigurationUtils.addConfigurationKey(
-      //   chargingStation,
-      //   OCPP16StandardParametersKey.HeartBeatInterval,
-      //   payload.interval.toString(),
-      //   { visible: false },
-      //   { overwrite: true, save: true }
-      // );
-      chargingStation.heartbeatSetInterval
-        ? chargingStation.restartHeartbeat()
-        : chargingStation.startHeartbeat();
+      ChargingStationConfigurationUtils.addConfigurationKey(
+        chargingStation,
+        OCPP20OptionalVariableName.HeartbeatInterval,
+        payload.interval.toString(),
+        {},
+        { overwrite: true, save: true },
+      );
+      OCPP20ServiceUtils.startHeartbeatInterval(chargingStation, payload.interval);
     }
     if (Object.values(RegistrationStatusEnumType).includes(payload.status)) {
       const logMsg = `${chargingStation.logPrefix()} Charging station in '${
@@ -190,9 +180,8 @@ export default class OCPP20ResponseService extends OCPPResponseService {
         : logger.info(logMsg);
     } else {
       logger.error(
-        chargingStation.logPrefix() +
-          ' Charging station boot notification response received: %j with undefined registration status',
-        payload
+        `${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
+        payload,
       );
     }
   }