]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
fix: ensure CS in pending state can send boot notification (#1376)
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Tue, 8 Apr 2025 09:22:10 +0000 (11:22 +0200)
committerGitHub <noreply@github.com>
Tue, 8 Apr 2025 09:22:10 +0000 (11:22 +0200)
* fix: ensure CS in pending state can send boot notification

closes #1374

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
* fix: proper CS state conditions

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
---------

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
src/charging-station/ChargingStation.ts
src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
src/charging-station/ocpp/1.6/OCPP16ResponseService.ts
src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.ts
src/charging-station/ocpp/2.0/OCPP20ResponseService.ts
src/charging-station/ocpp/OCPPRequestService.ts
src/types/ChargingStationEvents.ts

index f2f8bc2d04a6beea01a7a8171ed004190ac25707..8a66d31a6bad605f4c33b74b42ffc80524c1e062 100644 (file)
@@ -646,10 +646,6 @@ export class ChargingStation extends EventEmitter {
     return false
   }
 
-  public isRegistered (): boolean {
-    return !this.inUnknownState() && (this.inAcceptedState() || this.inPendingState())
-  }
-
   public isWebSocketConnectionOpened (): boolean {
     return this.wsConnection?.readyState === WebSocket.OPEN
   }
@@ -2087,7 +2083,7 @@ export class ChargingStation extends EventEmitter {
         } succeeded`
       )
       let registrationRetryCount = 0
-      if (!this.isRegistered()) {
+      if (!this.inAcceptedState()) {
         // Send BootNotification
         do {
           await this.ocppRequestService.requestHandler<
@@ -2100,22 +2096,25 @@ export class ChargingStation extends EventEmitter {
           this.bootNotificationResponse!.currentTime = convertToDate(
             this.bootNotificationResponse?.currentTime
           )!
-          if (!this.isRegistered()) {
-            this.stationInfo?.registrationMaxRetries !== -1 && ++registrationRetryCount
+          if (!this.inAcceptedState()) {
+            ++registrationRetryCount
             await sleep(
-              this.bootNotificationResponse?.interval != null
-                ? secondsToMilliseconds(this.bootNotificationResponse.interval)
-                : Constants.DEFAULT_BOOT_NOTIFICATION_INTERVAL
+              exponentialDelay(
+                registrationRetryCount,
+                this.bootNotificationResponse?.interval != null
+                  ? secondsToMilliseconds(this.bootNotificationResponse.interval)
+                  : Constants.DEFAULT_BOOT_NOTIFICATION_INTERVAL
+              )
             )
           }
         } while (
-          !this.isRegistered() &&
-          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-          (registrationRetryCount <= this.stationInfo!.registrationMaxRetries! ||
-            this.stationInfo?.registrationMaxRetries === -1)
+          !this.inAcceptedState() &&
+          (this.stationInfo?.registrationMaxRetries === -1 ||
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+            registrationRetryCount <= this.stationInfo!.registrationMaxRetries!)
         )
       }
-      if (!this.isRegistered()) {
+      if (!this.inAcceptedState()) {
         logger.error(
           // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
           `${this.logPrefix()} Registration failure: maximum retries reached (${registrationRetryCount.toString()}) or retry disabled (${this.stationInfo?.registrationMaxRetries?.toString()})`
@@ -2139,9 +2138,9 @@ export class ChargingStation extends EventEmitter {
 
   private async reconnect (): Promise<void> {
     if (
+      this.stationInfo?.autoReconnectMaxRetries === -1 ||
       // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      this.wsConnectionRetryCount < this.stationInfo!.autoReconnectMaxRetries! ||
-      this.stationInfo?.autoReconnectMaxRetries === -1
+      this.wsConnectionRetryCount < this.stationInfo!.autoReconnectMaxRetries!
     ) {
       ++this.wsConnectionRetryCount
       const reconnectDelay =
index 91b45b13b0a81f3ec4806b4648ad55fee1f3750d..6ecf4fe84afd8a6f1e78e0438059553c3729537f 100644 (file)
@@ -597,7 +597,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       )
     }
     if (
-      chargingStation.isRegistered() ||
+      chargingStation.inAcceptedState() ||
+      chargingStation.inPendingState() ||
       (chargingStation.stationInfo?.ocppStrictCompliance === false &&
         chargingStation.inUnknownState())
     ) {
index bac3f9fa9605cc72fca53c1bd786092ada849feb..3666d04842877d15ba69cd4b73037fd575c4d667 100644 (file)
@@ -386,7 +386,13 @@ export class OCPP16ResponseService extends OCPPResponseService {
     payload: ResType,
     requestPayload: ReqType
   ): Promise<void> {
-    if (chargingStation.isRegistered() || commandName === OCPP16RequestCommand.BOOT_NOTIFICATION) {
+    if (
+      chargingStation.inAcceptedState() ||
+      ((chargingStation.inUnknownState() || chargingStation.inPendingState()) &&
+        commandName === OCPP16RequestCommand.BOOT_NOTIFICATION) ||
+      (chargingStation.stationInfo?.ocppStrictCompliance === false &&
+        (chargingStation.inUnknownState() || chargingStation.inPendingState()))
+    ) {
       if (
         this.responseHandlers.has(commandName) &&
         OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName)
@@ -502,25 +508,24 @@ export class OCPP16ResponseService extends OCPPResponseService {
   ): void {
     if (Object.values(RegistrationStatusEnumType).includes(payload.status)) {
       chargingStation.bootNotificationResponse = payload
-      if (chargingStation.isRegistered()) {
-        chargingStation.emit(ChargingStationEvents.registered)
-        if (chargingStation.inAcceptedState()) {
-          addConfigurationKey(
-            chargingStation,
-            OCPP16StandardParametersKey.HeartbeatInterval,
-            payload.interval.toString(),
-            {},
-            { overwrite: true, save: true }
-          )
-          addConfigurationKey(
-            chargingStation,
-            OCPP16StandardParametersKey.HeartBeatInterval,
-            payload.interval.toString(),
-            { visible: false },
-            { overwrite: true, save: true }
-          )
-          chargingStation.emit(ChargingStationEvents.accepted)
-        }
+      if (chargingStation.inAcceptedState()) {
+        addConfigurationKey(
+          chargingStation,
+          OCPP16StandardParametersKey.HeartbeatInterval,
+          payload.interval.toString(),
+          {},
+          { overwrite: true, save: true }
+        )
+        addConfigurationKey(
+          chargingStation,
+          OCPP16StandardParametersKey.HeartBeatInterval,
+          payload.interval.toString(),
+          { visible: false },
+          { overwrite: true, save: true }
+        )
+        chargingStation.emit(ChargingStationEvents.accepted)
+      } else if (chargingStation.inPendingState()) {
+        chargingStation.emit(ChargingStationEvents.pending)
       } else if (chargingStation.inRejectedState()) {
         chargingStation.emit(ChargingStationEvents.rejected)
       }
index 39075970b7d29639d698e95cbb3562468e816893..3be92e9e863af639aeab6f2cd73b93c1a16cfef5 100644 (file)
@@ -79,7 +79,8 @@ export class OCPP20IncomingRequestService extends OCPPIncomingRequestService {
       )
     }
     if (
-      chargingStation.isRegistered() ||
+      chargingStation.inAcceptedState() ||
+      chargingStation.inPendingState() ||
       (chargingStation.stationInfo?.ocppStrictCompliance === false &&
         chargingStation.inUnknownState())
     ) {
index 0b0c32a7b7b19ea82c6f50f4d2bdb0932933f558..be63f14aeef3cb23e50cdd7ba46ae9bc45f958a1 100644 (file)
@@ -104,7 +104,13 @@ export class OCPP20ResponseService extends OCPPResponseService {
     payload: ResType,
     requestPayload: ReqType
   ): Promise<void> {
-    if (chargingStation.isRegistered() || commandName === OCPP20RequestCommand.BOOT_NOTIFICATION) {
+    if (
+      chargingStation.inAcceptedState() ||
+      ((chargingStation.inUnknownState() || chargingStation.inPendingState()) &&
+        commandName === OCPP20RequestCommand.BOOT_NOTIFICATION) ||
+      (chargingStation.stationInfo?.ocppStrictCompliance === false &&
+        (chargingStation.inUnknownState() || chargingStation.inPendingState()))
+    ) {
       if (
         this.responseHandlers.has(commandName) &&
         OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName)
@@ -164,18 +170,17 @@ export class OCPP20ResponseService extends OCPPResponseService {
   ): void {
     if (Object.values(RegistrationStatusEnumType).includes(payload.status)) {
       chargingStation.bootNotificationResponse = payload
-      if (chargingStation.isRegistered()) {
-        chargingStation.emit(ChargingStationEvents.registered)
-        if (chargingStation.inAcceptedState()) {
-          addConfigurationKey(
-            chargingStation,
-            OCPP20OptionalVariableName.HeartbeatInterval,
-            payload.interval.toString(),
-            {},
-            { overwrite: true, save: true }
-          )
-          chargingStation.emit(ChargingStationEvents.accepted)
-        }
+      if (chargingStation.inAcceptedState()) {
+        addConfigurationKey(
+          chargingStation,
+          OCPP20OptionalVariableName.HeartbeatInterval,
+          payload.interval.toString(),
+          {},
+          { overwrite: true, save: true }
+        )
+        chargingStation.emit(ChargingStationEvents.accepted)
+      } else if (chargingStation.inPendingState()) {
+        chargingStation.emit(ChargingStationEvents.pending)
       } else if (chargingStation.inRejectedState()) {
         chargingStation.emit(ChargingStationEvents.rejected)
       }
index 88f03de92b09c1b8255d62488b2e84f68820a744..d847a6e8de120c78bd4c47e3a275df33af3e5550 100644 (file)
@@ -243,9 +243,10 @@ export abstract class OCPPRequestService {
       ...params,
     }
     if (
-      (chargingStation.inUnknownState() && commandName === RequestCommand.BOOT_NOTIFICATION) ||
+      ((chargingStation.inUnknownState() || chargingStation.inPendingState()) &&
+        commandName === RequestCommand.BOOT_NOTIFICATION) ||
       (chargingStation.stationInfo?.ocppStrictCompliance === false &&
-        chargingStation.inUnknownState()) ||
+        (chargingStation.inUnknownState() || chargingStation.inPendingState())) ||
       chargingStation.inAcceptedState() ||
       (chargingStation.inPendingState() &&
         (params.triggerMessage === true || messageType === MessageType.CALL_RESULT_MESSAGE))
index b1d27038f885484d942f30e5f3f4a157474eb78c..305b84a837fa4791923f30863d8c2e0f1306e5b8 100644 (file)
@@ -5,7 +5,7 @@ export enum ChargingStationEvents {
   connectorStatusChanged = 'connectorStatusChanged',
   deleted = 'deleted',
   disconnected = 'disconnected',
-  registered = 'registered',
+  pending = 'pending',
   rejected = 'rejected',
   started = 'started',
   stopped = 'stopped',