build(deps-dev): apply updates
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStation.ts
index f18951635f72614fe0b284670668d655a3af5d63..0851c41abf6308a99774cfb4bc28b29371679c0d 100644 (file)
@@ -9,31 +9,24 @@ import { parentPort } from 'node:worker_threads';
 import merge from 'just-merge';
 import WebSocket, { type RawData } from 'ws';
 
+import { AutomaticTransactionGenerator } from './AutomaticTransactionGenerator';
+import { ChargingStationWorkerBroadcastChannel } from './broadcast-channel/ChargingStationWorkerBroadcastChannel';
+import { ChargingStationConfigurationUtils } from './ChargingStationConfigurationUtils';
+import { ChargingStationUtils } from './ChargingStationUtils';
+import { IdTagsCache } from './IdTagsCache';
 import {
-  AutomaticTransactionGenerator,
-  ChargingStationConfigurationUtils,
-  ChargingStationUtils,
-  ChargingStationWorkerBroadcastChannel,
-  IdTagsCache,
-  MessageChannelUtils,
-  SharedLRUCache,
-} from './internal';
-import {
-  // OCPP16IncomingRequestService,
+  OCPP16IncomingRequestService,
   OCPP16RequestService,
-  // OCPP16ResponseService,
+  OCPP16ResponseService,
   OCPP16ServiceUtils,
   OCPP20IncomingRequestService,
   OCPP20RequestService,
-  // OCPP20ResponseService,
+  OCPP20ResponseService,
   type OCPPIncomingRequestService,
   type OCPPRequestService,
-  // OCPPServiceUtils,
+  OCPPServiceUtils,
 } from './ocpp';
-import { OCPP16IncomingRequestService } from './ocpp/1.6/OCPP16IncomingRequestService';
-import { OCPP16ResponseService } from './ocpp/1.6/OCPP16ResponseService';
-import { OCPP20ResponseService } from './ocpp/2.0/OCPP20ResponseService';
-import { OCPPServiceUtils } from './ocpp/OCPPServiceUtils';
+import { SharedLRUCache } from './SharedLRUCache';
 import { BaseError, OCPPError } from '../exception';
 import { PerformanceStatistics } from '../performance';
 import {
@@ -42,7 +35,6 @@ import {
   type BootNotificationRequest,
   type BootNotificationResponse,
   type CachedRequest,
-  type ChargingStationAutomaticTransactionGeneratorConfiguration,
   type ChargingStationConfiguration,
   type ChargingStationInfo,
   type ChargingStationOcppConfiguration,
@@ -96,8 +88,13 @@ import {
   Configuration,
   Constants,
   DCElectricUtils,
+  ErrorUtils,
   FileUtils,
+  MessageChannelUtils,
   Utils,
+  buildChargingStationAutomaticTransactionGeneratorConfiguration,
+  buildConnectorsStatus,
+  buildEvsesStatus,
   logger,
 } from '../utils';
 
@@ -163,11 +160,17 @@ export class ChargingStation {
     return new URL(
       `${
         this.getSupervisionUrlOcppConfiguration() &&
-        Utils.isNotEmptyString(this.getSupervisionUrlOcppKey())
+        Utils.isNotEmptyString(this.getSupervisionUrlOcppKey()) &&
+        Utils.isNotEmptyString(
+          ChargingStationConfigurationUtils.getConfigurationKey(
+            this,
+            this.getSupervisionUrlOcppKey()
+          )?.value
+        )
           ? ChargingStationConfigurationUtils.getConfigurationKey(
               this,
               this.getSupervisionUrlOcppKey()
-            )?.value
+            ).value
           : this.configuredSupervisionUrl.href
       }/${this.stationInfo.chargingStationId}`
     );
@@ -185,8 +188,9 @@ export class ChargingStation {
   };
 
   public hasIdTags(): boolean {
-    const idTagsFile = ChargingStationUtils.getIdTagsFile(this.stationInfo);
-    return Utils.isNotEmptyArray(this.idTagsCache.getIdTags(idTagsFile));
+    return Utils.isNotEmptyArray(
+      this.idTagsCache.getIdTags(ChargingStationUtils.getIdTagsFile(this.stationInfo))
+    );
   }
 
   public getEnableStatistics(): boolean {
@@ -221,26 +225,26 @@ export class ChargingStation {
     return this?.bootNotificationResponse?.status;
   }
 
-  public isInUnknownState(): boolean {
+  public inUnknownState(): boolean {
     return Utils.isNullOrUndefined(this?.bootNotificationResponse?.status);
   }
 
-  public isInPendingState(): boolean {
+  public inPendingState(): boolean {
     return this?.bootNotificationResponse?.status === RegistrationStatusEnumType.PENDING;
   }
 
-  public isInAcceptedState(): boolean {
+  public inAcceptedState(): boolean {
     return this?.bootNotificationResponse?.status === RegistrationStatusEnumType.ACCEPTED;
   }
 
-  public isInRejectedState(): boolean {
+  public inRejectedState(): boolean {
     return this?.bootNotificationResponse?.status === RegistrationStatusEnumType.REJECTED;
   }
 
   public isRegistered(): boolean {
     return (
-      this.isInUnknownState() === false &&
-      (this.isInAcceptedState() === true || this.isInPendingState() === true)
+      this.inUnknownState() === false &&
+      (this.inAcceptedState() === true || this.inPendingState() === true)
     );
   }
 
@@ -935,7 +939,7 @@ export class ChargingStation {
         this.templateFileHash = template.templateHash;
       }
     } catch (error) {
-      FileUtils.handleFileException(
+      ErrorUtils.handleFileException(
         this.templateFile,
         FileType.ChargingStationTemplate,
         error as NodeJS.ErrnoException,
@@ -1497,7 +1501,7 @@ export class ChargingStation {
 
   private getConfigurationFromFile(): ChargingStationConfiguration | undefined {
     let configuration: ChargingStationConfiguration | undefined;
-    if (this.configurationFile && fs.existsSync(this.configurationFile)) {
+    if (Utils.isNotEmptyString(this.configurationFile) && fs.existsSync(this.configurationFile)) {
       try {
         if (this.sharedLRUCache.hasChargingStationConfiguration(this.configurationFileHash)) {
           configuration = this.sharedLRUCache.getChargingStationConfiguration(
@@ -1514,7 +1518,7 @@ export class ChargingStation {
           this.configurationFileHash = configuration.configurationHash;
         }
       } catch (error) {
-        FileUtils.handleFileException(
+        ErrorUtils.handleFileException(
           this.configurationFile,
           FileType.ChargingStationConfiguration,
           error as NodeJS.ErrnoException,
@@ -1525,18 +1529,8 @@ export class ChargingStation {
     return configuration;
   }
 
-  private saveChargingStationAutomaticTransactionGeneratorConfiguration(
-    stationTemplate?: ChargingStationTemplate
-  ): void {
-    this.saveConfiguration({
-      automaticTransactionGenerator: (stationTemplate ?? this.getTemplateFromFile())
-        .AutomaticTransactionGenerator,
-      ...(!Utils.isNullOrUndefined(this.automaticTransactionGenerator?.connectorsStatus) && {
-        automaticTransactionGeneratorStatuses: [
-          ...this.automaticTransactionGenerator.connectorsStatus.values(),
-        ],
-      }),
-    });
+  private saveChargingStationAutomaticTransactionGeneratorConfiguration(): void {
+    this.saveConfiguration();
   }
 
   private saveConnectorsStatus() {
@@ -1547,10 +1541,8 @@ export class ChargingStation {
     this.saveConfiguration();
   }
 
-  private saveConfiguration(
-    chargingStationAutomaticTransactionGeneratorConfiguration?: ChargingStationAutomaticTransactionGeneratorConfiguration
-  ): void {
-    if (this.configurationFile) {
+  private saveConfiguration(): void {
+    if (Utils.isNotEmptyString(this.configurationFile)) {
       try {
         if (!fs.existsSync(path.dirname(this.configurationFile))) {
           fs.mkdirSync(path.dirname(this.configurationFile), { recursive: true });
@@ -1563,30 +1555,15 @@ export class ChargingStation {
         if (this.getOcppPersistentConfiguration() && this.ocppConfiguration?.configurationKey) {
           configurationData.configurationKey = this.ocppConfiguration.configurationKey;
         }
-        if (chargingStationAutomaticTransactionGeneratorConfiguration) {
-          configurationData = merge<ChargingStationConfiguration>(
-            configurationData,
-            chargingStationAutomaticTransactionGeneratorConfiguration
-          );
-        }
+        configurationData = merge<ChargingStationConfiguration>(
+          configurationData,
+          buildChargingStationAutomaticTransactionGeneratorConfiguration(this)
+        );
         if (this.connectors.size > 0) {
-          configurationData.connectorsStatus = [...this.connectors.values()].map(
-            // eslint-disable-next-line @typescript-eslint/no-unused-vars
-            ({ transactionSetInterval, ...connectorStatusRest }) => connectorStatusRest
-          );
+          configurationData.connectorsStatus = buildConnectorsStatus(this);
         }
         if (this.evses.size > 0) {
-          configurationData.evsesStatus = [...this.evses.values()].map((evseStatus) => {
-            const status = {
-              ...evseStatus,
-              connectorsStatus: [...evseStatus.connectors.values()].map(
-                // eslint-disable-next-line @typescript-eslint/no-unused-vars
-                ({ transactionSetInterval, ...connectorStatusRest }) => connectorStatusRest
-              ),
-            };
-            delete status.connectors;
-            return status as EvseStatusConfiguration;
-          });
+          configurationData.evsesStatus = buildEvsesStatus(this);
         }
         delete configurationData.configurationHash;
         const configurationHash = crypto
@@ -1608,7 +1585,7 @@ export class ChargingStation {
               this.configurationFileHash = configurationHash;
             })
             .catch((error) => {
-              FileUtils.handleFileException(
+              ErrorUtils.handleFileException(
                 this.configurationFile,
                 FileType.ChargingStationConfiguration,
                 error as NodeJS.ErrnoException,
@@ -1626,7 +1603,7 @@ export class ChargingStation {
           );
         }
       } catch (error) {
-        FileUtils.handleFileException(
+        ErrorUtils.handleFileException(
           this.configurationFile,
           FileType.ChargingStationConfiguration,
           error as NodeJS.ErrnoException,
@@ -1645,9 +1622,11 @@ export class ChargingStation {
   }
 
   private getOcppConfigurationFromFile(): ChargingStationOcppConfiguration | undefined {
-    if (this.getOcppPersistentConfiguration() === true) {
-      return { configurationKey: this.getConfigurationFromFile()?.configurationKey };
+    const configurationKey = this.getConfigurationFromFile()?.configurationKey;
+    if (this.getOcppPersistentConfiguration() === true && configurationKey) {
+      return { configurationKey };
     }
+    return undefined;
   }
 
   private getOcppConfiguration(): ChargingStationOcppConfiguration | undefined {
@@ -1679,7 +1658,7 @@ export class ChargingStation {
             await Utils.sleep(
               this?.bootNotificationResponse?.interval
                 ? this.bootNotificationResponse.interval * 1000
-                : Constants.OCPP_DEFAULT_BOOT_NOTIFICATION_INTERVAL
+                : Constants.DEFAULT_BOOT_NOTIFICATION_INTERVAL
             );
           }
         } while (
@@ -1689,7 +1668,7 @@ export class ChargingStation {
         );
       }
       if (this.isRegistered() === true) {
-        if (this.isInAcceptedState() === true) {
+        if (this.inAcceptedState() === true) {
           await this.startMessageSequence();
         }
       } else {
@@ -2038,7 +2017,8 @@ export class ChargingStation {
             await OCPPServiceUtils.sendAndSetConnectorStatus(
               this,
               connectorId,
-              connectorBootStatus
+              connectorBootStatus,
+              evseId
             );
           }
         }
@@ -2098,7 +2078,8 @@ export class ChargingStation {
               OCPPServiceUtils.buildStatusNotificationRequest(
                 this,
                 connectorId,
-                ConnectorStatusEnum.Unavailable
+                ConnectorStatusEnum.Unavailable,
+                evseId
               )
             );
             delete connectorStatus?.status;
@@ -2170,6 +2151,7 @@ export class ChargingStation {
   }
 
   private getConfiguredSupervisionUrl(): URL {
+    let configuredSupervisionUrl: string;
     const supervisionUrls = this.stationInfo?.supervisionUrls ?? Configuration.getSupervisionUrls();
     if (Utils.isNotEmptyArray(supervisionUrls)) {
       let configuredSupervisionUrlIndex: number;
@@ -2191,9 +2173,14 @@ export class ChargingStation {
           configuredSupervisionUrlIndex = (this.index - 1) % supervisionUrls.length;
           break;
       }
-      return new URL(supervisionUrls[configuredSupervisionUrlIndex]);
+      configuredSupervisionUrl = supervisionUrls[configuredSupervisionUrlIndex];
+    } else {
+      configuredSupervisionUrl = supervisionUrls as string;
+    }
+    if (Utils.isNotEmptyString(configuredSupervisionUrl)) {
+      return new URL(configuredSupervisionUrl);
     }
-    return new URL(supervisionUrls as string);
+    throw new BaseError('No supervision urls configured');
   }
 
   private stopHeartbeat(): void {