refactor: update MikroORM entities definition
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStation.ts
index 47ffecf2b1ebd2be207eaf7dc0a92b000448c754..7534f66e72f38abd778d11397b42708a03ab0af3 100644 (file)
@@ -1,4 +1,4 @@
-// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
+// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
 
 import { createHash } from 'node:crypto'
 import { EventEmitter } from 'node:events'
@@ -132,8 +132,9 @@ import {
   buildStartedMessage,
   buildStoppedMessage,
   buildUpdatedMessage,
-  cloneObject,
+  clone,
   convertToBoolean,
+  convertToDate,
   convertToInt,
   exponentialDelay,
   formatDurationMilliSeconds,
@@ -228,10 +229,8 @@ export class ChargingStation extends EventEmitter {
       `${
         this.stationInfo?.supervisionUrlOcppConfiguration === true &&
         isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        isNotEmptyString(getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!)?.value)
-          ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-            getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!)!.value
+        isNotEmptyString(getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey)?.value)
+          ? getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey)?.value
           : this.configuredSupervisionUrl.href
       }/${this.stationInfo?.chargingStationId}`
     )
@@ -503,8 +502,7 @@ export class ChargingStation extends EventEmitter {
       this.stationInfo?.supervisionUrlOcppConfiguration === true &&
       isNotEmptyString(this.stationInfo.supervisionUrlOcppKey)
     ) {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey!, url)
+      setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey, url)
     } else {
       // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
       this.stationInfo!.supervisionUrls = url
@@ -518,7 +516,7 @@ export class ChargingStation extends EventEmitter {
       this.heartbeatSetInterval = setInterval(() => {
         this.ocppRequestService
           .requestHandler<HeartbeatRequest, HeartbeatResponse>(this, RequestCommand.HEARTBEAT)
-          .catch((error) => {
+          .catch(error => {
             logger.error(
               `${this.logPrefix()} Error while sending '${RequestCommand.HEARTBEAT}':`,
               error
@@ -603,7 +601,7 @@ export class ChargingStation extends EventEmitter {
             meterValue: [meterValue]
           }
         )
-          .catch((error) => {
+          .catch(error => {
             logger.error(
               `${this.logPrefix()} Error while sending '${RequestCommand.METER_VALUES}':`,
               error
@@ -833,8 +831,7 @@ export class ChargingStation extends EventEmitter {
   public startAutomaticTransactionGenerator (connectorIds?: number[]): void {
     this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(this)
     if (isNotEmptyArray(connectorIds)) {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      for (const connectorId of connectorIds!) {
+      for (const connectorId of connectorIds) {
         this.automaticTransactionGenerator?.startConnector(connectorId)
       }
     } else {
@@ -846,8 +843,7 @@ export class ChargingStation extends EventEmitter {
 
   public stopAutomaticTransactionGenerator (connectorIds?: number[]): void {
     if (isNotEmptyArray(connectorIds)) {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      for (const connectorId of connectorIds!) {
+      for (const connectorId of connectorIds) {
         this.automaticTransactionGenerator?.stopConnector(connectorId)
       }
     } else {
@@ -1107,17 +1103,16 @@ export class ChargingStation extends EventEmitter {
     createSerialNumber(stationTemplate, stationInfo)
     stationInfo.voltageOut = this.getVoltageOut(stationInfo)
     if (isNotEmptyArray(stationTemplate.power)) {
-      stationTemplate.power = stationTemplate.power as number[]
       const powerArrayRandomIndex = Math.floor(secureRandom() * stationTemplate.power.length)
       stationInfo.maximumPower =
         stationTemplate.powerUnit === PowerUnits.KILO_WATT
           ? stationTemplate.power[powerArrayRandomIndex] * 1000
           : stationTemplate.power[powerArrayRandomIndex]
     } else {
-      stationTemplate.power = stationTemplate.power as number
       stationInfo.maximumPower =
         stationTemplate.powerUnit === PowerUnits.KILO_WATT
-          ? stationTemplate.power * 1000
+          ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+          stationTemplate.power! * 1000
           : stationTemplate.power
     }
     stationInfo.maximumAmperage = this.getMaximumAmperage(stationInfo)
@@ -1125,8 +1120,7 @@ export class ChargingStation extends EventEmitter {
       stationTemplate.firmwareVersionPattern ?? Constants.SEMVER_PATTERN
     if (
       isNotEmptyString(stationInfo.firmwareVersion) &&
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      !new RegExp(stationInfo.firmwareVersionPattern).test(stationInfo.firmwareVersion!)
+      !new RegExp(stationInfo.firmwareVersionPattern).test(stationInfo.firmwareVersion)
     ) {
       logger.warn(
         `${this.logPrefix()} Firmware version '${stationInfo.firmwareVersion}' in template file ${
@@ -1225,13 +1219,10 @@ export class ChargingStation extends EventEmitter {
     ) {
       const patternGroup =
         this.stationInfo.firmwareUpgrade?.versionUpgrade?.patternGroup ??
-        this.stationInfo.firmwareVersion?.split('.').length
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      const match = new RegExp(this.stationInfo.firmwareVersionPattern!)
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        .exec(this.stationInfo.firmwareVersion!)
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        ?.slice(1, patternGroup! + 1)
+        this.stationInfo.firmwareVersion.split('.').length
+      const match = new RegExp(this.stationInfo.firmwareVersionPattern)
+        .exec(this.stationInfo.firmwareVersion)
+        ?.slice(1, patternGroup + 1)
       if (match != null) {
         const patchLevelIndex = match.length - 1
         match[patchLevelIndex] = (
@@ -1264,7 +1255,7 @@ export class ChargingStation extends EventEmitter {
     this.initializeOcppConfiguration()
     this.initializeOcppServices()
     this.once(ChargingStationEvents.accepted, () => {
-      this.startMessageSequence().catch((error) => {
+      this.startMessageSequence().catch(error => {
         logger.error(`${this.logPrefix()} Error while starting the message sequence:`, error)
       })
     })
@@ -1311,37 +1302,31 @@ export class ChargingStation extends EventEmitter {
     if (
       this.stationInfo?.supervisionUrlOcppConfiguration === true &&
       isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!) == null
+      getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey) == null
     ) {
       addConfigurationKey(
         this,
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        this.stationInfo.supervisionUrlOcppKey!,
+        this.stationInfo.supervisionUrlOcppKey,
         this.configuredSupervisionUrl.href,
         { reboot: true }
       )
     } else if (
       this.stationInfo?.supervisionUrlOcppConfiguration === false &&
       isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!) != null
+      getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey) != null
     ) {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      deleteConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!, { save: false })
+      deleteConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey, { save: false })
     }
     if (
       isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey!) == null
+      getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey) == null
     ) {
       addConfigurationKey(
         this,
-        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        this.stationInfo!.amperageLimitationOcppKey!,
+        this.stationInfo.amperageLimitationOcppKey,
         // prettier-ignore
         // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        (this.stationInfo!.maximumAmperage! * getAmperageLimitationUnitDivider(this.stationInfo)).toString()
+        (this.stationInfo.maximumAmperage! * getAmperageLimitationUnitDivider(this.stationInfo)).toString()
       )
     }
     if (getConfigurationKey(this, StandardParametersKey.SupportedFeatureProfiles) == null) {
@@ -1412,11 +1397,11 @@ export class ChargingStation extends EventEmitter {
   private initializeConnectorsOrEvsesFromFile (configuration: ChargingStationConfiguration): void {
     if (configuration.connectorsStatus != null && configuration.evsesStatus == null) {
       for (const [connectorId, connectorStatus] of configuration.connectorsStatus.entries()) {
-        this.connectors.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus))
+        this.connectors.set(connectorId, clone<ConnectorStatus>(connectorStatus))
       }
     } else if (configuration.evsesStatus != null && configuration.connectorsStatus == null) {
       for (const [evseId, evseStatusConfiguration] of configuration.evsesStatus.entries()) {
-        const evseStatus = cloneObject<EvseStatusConfiguration>(evseStatusConfiguration)
+        const evseStatus = clone<EvseStatusConfiguration>(evseStatusConfiguration)
         delete evseStatus.connectorsStatus
         this.evses.set(evseId, {
           ...(evseStatus as EvseStatus),
@@ -1503,7 +1488,7 @@ export class ChargingStation extends EventEmitter {
               this.logPrefix(),
               this.templateFile
             )
-            this.connectors.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus))
+            this.connectors.set(connectorId, clone<ConnectorStatus>(connectorStatus))
           }
           initializeConnectorsMapStatus(this.connectors, this.logPrefix())
           this.saveConnectorsStatus()
@@ -1647,7 +1632,7 @@ export class ChargingStation extends EventEmitter {
         const configurationFromFile = this.getConfigurationFromFile()
         let configurationData: ChargingStationConfiguration =
           configurationFromFile != null
-            ? cloneObject<ChargingStationConfiguration>(configurationFromFile)
+            ? clone<ChargingStationConfiguration>(configurationFromFile)
             : {}
         if (this.stationInfo?.stationInfoPersistentConfiguration === true) {
           configurationData.stationInfo = this.stationInfo
@@ -1710,7 +1695,7 @@ export class ChargingStation extends EventEmitter {
             this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash)
             this.sharedLRUCache.setChargingStationConfiguration(configurationData)
             this.configurationFileHash = configurationHash
-          }).catch((error) => {
+          }).catch(error => {
             handleFileException(
               this.configurationFile,
               FileType.ChargingStationConfiguration,
@@ -1776,6 +1761,11 @@ export class ChargingStation extends EventEmitter {
           >(this, RequestCommand.BOOT_NOTIFICATION, this.bootNotificationRequest, {
             skipBufferingOnError: true
           })
+          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+          this.bootNotificationResponse.currentTime = convertToDate(
+            // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+            this.bootNotificationResponse?.currentTime
+          )!
           if (!this.isRegistered()) {
             this.stationInfo?.registrationMaxRetries !== -1 && ++registrationRetryCount
             await sleep(
@@ -1799,8 +1789,9 @@ export class ChargingStation extends EventEmitter {
         }
       } else {
         logger.error(
-          `${this.logPrefix()} Registration failure: maximum retries reached (${registrationRetryCount}) or retry disabled (${this
-            .stationInfo?.registrationMaxRetries})`
+          `${this.logPrefix()} Registration failure: maximum retries reached (${registrationRetryCount}) or retry disabled (${
+            this.stationInfo?.registrationMaxRetries
+          })`
         )
       }
       this.autoReconnectRetryCount = 0
@@ -2116,15 +2107,11 @@ export class ChargingStation extends EventEmitter {
   private getAmperageLimitation (): number | undefined {
     if (
       isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      getConfigurationKey(this, this.stationInfo!.amperageLimitationOcppKey!) != null
+      getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey) != null
     ) {
       return (
-        convertToInt(
-          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-          getConfigurationKey(this, this.stationInfo!.amperageLimitationOcppKey!)!.value
-          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        ) / getAmperageLimitationUnitDivider(this.stationInfo!)
+        convertToInt(getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey)?.value) /
+        getAmperageLimitationUnitDivider(this.stationInfo)
       )
     }
   }
@@ -2279,9 +2266,7 @@ export class ChargingStation extends EventEmitter {
       let configuredSupervisionUrlIndex: number
       switch (Configuration.getSupervisionUrlDistribution()) {
         case SupervisionUrlDistribution.RANDOM:
-          configuredSupervisionUrlIndex = Math.floor(
-            secureRandom() * (supervisionUrls as string[]).length
-          )
+          configuredSupervisionUrlIndex = Math.floor(secureRandom() * supervisionUrls.length)
           break
         case SupervisionUrlDistribution.ROUND_ROBIN:
         case SupervisionUrlDistribution.CHARGING_STATION_AFFINITY:
@@ -2296,12 +2281,13 @@ export class ChargingStation extends EventEmitter {
                 SupervisionUrlDistribution.CHARGING_STATION_AFFINITY
               }`
             )
-          configuredSupervisionUrlIndex = (this.index - 1) % (supervisionUrls as string[]).length
+          configuredSupervisionUrlIndex = (this.index - 1) % supervisionUrls.length
           break
       }
-      configuredSupervisionUrl = (supervisionUrls as string[])[configuredSupervisionUrlIndex]
+      configuredSupervisionUrl = supervisionUrls[configuredSupervisionUrlIndex]
     } else {
-      configuredSupervisionUrl = supervisionUrls as string
+      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+      configuredSupervisionUrl = supervisionUrls!
     }
     if (isNotEmptyString(configuredSupervisionUrl)) {
       return new URL(configuredSupervisionUrl)