feat: allow to override supervisionUrls at adding charging stations
authorJérôme Benoit <jerome.benoit@sap.com>
Mon, 12 Feb 2024 12:20:41 +0000 (13:20 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Mon, 12 Feb 2024 12:20:41 +0000 (13:20 +0100)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
README.md
src/charging-station/Bootstrap.ts
src/charging-station/ChargingStation.ts
src/charging-station/Helpers.ts
src/types/ChargingStationWorker.ts
ui/web/src/types/ChargingStationType.ts

index 84347a67d8fd428fffc6ea0dbf83271a255f1da6..14843e47de80b3efe41cd31a73328ec47ecd7a0e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -573,6 +573,7 @@ Set the Websocket header _Sec-Websocket-Protocol_ to `ui0.0.1`.
    `template`: string,  
    `numberOfStations`: number,  
    `options?`: {  
+   `supervisionUrls`: string | string[],  
    `persistentConfiguration?`: boolean,  
    `autoStart?`: boolean,  
    `autoRegister?`: boolean,  
index 9e24c8b845e258351e1087cd36fab590a572fa98..3993ae1f2a34a23ea3113b04b447512deb6474b9 100644 (file)
@@ -67,7 +67,7 @@ export class Bootstrap extends EventEmitter {
   private workerImplementation?: WorkerAbstract<ChargingStationWorkerData>
   private readonly uiServer?: AbstractUIServer
   private storage?: Storage
-  private readonly chargingStationsByTemplate: Map<string, TemplateChargingStations>
+  private readonly templatesChargingStations: Map<string, TemplateChargingStations>
   private readonly version: string = version
   private initializedCounters: boolean
   private started: boolean
@@ -85,7 +85,7 @@ export class Bootstrap extends EventEmitter {
     this.started = false
     this.starting = false
     this.stopping = false
-    this.chargingStationsByTemplate = new Map<string, TemplateChargingStations>()
+    this.templatesChargingStations = new Map<string, TemplateChargingStations>()
     this.uiServer = UIServerFactory.getUIServerImplementation(
       Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer)
     )
@@ -106,11 +106,11 @@ export class Bootstrap extends EventEmitter {
   }
 
   public get numberOfChargingStationTemplates (): number {
-    return this.chargingStationsByTemplate.size
+    return this.templatesChargingStations.size
   }
 
   public get numberOfConfiguredChargingStations (): number {
-    return [...this.chargingStationsByTemplate.values()].reduce(
+    return [...this.templatesChargingStations.values()].reduce(
       (accumulator, value) => accumulator + value.configured,
       0
     )
@@ -118,7 +118,7 @@ export class Bootstrap extends EventEmitter {
 
   public getLastIndex (templateName: string): number {
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    const indexes = [...this.chargingStationsByTemplate.get(templateName)!.indexes]
+    const indexes = [...this.templatesChargingStations.get(templateName)!.indexes]
       .concat(0)
       .sort((a, b) => a - b)
     for (let i = 0; i < indexes.length - 1; i++) {
@@ -134,14 +134,14 @@ export class Bootstrap extends EventEmitter {
   }
 
   private get numberOfAddedChargingStations (): number {
-    return [...this.chargingStationsByTemplate.values()].reduce(
+    return [...this.templatesChargingStations.values()].reduce(
       (accumulator, value) => accumulator + value.added,
       0
     )
   }
 
   private get numberOfStartedChargingStations (): number {
-    return [...this.chargingStationsByTemplate.values()].reduce(
+    return [...this.templatesChargingStations.values()].reduce(
       (accumulator, value) => accumulator + value.started,
       0
     )
@@ -196,8 +196,8 @@ export class Bootstrap extends EventEmitter {
         for (const stationTemplateUrl of Configuration.getStationTemplateUrls()!) {
           try {
             const nbStations =
-              this.chargingStationsByTemplate.get(parse(stationTemplateUrl.file).name)
-                ?.configured ?? stationTemplateUrl.numberOfStations
+              this.templatesChargingStations.get(parse(stationTemplateUrl.file).name)?.configured ??
+              stationTemplateUrl.numberOfStations
             for (let index = 1; index <= nbStations; index++) {
               await this.addChargingStation(index, stationTemplateUrl.file)
             }
@@ -412,10 +412,11 @@ export class Bootstrap extends EventEmitter {
   private readonly workerEventDeleted = (data: ChargingStationData): void => {
     this.uiServer?.chargingStations.delete(data.stationInfo.hashId)
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    --this.chargingStationsByTemplate.get(data.stationInfo.templateName)!.added
-    this.chargingStationsByTemplate
-      .get(data.stationInfo.templateName)
-      ?.indexes.delete(data.stationInfo.templateIndex)
+    const templateChargingStations = this.templatesChargingStations.get(
+      data.stationInfo.templateName
+    )!
+    --templateChargingStations.added
+    templateChargingStations.indexes.delete(data.stationInfo.templateIndex)
     logger.info(
       `${this.logPrefix()} ${moduleName}.workerEventDeleted: Charging station ${
         data.stationInfo.chargingStationId
@@ -428,7 +429,7 @@ export class Bootstrap extends EventEmitter {
   private readonly workerEventStarted = (data: ChargingStationData): void => {
     this.uiServer?.chargingStations.set(data.stationInfo.hashId, data)
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    ++this.chargingStationsByTemplate.get(data.stationInfo.templateName)!.started
+    ++this.templatesChargingStations.get(data.stationInfo.templateName)!.started
     logger.info(
       `${this.logPrefix()} ${moduleName}.workerEventStarted: Charging station ${
         data.stationInfo.chargingStationId
@@ -441,7 +442,7 @@ export class Bootstrap extends EventEmitter {
   private readonly workerEventStopped = (data: ChargingStationData): void => {
     this.uiServer?.chargingStations.set(data.stationInfo.hashId, data)
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    --this.chargingStationsByTemplate.get(data.stationInfo.templateName)!.started
+    --this.templatesChargingStations.get(data.stationInfo.templateName)!.started
     logger.info(
       `${this.logPrefix()} ${moduleName}.workerEventStopped: Charging station ${
         data.stationInfo.chargingStationId
@@ -477,7 +478,7 @@ export class Bootstrap extends EventEmitter {
       if (isNotEmptyArray(stationTemplateUrls)) {
         for (const stationTemplateUrl of stationTemplateUrls) {
           const templateName = parse(stationTemplateUrl.file).name
-          this.chargingStationsByTemplate.set(templateName, {
+          this.templatesChargingStations.set(templateName, {
             configured: stationTemplateUrl.numberOfStations,
             added: 0,
             started: 0,
@@ -485,7 +486,7 @@ export class Bootstrap extends EventEmitter {
           })
           this.uiServer?.chargingStationTemplates.add(templateName)
         }
-        if (this.chargingStationsByTemplate.size !== stationTemplateUrls.length) {
+        if (this.templatesChargingStations.size !== stationTemplateUrls.length) {
           console.error(
             chalk.red(
               "'stationTemplateUrls' contains duplicate entries, please check your configuration"
@@ -530,10 +531,12 @@ export class Bootstrap extends EventEmitter {
       ),
       options
     })
-    const templateName = parse(stationTemplateFile).name
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    ++this.chargingStationsByTemplate.get(templateName)!.added
-    this.chargingStationsByTemplate.get(templateName)?.indexes.add(index)
+    const templateChargingStations = this.templatesChargingStations.get(
+      parse(stationTemplateFile).name
+    )!
+    ++templateChargingStations.added
+    templateChargingStations.indexes.add(index)
   }
 
   private gracefulShutdown (): void {
index 38d40dc1323b313280010ade231f7cfbc5eee8cf..72bfd0aeceeadb0737b6f4629aab0586e87fe768 100644 (file)
@@ -535,6 +535,15 @@ export class ChargingStation extends EventEmitter {
     return Constants.DEFAULT_HEARTBEAT_INTERVAL
   }
 
+  public setSupervisionUrls (urls: string | string[], saveStationInfo = true): void {
+    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+    this.stationInfo!.supervisionUrls = urls
+    if (saveStationInfo) {
+      this.saveStationInfo()
+    }
+    this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl()
+  }
+
   public setSupervisionUrl (url: string): void {
     if (
       this.stationInfo?.supervisionUrlOcppConfiguration === true &&
@@ -542,10 +551,7 @@ export class ChargingStation extends EventEmitter {
     ) {
       setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey, url)
     } else {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      this.stationInfo!.supervisionUrls = url
-      this.saveStationInfo()
-      this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl()
+      this.setSupervisionUrls(url)
     }
   }
 
@@ -1245,6 +1251,7 @@ export class ChargingStation extends EventEmitter {
       stationInfoFromFile.templateHash === stationInfoFromTemplate.templateHash
     ) {
       return setChargingStationOptions(
+        this,
         { ...Constants.DEFAULT_STATION_INFO, ...stationInfoFromFile },
         options
       )
@@ -1256,6 +1263,7 @@ export class ChargingStation extends EventEmitter {
         stationInfoFromTemplate
       )
     return setChargingStationOptions(
+      this,
       { ...Constants.DEFAULT_STATION_INFO, ...stationInfoFromTemplate },
       options
     )
index 258613a3f1aa29d32e9818d17db366a9bf8bbcba..2e6f0869b114629a1132a5f249f7e72f4264d2e2 100644 (file)
@@ -335,9 +335,13 @@ export const buildConnectorsMap = (
 }
 
 export const setChargingStationOptions = (
+  chargingStation: ChargingStation,
   stationInfo: ChargingStationInfo,
   options?: ChargingStationOptions
 ): ChargingStationInfo => {
+  if (options?.supervisionUrls != null) {
+    chargingStation.setSupervisionUrls(options.supervisionUrls, false)
+  }
   if (options?.persistentConfiguration != null) {
     stationInfo.stationInfoPersistentConfiguration = options.persistentConfiguration
     stationInfo.ocppPersistentConfiguration = options.persistentConfiguration
index 6dbd879310592796529df358364c65c69f672734..ff3c5ef0fe56ed6b29d11745279dd334741a3b92 100644 (file)
@@ -12,6 +12,7 @@ import type { Statistics } from './Statistics.js'
 import { type WorkerData, type WorkerMessage, WorkerMessageEvents } from '../worker/index.js'
 
 export interface ChargingStationOptions extends JsonObject {
+  supervisionUrls?: string | string[]
   persistentConfiguration?: boolean
   autoStart?: boolean
   autoRegister?: boolean
index 276e9dd9f159b1810051a107f34552960fa4641b..d7387b233e39642f19956a7a3ac38bafa45b266f 100644 (file)
@@ -33,6 +33,7 @@ export type FirmwareStatus = OCPP16FirmwareStatus
 
 export type ChargingStationInfo = {
   hashId: string
+  templateIndex: number
   templateName: string
   chargingStationId?: string
   chargePointModel: string