feat: check status notification transition in OCPP 1.6 stack
authorJérôme Benoit <jerome.benoit@sap.com>
Mon, 17 Apr 2023 21:48:42 +0000 (23:48 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Mon, 17 Apr 2023 21:48:42 +0000 (23:48 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/ocpp/1.6/OCPP16Constants.ts [new file with mode: 0644]
src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
src/charging-station/ocpp/1.6/OCPP16ResponseService.ts
src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts
src/charging-station/ocpp/OCPPConstants.ts
src/charging-station/ocpp/internal.ts
src/types/ocpp/1.6/ChargePointStatus.ts

diff --git a/src/charging-station/ocpp/1.6/OCPP16Constants.ts b/src/charging-station/ocpp/1.6/OCPP16Constants.ts
new file mode 100644 (file)
index 0000000..b0fb1ef
--- /dev/null
@@ -0,0 +1,116 @@
+import { OCPP16ChargePointStatus } from '../../../types';
+import { OCPPConstants } from '../internal';
+
+export class OCPP16Constants extends OCPPConstants {
+  static readonly OCPP16ChargePointStatusChargingStationTransition = new Set<
+    [OCPP16ChargePointStatus | undefined, OCPP16ChargePointStatus | undefined]
+  >([
+    [undefined, OCPP16ChargePointStatus.Available],
+    // [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Available],
+    [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Faulted],
+    [undefined, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Available],
+    // [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Faulted],
+    [undefined, OCPP16ChargePointStatus.Faulted],
+    [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Available],
+    [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Unavailable],
+    // [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Faulted],
+  ]);
+
+  static readonly OCPP16ChargePointStatusConnectorTransition = new Set<
+    [OCPP16ChargePointStatus | undefined, OCPP16ChargePointStatus | undefined]
+  >([
+    [undefined, OCPP16ChargePointStatus.Available],
+    // [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Available],
+    [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Preparing],
+    [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Charging],
+    [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.SuspendedEV],
+    [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.SuspendedEVSE],
+    // [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Finishing],
+    [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Reserved],
+    [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Faulted],
+    // [undefined, OCPP16ChargePointStatus.Preparing],
+    [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Available],
+    // [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Preparing],
+    [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Charging],
+    [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.SuspendedEV],
+    [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.SuspendedEVSE],
+    [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Finishing],
+    // [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Reserved],
+    // [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Faulted],
+    // [undefined, OCPP16ChargePointStatus.Charging],
+    [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Available],
+    // [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Preparing],
+    // [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Charging],
+    [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.SuspendedEV],
+    [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.SuspendedEVSE],
+    [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Finishing],
+    // [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Reserved],
+    [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Faulted],
+    // [undefined, OCPP16ChargePointStatus.SuspendedEV],
+    [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Available],
+    // [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Preparing],
+    [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Charging],
+    // [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.SuspendedEV],
+    [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.SuspendedEVSE],
+    [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Finishing],
+    // [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Reserved],
+    [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Faulted],
+    // [undefined, OCPP16ChargePointStatus.SuspendedEVSE],
+    [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Available],
+    // [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Preparing],
+    [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Charging],
+    [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.SuspendedEV],
+    // [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.SuspendedEVSE],
+    [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Finishing],
+    // [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Reserved],
+    [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Faulted],
+    // [undefined, OCPP16ChargePointStatus.Finishing],
+    [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Available],
+    [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Preparing],
+    // [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Charging],
+    // [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.SuspendedEV],
+    // [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.SuspendedEVSE],
+    // [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Finishing],
+    // [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Reserved],
+    [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Faulted],
+    // [undefined, OCPP16ChargePointStatus.Reserved],
+    [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Available],
+    [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Preparing],
+    // [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Charging],
+    // [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.SuspendedEV],
+    // [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.SuspendedEVSE],
+    // [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Finishing],
+    // [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Reserved],
+    [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Faulted],
+    [undefined, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Available],
+    [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Preparing],
+    [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Charging],
+    [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.SuspendedEV],
+    [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.SuspendedEVSE],
+    // [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Finishing],
+    // [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Reserved],
+    // [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Unavailable],
+    [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Faulted],
+    [undefined, OCPP16ChargePointStatus.Faulted],
+    [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Available],
+    [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Preparing],
+    [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Charging],
+    [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.SuspendedEV],
+    [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.SuspendedEVSE],
+    [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Finishing],
+    [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Reserved],
+    [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Unavailable],
+    // [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Faulted],
+  ]);
+}
index a3aced78aec9289e929e3d71abae9823c116fdae..49ed8c92ae99ffd93fb4495d4fb916c8c73da925 100644 (file)
@@ -416,15 +416,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       }
       return OCPPConstants.OCPP_RESPONSE_UNLOCK_FAILED;
     }
-    await chargingStation.ocppRequestService.requestHandler<
-      OCPP16StatusNotificationRequest,
-      OCPP16StatusNotificationResponse
-    >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
+    await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+      chargingStation,
       connectorId,
-      status: OCPP16ChargePointStatus.Available,
-      errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-    });
-    chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.Available;
+      OCPP16ChargePointStatus.Available
+    );
     return OCPPConstants.OCPP_RESPONSE_UNLOCKED;
   }
 
@@ -744,15 +740,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         }
         chargingStation.getConnectorStatus(id).availability = commandPayload.type;
         if (response === OCPPConstants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED) {
-          await chargingStation.ocppRequestService.requestHandler<
-            OCPP16StatusNotificationRequest,
-            OCPP16StatusNotificationResponse
-          >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
-            connectorId: id,
-            status: chargePointStatus,
-            errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-          });
-          chargingStation.getConnectorStatus(id).status = chargePointStatus;
+          await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+            chargingStation,
+            id,
+            chargePointStatus
+          );
         }
       }
       return response;
@@ -767,15 +759,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         return OCPPConstants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
       }
       chargingStation.getConnectorStatus(connectorId).availability = commandPayload.type;
-      await chargingStation.ocppRequestService.requestHandler<
-        OCPP16StatusNotificationRequest,
-        OCPP16StatusNotificationResponse
-      >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
+      await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+        chargingStation,
         connectorId,
-        status: chargePointStatus,
-        errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-      });
-      chargingStation.getConnectorStatus(connectorId).status = chargePointStatus;
+        chargePointStatus
+      );
       return OCPPConstants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
     }
     return OCPPConstants.OCPP_AVAILABILITY_RESPONSE_REJECTED;
@@ -790,16 +778,12 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       const remoteStartTransactionLogMsg = `${chargingStation.logPrefix()} Transaction remotely STARTED on ${
         chargingStation.stationInfo.chargingStationId
       }#${transactionConnectorId.toString()} for idTag '${commandPayload.idTag}'`;
-      await chargingStation.ocppRequestService.requestHandler<
-        OCPP16StatusNotificationRequest,
-        OCPP16StatusNotificationResponse
-      >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
-        connectorId: transactionConnectorId,
-        status: OCPP16ChargePointStatus.Preparing,
-        errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-      });
+      await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+        chargingStation,
+        transactionConnectorId,
+        OCPP16ChargePointStatus.Preparing
+      );
       const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId);
-      connectorStatus.status = OCPP16ChargePointStatus.Preparing;
       if (
         chargingStation.isChargingStationAvailable() === true &&
         chargingStation.isConnectorAvailable(transactionConnectorId) === true
@@ -934,15 +918,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
     if (
       chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.Available
     ) {
-      await chargingStation.ocppRequestService.requestHandler<
-        OCPP16StatusNotificationRequest,
-        OCPP16StatusNotificationResponse
-      >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
+      await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+        chargingStation,
         connectorId,
-        status: OCPP16ChargePointStatus.Available,
-        errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-      });
-      chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.Available;
+        OCPP16ChargePointStatus.Available
+      );
     }
     logger.warn(
       `${chargingStation.logPrefix()} Remote starting transaction REJECTED on connector Id ${connectorId.toString()}, idTag '${idTag}', availability '${
@@ -986,15 +966,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         connectorId > 0 &&
         chargingStation.getConnectorStatus(connectorId)?.transactionId === transactionId
       ) {
-        await chargingStation.ocppRequestService.requestHandler<
-          OCPP16StatusNotificationRequest,
-          OCPP16StatusNotificationResponse
-        >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
+        await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+          chargingStation,
           connectorId,
-          status: OCPP16ChargePointStatus.Finishing,
-          errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-        });
-        chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.Finishing;
+          OCPP16ChargePointStatus.Finishing
+        );
         const stopResponse = await chargingStation.stopTransactionOnConnector(
           connectorId,
           OCPP16StopTransactionReason.REMOTE
@@ -1071,16 +1047,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         connectorId > 0 &&
         chargingStation.getConnectorStatus(connectorId)?.transactionStarted === false
       ) {
-        await chargingStation.ocppRequestService.requestHandler<
-          OCPP16StatusNotificationRequest,
-          OCPP16StatusNotificationResponse
-        >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
+        await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+          chargingStation,
           connectorId,
-          status: OCPP16ChargePointStatus.Unavailable,
-          errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-        });
-        chargingStation.getConnectorStatus(connectorId).status =
-          OCPP16ChargePointStatus.Unavailable;
+          OCPP16ChargePointStatus.Unavailable
+        );
       }
     }
     await chargingStation.ocppRequestService.requestHandler<
@@ -1142,16 +1113,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
             chargingStation.getConnectorStatus(connectorId)?.status !==
               OCPP16ChargePointStatus.Unavailable
           ) {
-            await chargingStation.ocppRequestService.requestHandler<
-              OCPP16StatusNotificationRequest,
-              OCPP16StatusNotificationResponse
-            >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
+            await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+              chargingStation,
               connectorId,
-              status: OCPP16ChargePointStatus.Unavailable,
-              errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-            });
-            chargingStation.getConnectorStatus(connectorId).status =
-              OCPP16ChargePointStatus.Unavailable;
+              OCPP16ChargePointStatus.Unavailable
+            );
           }
         }
         transactionsStarted = false;
index 2a86135dd78923f335d25fd850274ab25aedeed0..36eecc577cdbfddd3ba1ea2484e23075f95809cb 100644 (file)
@@ -17,9 +17,7 @@ import {
   OCPP16AuthorizationStatus,
   type OCPP16AuthorizeRequest,
   type OCPP16AuthorizeResponse,
-  type OCPP16BootNotificationRequest,
   type OCPP16BootNotificationResponse,
-  OCPP16ChargePointErrorCode,
   OCPP16ChargePointStatus,
   type OCPP16DataTransferResponse,
   type OCPP16DiagnosticsStatusNotificationResponse,
@@ -33,7 +31,6 @@ import {
   OCPP16StandardParametersKey,
   type OCPP16StartTransactionRequest,
   type OCPP16StartTransactionResponse,
-  type OCPP16StatusNotificationRequest,
   type OCPP16StatusNotificationResponse,
   type OCPP16StopTransactionRequest,
   type OCPP16StopTransactionResponse,
@@ -558,15 +555,11 @@ export class OCPP16ResponseService extends OCPPResponseService {
           transactionId: payload.transactionId,
           meterValue: [chargingStation.getConnectorStatus(connectorId).transactionBeginMeterValue],
         }));
-      await chargingStation.ocppRequestService.requestHandler<
-        OCPP16StatusNotificationRequest,
-        OCPP16StatusNotificationResponse
-      >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
+      await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+        chargingStation,
         connectorId,
-        status: OCPP16ChargePointStatus.Charging,
-        errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-      });
-      chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.Charging;
+        OCPP16ChargePointStatus.Charging
+      );
       logger.info(
         `${chargingStation.logPrefix()} Transaction ${payload.transactionId.toString()} STARTED on ${
           chargingStation.stationInfo.chargingStationId
@@ -604,15 +597,11 @@ export class OCPP16ResponseService extends OCPPResponseService {
     if (
       chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.Available
     ) {
-      await chargingStation.ocppRequestService.requestHandler<
-        OCPP16StatusNotificationRequest,
-        OCPP16StatusNotificationResponse
-      >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
+      await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+        chargingStation,
         connectorId,
-        status: OCPP16ChargePointStatus.Available,
-        errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-      });
-      chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.Available;
+        OCPP16ChargePointStatus.Available
+      );
     }
   }
 
@@ -651,27 +640,17 @@ export class OCPP16ResponseService extends OCPPResponseService {
       chargingStation.isChargingStationAvailable() === false ||
       chargingStation.isConnectorAvailable(transactionConnectorId) === false
     ) {
-      await chargingStation.ocppRequestService.requestHandler<
-        OCPP16StatusNotificationRequest,
-        OCPP16StatusNotificationResponse
-      >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
-        connectorId: transactionConnectorId,
-        status: OCPP16ChargePointStatus.Unavailable,
-        errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-      });
-      chargingStation.getConnectorStatus(transactionConnectorId).status =
-        OCPP16ChargePointStatus.Unavailable;
+      await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+        chargingStation,
+        transactionConnectorId,
+        OCPP16ChargePointStatus.Unavailable
+      );
     } else {
-      await chargingStation.ocppRequestService.requestHandler<
-        OCPP16BootNotificationRequest,
-        OCPP16BootNotificationResponse
-      >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
-        connectorId: transactionConnectorId,
-        status: OCPP16ChargePointStatus.Available,
-        errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
-      });
-      chargingStation.getConnectorStatus(transactionConnectorId).status =
-        OCPP16ChargePointStatus.Available;
+      await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+        chargingStation,
+        transactionConnectorId,
+        OCPP16ChargePointStatus.Available
+      );
     }
     if (chargingStation.stationInfo.powerSharedByConnectors) {
       chargingStation.powerDivider--;
index 932d4515f6d0fcc7d0c259f3fe8ff000e11423ed..47c711af16fa7f5ba300bd51ab620b20f147188c 100644 (file)
@@ -16,6 +16,8 @@ import {
   MeterValueContext,
   MeterValueLocation,
   MeterValueUnit,
+  OCPP16ChargePointErrorCode,
+  type OCPP16ChargePointStatus,
   type OCPP16ChargingProfile,
   type OCPP16IncomingRequestCommand,
   type OCPP16MeterValue,
@@ -24,13 +26,15 @@ import {
   OCPP16RequestCommand,
   type OCPP16SampledValue,
   OCPP16StandardParametersKey,
+  type OCPP16StatusNotificationRequest,
+  type OCPP16StatusNotificationResponse,
   type OCPP16SupportedFeatureProfiles,
   OCPPVersion,
   type SampledValueTemplate,
   Voltage,
 } from '../../../types';
 import { ACElectricUtils, Constants, DCElectricUtils, Utils, logger } from '../../../utils';
-import { OCPPServiceUtils } from '../internal';
+import { OCPP16Constants, OCPPServiceUtils } from '../internal';
 
 export class OCPP16ServiceUtils extends OCPPServiceUtils {
   public static checkFeatureProfile(
@@ -840,6 +844,55 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     );
   }
 
+  public static async sendAndSetConnectorStatus(
+    chargingStation: ChargingStation,
+    connectorId: number,
+    status: OCPP16ChargePointStatus,
+    errorCode: OCPP16ChargePointErrorCode = OCPP16ChargePointErrorCode.NO_ERROR
+  ) {
+    OCPP16ServiceUtils.checkConnectorStatusTransition(chargingStation, connectorId, status);
+    await chargingStation.ocppRequestService.requestHandler<
+      OCPP16StatusNotificationRequest,
+      OCPP16StatusNotificationResponse
+    >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
+      connectorId,
+      status,
+      errorCode,
+    });
+    chargingStation.getConnectorStatus(connectorId).status = status;
+  }
+
+  private static checkConnectorStatusTransition(
+    chargingStation: ChargingStation,
+    connectorId: number,
+    status: OCPP16ChargePointStatus
+  ): void {
+    if (
+      connectorId === 0 &&
+      !OCPP16Constants.OCPP16ChargePointStatusChargingStationTransition.has([
+        chargingStation.getConnectorStatus(connectorId).status as OCPP16ChargePointStatus,
+        status,
+      ])
+    ) {
+      logger.warn(
+        `${chargingStation.logPrefix()} Connector ${connectorId} status transition from ${
+          chargingStation.getConnectorStatus(connectorId).status
+        } to ${status} is not allowed`
+      );
+    } else if (
+      !OCPP16Constants.OCPP16ChargePointStatusConnectorTransition.has([
+        chargingStation.getConnectorStatus(connectorId).status as OCPP16ChargePointStatus,
+        status,
+      ])
+    ) {
+      logger.warn(
+        `${chargingStation.logPrefix()} Connector ${connectorId} status transition from ${
+          chargingStation.getConnectorStatus(connectorId).status
+        } to ${status} is not allowed`
+      );
+    }
+  }
+
   private static buildSampledValue(
     sampledValueTemplate: SampledValueTemplate,
     value: number,
index c8b110e4262131d4ea33f6332cbe65766f53ff70..2da9345563936f545fef5089abd373bc00ebd2a3 100644 (file)
@@ -89,7 +89,7 @@ export class OCPPConstants {
     status: DataTransferStatus.REJECTED,
   });
 
-  private constructor() {
+  protected constructor() {
     // This is intentional
   }
 }
index c8755707f7fadf78f77fd0ecdded32ff37590ae8..c7f0fe728a2e10cc3ce66c8d7a3914f68f4014a4 100644 (file)
@@ -1,3 +1,4 @@
+export * from './1.6/OCPP16Constants';
 export * from './1.6/OCPP16IncomingRequestService';
 export * from './1.6/OCPP16RequestService';
 export * from './1.6/OCPP16ResponseService';
index d7a197ae0f4c32307b296986bc0e140920f1aeb7..4cef943e712f797ec4e3c3d6ba88c446e0ff7eb6 100644 (file)
@@ -2,7 +2,6 @@ export enum OCPP16ChargePointStatus {
   Available = 'Available',
   Preparing = 'Preparing',
   Charging = 'Charging',
-  Occupied = 'Occupied',
   SuspendedEVSE = 'SuspendedEVSE',
   SuspendedEV = 'SuspendedEV',
   Finishing = 'Finishing',