refactor: improve time handling code
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStation.ts
index d0c7b0780119e528ab5c6a019563f7177dc4c7ff..70390b152dd9356219c9ba2d2ced00a9d9c1c002 100644 (file)
@@ -14,12 +14,18 @@ import { dirname, join } from 'node:path';
 import { URL } from 'node:url';
 import { parentPort } from 'node:worker_threads';
 
+import { millisecondsToSeconds, secondsToMilliseconds } from 'date-fns';
 import merge from 'just-merge';
 import { type RawData, WebSocket } from 'ws';
 
 import { AutomaticTransactionGenerator } from './AutomaticTransactionGenerator';
 import { ChargingStationWorkerBroadcastChannel } from './broadcast-channel/ChargingStationWorkerBroadcastChannel';
-import { ChargingStationConfigurationUtils } from './ChargingStationConfigurationUtils';
+import {
+  addConfigurationKey,
+  deleteConfigurationKey,
+  getConfigurationKey,
+  setConfigurationKeyValue,
+} from './ChargingStationConfigurationUtils';
 import {
   buildConnectorsMap,
   checkConnectorsConfiguration,
@@ -172,6 +178,7 @@ export class ChargingStation {
   private configurationFileHash!: string;
   private connectorsConfigurationHash!: string;
   private evsesConfigurationHash!: string;
+  private automaticTransactionGeneratorConfiguration?: AutomaticTransactionGeneratorConfiguration;
   private ocppIncomingRequestService!: OCPPIncomingRequestService;
   private readonly messageBuffer: Set<string>;
   private configuredSupervisionUrl!: URL;
@@ -212,16 +219,8 @@ export class ChargingStation {
       `${
         this.getSupervisionUrlOcppConfiguration() &&
         isNotEmptyString(this.getSupervisionUrlOcppKey()) &&
-        isNotEmptyString(
-          ChargingStationConfigurationUtils.getConfigurationKey(
-            this,
-            this.getSupervisionUrlOcppKey(),
-          )?.value,
-        )
-          ? ChargingStationConfigurationUtils.getConfigurationKey(
-              this,
-              this.getSupervisionUrlOcppKey(),
-            )!.value
+        isNotEmptyString(getConfigurationKey(this, this.getSupervisionUrlOcppKey())?.value)
+          ? getConfigurationKey(this, this.getSupervisionUrlOcppKey())!.value
           : this.configuredSupervisionUrl.href
       }/${this.stationInfo.chargingStationId}`,
     );
@@ -363,7 +362,10 @@ export class ChargingStation {
   public getMaximumPower(stationInfo?: ChargingStationInfo): number {
     const localStationInfo = stationInfo ?? this.stationInfo;
     // eslint-disable-next-line @typescript-eslint/dot-notation
-    return (localStationInfo['maxPower'] as number) ?? localStationInfo.maximumPower;
+    return (
+      (localStationInfo['maxPower' as keyof ChargingStationInfo] as number) ??
+      localStationInfo.maximumPower
+    );
   }
 
   public getConnectorMaximumAvailablePower(connectorId: number): number {
@@ -497,7 +499,7 @@ export class ChargingStation {
   }
 
   public getAuthorizeRemoteTxRequests(): boolean {
-    const authorizeRemoteTxRequests = ChargingStationConfigurationUtils.getConfigurationKey(
+    const authorizeRemoteTxRequests = getConfigurationKey(
       this,
       StandardParametersKey.AuthorizeRemoteTxRequests,
     );
@@ -505,7 +507,7 @@ export class ChargingStation {
   }
 
   public getLocalAuthListEnabled(): boolean {
-    const localAuthListEnabled = ChargingStationConfigurationUtils.getConfigurationKey(
+    const localAuthListEnabled = getConfigurationKey(
       this,
       StandardParametersKey.LocalAuthListEnabled,
     );
@@ -513,19 +515,13 @@ export class ChargingStation {
   }
 
   public getHeartbeatInterval(): number {
-    const HeartbeatInterval = ChargingStationConfigurationUtils.getConfigurationKey(
-      this,
-      StandardParametersKey.HeartbeatInterval,
-    );
+    const HeartbeatInterval = getConfigurationKey(this, StandardParametersKey.HeartbeatInterval);
     if (HeartbeatInterval) {
-      return convertToInt(HeartbeatInterval.value) * 1000;
+      return secondsToMilliseconds(convertToInt(HeartbeatInterval.value));
     }
-    const HeartBeatInterval = ChargingStationConfigurationUtils.getConfigurationKey(
-      this,
-      StandardParametersKey.HeartBeatInterval,
-    );
+    const HeartBeatInterval = getConfigurationKey(this, StandardParametersKey.HeartBeatInterval);
     if (HeartBeatInterval) {
-      return convertToInt(HeartBeatInterval.value) * 1000;
+      return secondsToMilliseconds(convertToInt(HeartBeatInterval.value));
     }
     this.stationInfo?.autoRegister === false &&
       logger.warn(
@@ -541,11 +537,7 @@ export class ChargingStation {
       this.getSupervisionUrlOcppConfiguration() &&
       isNotEmptyString(this.getSupervisionUrlOcppKey())
     ) {
-      ChargingStationConfigurationUtils.setConfigurationKeyValue(
-        this,
-        this.getSupervisionUrlOcppKey(),
-        url,
-      );
+      setConfigurationKeyValue(this, this.getSupervisionUrlOcppKey(), url);
     } else {
       this.stationInfo.supervisionUrls = url;
       this.saveStationInfo();
@@ -601,14 +593,14 @@ export class ChargingStation {
   public startMeterValues(connectorId: number, interval: number): void {
     if (connectorId === 0) {
       logger.error(
-        `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId.toString()}`,
+        `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId}`,
       );
       return;
     }
     if (!this.getConnectorStatus(connectorId)) {
       logger.error(
         `${this.logPrefix()} Trying to start MeterValues on non existing connector id
-          ${connectorId.toString()}`,
+          ${connectorId}`,
       );
       return;
     }
@@ -700,6 +692,7 @@ export class ChargingStation {
                 this.idTagsCache.deleteIdTags(getIdTagsFile(this.stationInfo)!);
                 // Restart the ATG
                 this.stopAutomaticTransactionGenerator();
+                delete this.automaticTransactionGeneratorConfiguration;
                 if (this.getAutomaticTransactionGeneratorConfiguration()?.enable === true) {
                   this.startAutomaticTransactionGenerator();
                 }
@@ -768,7 +761,7 @@ export class ChargingStation {
   }
 
   public hasFeatureProfile(featureProfile: SupportedFeatureProfiles): boolean | undefined {
-    return ChargingStationConfigurationUtils.getConfigurationKey(
+    return getConfigurationKey(
       this,
       StandardParametersKey.SupportedFeatureProfiles,
     )?.value?.includes(featureProfile);
@@ -785,7 +778,7 @@ export class ChargingStation {
       terminateOpened: false,
     },
   ): void {
-    options = { handshakeTimeout: this.getConnectionTimeout() * 1000, ...options };
+    options = { handshakeTimeout: secondsToMilliseconds(this.getConnectionTimeout()), ...options };
     params = { ...{ closeOpened: false, terminateOpened: false }, ...params };
     if (this.started === false && this.starting === false) {
       logger.warn(
@@ -856,25 +849,28 @@ export class ChargingStation {
   }
 
   public getAutomaticTransactionGeneratorConfiguration(): AutomaticTransactionGeneratorConfiguration {
-    let automaticTransactionGeneratorConfiguration:
-      | AutomaticTransactionGeneratorConfiguration
-      | undefined;
-    const automaticTransactionGeneratorConfigurationFromFile =
-      this.getConfigurationFromFile()?.automaticTransactionGenerator;
-    if (
-      this.getAutomaticTransactionGeneratorPersistentConfiguration() &&
-      automaticTransactionGeneratorConfigurationFromFile
-    ) {
-      automaticTransactionGeneratorConfiguration =
-        automaticTransactionGeneratorConfigurationFromFile;
-    } else {
-      automaticTransactionGeneratorConfiguration =
-        this.getTemplateFromFile()?.AutomaticTransactionGenerator;
+    if (isNullOrUndefined(this.automaticTransactionGeneratorConfiguration)) {
+      let automaticTransactionGeneratorConfiguration:
+        | AutomaticTransactionGeneratorConfiguration
+        | undefined;
+      const automaticTransactionGeneratorConfigurationFromFile =
+        this.getConfigurationFromFile()?.automaticTransactionGenerator;
+      if (
+        this.getAutomaticTransactionGeneratorPersistentConfiguration() &&
+        automaticTransactionGeneratorConfigurationFromFile
+      ) {
+        automaticTransactionGeneratorConfiguration =
+          automaticTransactionGeneratorConfigurationFromFile;
+      } else {
+        automaticTransactionGeneratorConfiguration =
+          this.getTemplateFromFile()?.AutomaticTransactionGenerator;
+      }
+      this.automaticTransactionGeneratorConfiguration = {
+        ...Constants.DEFAULT_ATG_CONFIGURATION,
+        ...automaticTransactionGeneratorConfiguration,
+      };
     }
-    return {
-      ...Constants.DEFAULT_ATG_CONFIGURATION,
-      ...automaticTransactionGeneratorConfiguration,
-    };
+    return this.automaticTransactionGeneratorConfiguration!;
   }
 
   public getAutomaticTransactionGeneratorStatuses(): Status[] | undefined {
@@ -945,10 +941,7 @@ export class ChargingStation {
 
   public getReservationOnConnectorId0Enabled(): boolean {
     return convertToBoolean(
-      ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.ReserveConnectorZeroSupported,
-      )!.value,
+      getConfigurationKey(this, StandardParametersKey.ReserveConnectorZeroSupported)!.value,
     );
   }
 
@@ -1006,14 +999,14 @@ export class ChargingStation {
     if (this.hasEvses) {
       for (const evseStatus of this.evses.values()) {
         for (const connectorStatus of evseStatus.connectors.values()) {
-          if (connectorStatus?.reservation?.[filterKey] === value) {
+          if (connectorStatus?.reservation?.[filterKey as keyof Reservation] === value) {
             return connectorStatus.reservation;
           }
         }
       }
     } else {
       for (const connectorStatus of this.connectors.values()) {
-        if (connectorStatus?.reservation?.[filterKey] === value) {
+        if (connectorStatus?.reservation?.[filterKey as keyof Reservation] === value) {
           return connectorStatus.reservation;
         }
       }
@@ -1033,32 +1026,38 @@ export class ChargingStation {
   public startReservationExpirationSetInterval(customInterval?: number): void {
     const interval =
       customInterval ?? Constants.DEFAULT_RESERVATION_EXPIRATION_OBSERVATION_INTERVAL;
-    logger.info(
-      `${this.logPrefix()} Reservation expiration date interval is set to ${interval}
-        and starts on charging station now`,
-    );
     if (interval > 0) {
-      // eslint-disable-next-line @typescript-eslint/no-misused-promises
-      this.reservationExpirationSetInterval = setInterval(async (): Promise<void> => {
-        const now = new Date();
+      logger.info(
+        `${this.logPrefix()} Reservation expiration date checks started every ${formatDurationMilliSeconds(
+          interval,
+        )}`,
+      );
+      this.reservationExpirationSetInterval = setInterval((): void => {
+        const currentDate = new Date();
         if (this.hasEvses) {
           for (const evseStatus of this.evses.values()) {
             for (const connectorStatus of evseStatus.connectors.values()) {
-              if (connectorStatus.reservation!.expiryDate < now) {
-                await this.removeReservation(
-                  connectorStatus.reservation!,
+              if (
+                connectorStatus.reservation &&
+                connectorStatus.reservation.expiryDate < currentDate
+              ) {
+                this.removeReservation(
+                  connectorStatus.reservation,
                   ReservationTerminationReason.EXPIRED,
-                );
+                ).catch(Constants.EMPTY_FUNCTION);
               }
             }
           }
         } else {
           for (const connectorStatus of this.connectors.values()) {
-            if (connectorStatus.reservation!.expiryDate < now) {
-              await this.removeReservation(
-                connectorStatus.reservation!,
+            if (
+              connectorStatus.reservation &&
+              connectorStatus.reservation.expiryDate < currentDate
+            ) {
+              this.removeReservation(
+                connectorStatus.reservation,
                 ReservationTerminationReason.EXPIRED,
-              );
+              ).catch(Constants.EMPTY_FUNCTION);
             }
           }
         }
@@ -1228,7 +1227,7 @@ export class ChargingStation {
       stationTemplate?.firmwareUpgrade ?? {},
     );
     stationInfo.resetTime = !isNullOrUndefined(stationTemplate?.resetTime)
-      ? stationTemplate.resetTime! * 1000
+      ? secondsToMilliseconds(stationTemplate.resetTime!)
       : Constants.CHARGING_STATION_DEFAULT_RESET_TIME;
     stationInfo.maximumAmperage = this.getMaximumAmperage(stationInfo);
     return stationInfo;
@@ -1342,7 +1341,7 @@ export class ChargingStation {
     if (this.stationInfo?.autoRegister === true) {
       this.bootNotificationResponse = {
         currentTime: new Date(),
-        interval: this.getHeartbeatInterval() / 1000,
+        interval: millisecondsToSeconds(this.getHeartbeatInterval()),
         status: RegistrationStatusEnumType.ACCEPTED,
       };
     }
@@ -1373,37 +1372,18 @@ export class ChargingStation {
   }
 
   private initializeOcppConfiguration(): void {
-    if (
-      !ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.HeartbeatInterval,
-      )
-    ) {
-      ChargingStationConfigurationUtils.addConfigurationKey(
-        this,
-        StandardParametersKey.HeartbeatInterval,
-        '0',
-      );
+    if (!getConfigurationKey(this, StandardParametersKey.HeartbeatInterval)) {
+      addConfigurationKey(this, StandardParametersKey.HeartbeatInterval, '0');
     }
-    if (
-      !ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.HeartBeatInterval,
-      )
-    ) {
-      ChargingStationConfigurationUtils.addConfigurationKey(
-        this,
-        StandardParametersKey.HeartBeatInterval,
-        '0',
-        { visible: false },
-      );
+    if (!getConfigurationKey(this, StandardParametersKey.HeartBeatInterval)) {
+      addConfigurationKey(this, StandardParametersKey.HeartBeatInterval, '0', { visible: false });
     }
     if (
       this.getSupervisionUrlOcppConfiguration() &&
       isNotEmptyString(this.getSupervisionUrlOcppKey()) &&
-      !ChargingStationConfigurationUtils.getConfigurationKey(this, this.getSupervisionUrlOcppKey())
+      !getConfigurationKey(this, this.getSupervisionUrlOcppKey())
     ) {
-      ChargingStationConfigurationUtils.addConfigurationKey(
+      addConfigurationKey(
         this,
         this.getSupervisionUrlOcppKey(),
         this.configuredSupervisionUrl.href,
@@ -1412,22 +1392,15 @@ export class ChargingStation {
     } else if (
       !this.getSupervisionUrlOcppConfiguration() &&
       isNotEmptyString(this.getSupervisionUrlOcppKey()) &&
-      ChargingStationConfigurationUtils.getConfigurationKey(this, this.getSupervisionUrlOcppKey())
+      getConfigurationKey(this, this.getSupervisionUrlOcppKey())
     ) {
-      ChargingStationConfigurationUtils.deleteConfigurationKey(
-        this,
-        this.getSupervisionUrlOcppKey(),
-        { save: false },
-      );
+      deleteConfigurationKey(this, this.getSupervisionUrlOcppKey(), { save: false });
     }
     if (
       isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
-      !ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        this.stationInfo.amperageLimitationOcppKey!,
-      )
+      !getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey!)
     ) {
-      ChargingStationConfigurationUtils.addConfigurationKey(
+      addConfigurationKey(
         this,
         this.stationInfo.amperageLimitationOcppKey!,
         (
@@ -1435,43 +1408,28 @@ export class ChargingStation {
         ).toString(),
       );
     }
-    if (
-      !ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.SupportedFeatureProfiles,
-      )
-    ) {
-      ChargingStationConfigurationUtils.addConfigurationKey(
+    if (!getConfigurationKey(this, StandardParametersKey.SupportedFeatureProfiles)) {
+      addConfigurationKey(
         this,
         StandardParametersKey.SupportedFeatureProfiles,
         `${SupportedFeatureProfiles.Core},${SupportedFeatureProfiles.FirmwareManagement},${SupportedFeatureProfiles.LocalAuthListManagement},${SupportedFeatureProfiles.SmartCharging},${SupportedFeatureProfiles.RemoteTrigger}`,
       );
     }
-    ChargingStationConfigurationUtils.addConfigurationKey(
+    addConfigurationKey(
       this,
       StandardParametersKey.NumberOfConnectors,
       this.getNumberOfConnectors().toString(),
       { readonly: true },
       { overwrite: true },
     );
-    if (
-      !ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.MeterValuesSampledData,
-      )
-    ) {
-      ChargingStationConfigurationUtils.addConfigurationKey(
+    if (!getConfigurationKey(this, StandardParametersKey.MeterValuesSampledData)) {
+      addConfigurationKey(
         this,
         StandardParametersKey.MeterValuesSampledData,
         MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
       );
     }
-    if (
-      !ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.ConnectorPhaseRotation,
-      )
-    ) {
+    if (!getConfigurationKey(this, StandardParametersKey.ConnectorPhaseRotation)) {
       const connectorsPhaseRotation: string[] = [];
       if (this.hasEvses) {
         for (const evseStatus of this.evses.values()) {
@@ -1488,47 +1446,25 @@ export class ChargingStation {
           );
         }
       }
-      ChargingStationConfigurationUtils.addConfigurationKey(
+      addConfigurationKey(
         this,
         StandardParametersKey.ConnectorPhaseRotation,
         connectorsPhaseRotation.toString(),
       );
     }
-    if (
-      !ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.AuthorizeRemoteTxRequests,
-      )
-    ) {
-      ChargingStationConfigurationUtils.addConfigurationKey(
-        this,
-        StandardParametersKey.AuthorizeRemoteTxRequests,
-        'true',
-      );
-    }
-    if (
-      !ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.LocalAuthListEnabled,
-      ) &&
-      ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.SupportedFeatureProfiles,
-      )?.value?.includes(SupportedFeatureProfiles.LocalAuthListManagement)
-    ) {
-      ChargingStationConfigurationUtils.addConfigurationKey(
-        this,
-        StandardParametersKey.LocalAuthListEnabled,
-        'false',
-      );
+    if (!getConfigurationKey(this, StandardParametersKey.AuthorizeRemoteTxRequests)) {
+      addConfigurationKey(this, StandardParametersKey.AuthorizeRemoteTxRequests, 'true');
     }
     if (
-      !ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.ConnectionTimeOut,
+      !getConfigurationKey(this, StandardParametersKey.LocalAuthListEnabled) &&
+      getConfigurationKey(this, StandardParametersKey.SupportedFeatureProfiles)?.value?.includes(
+        SupportedFeatureProfiles.LocalAuthListManagement,
       )
     ) {
-      ChargingStationConfigurationUtils.addConfigurationKey(
+      addConfigurationKey(this, StandardParametersKey.LocalAuthListEnabled, 'false');
+    }
+    if (!getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut)) {
+      addConfigurationKey(
         this,
         StandardParametersKey.ConnectionTimeOut,
         Constants.DEFAULT_CONNECTION_TIMEOUT.toString(),
@@ -1761,8 +1697,9 @@ export class ChargingStation {
         if (!existsSync(dirname(this.configurationFile))) {
           mkdirSync(dirname(this.configurationFile), { recursive: true });
         }
-        let configurationData: ChargingStationConfiguration =
-          cloneObject<ChargingStationConfiguration>(this.getConfigurationFromFile()!) ?? {};
+        let configurationData: ChargingStationConfiguration = this.getConfigurationFromFile()
+          ? cloneObject<ChargingStationConfiguration>(this.getConfigurationFromFile()!)
+          : {};
         if (this.getStationInfoPersistentConfiguration() && this.stationInfo) {
           configurationData.stationInfo = this.stationInfo;
         } else {
@@ -1890,7 +1827,7 @@ export class ChargingStation {
             this.getRegistrationMaxRetries() !== -1 && ++registrationRetryCount;
             await sleep(
               this?.bootNotificationResponse?.interval
-                ? this.bootNotificationResponse.interval * 1000
+                ? secondsToMilliseconds(this.bootNotificationResponse.interval)
                 : Constants.DEFAULT_BOOT_NOTIFICATION_INTERVAL,
             );
           }
@@ -2164,19 +2101,10 @@ export class ChargingStation {
 
   // 0 for disabling
   private getConnectionTimeout(): number {
-    if (
-      ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        StandardParametersKey.ConnectionTimeOut,
-      )
-    ) {
+    if (getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut)) {
       return (
-        parseInt(
-          ChargingStationConfigurationUtils.getConfigurationKey(
-            this,
-            StandardParametersKey.ConnectionTimeOut,
-          )!.value!,
-        ) ?? Constants.DEFAULT_CONNECTION_TIMEOUT
+        parseInt(getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut)!.value!) ??
+        Constants.DEFAULT_CONNECTION_TIMEOUT
       );
     }
     return Constants.DEFAULT_CONNECTION_TIMEOUT;
@@ -2219,17 +2147,11 @@ export class ChargingStation {
   private getAmperageLimitation(): number | undefined {
     if (
       isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
-      ChargingStationConfigurationUtils.getConfigurationKey(
-        this,
-        this.stationInfo.amperageLimitationOcppKey!,
-      )
+      getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey!)
     ) {
       return (
         convertToInt(
-          ChargingStationConfigurationUtils.getConfigurationKey(
-            this,
-            this.stationInfo.amperageLimitationOcppKey!,
-          )?.value,
+          getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey!)?.value,
         ) / getAmperageLimitationUnitDivider(this.stationInfo)
       );
     }
@@ -2348,23 +2270,18 @@ export class ChargingStation {
   }
 
   private startWebSocketPing(): void {
-    const webSocketPingInterval: number = ChargingStationConfigurationUtils.getConfigurationKey(
+    const webSocketPingInterval: number = getConfigurationKey(
       this,
       StandardParametersKey.WebSocketPingInterval,
     )
-      ? convertToInt(
-          ChargingStationConfigurationUtils.getConfigurationKey(
-            this,
-            StandardParametersKey.WebSocketPingInterval,
-          )?.value,
-        )
+      ? convertToInt(getConfigurationKey(this, StandardParametersKey.WebSocketPingInterval)?.value)
       : 0;
     if (webSocketPingInterval > 0 && !this.webSocketPingSetInterval) {
       this.webSocketPingSetInterval = setInterval(() => {
         if (this.isWebSocketConnectionOpened() === true) {
           this.wsConnection?.ping();
         }
-      }, webSocketPingInterval * 1000);
+      }, secondsToMilliseconds(webSocketPingInterval));
       logger.info(
         `${this.logPrefix()} WebSocket ping started every ${formatDurationSeconds(
           webSocketPingInterval,
@@ -2462,7 +2379,7 @@ export class ChargingStation {
       ++this.autoReconnectRetryCount;
       const reconnectDelay = this.getReconnectExponentialDelay()
         ? exponentialDelay(this.autoReconnectRetryCount)
-        : this.getConnectionTimeout() * 1000;
+        : secondsToMilliseconds(this.getConnectionTimeout());
       const reconnectDelayWithdraw = 1000;
       const reconnectTimeout =
         reconnectDelay && reconnectDelay - reconnectDelayWithdraw > 0