refactor: improve start transaction sanity checks log messages
[e-mobility-charging-stations-simulator.git] / src / charging-station / Helpers.ts
index b722926205f0d5b949ae450a92990abfe86e971b..936c1a7d65a9136dbd11843c915f91a8d334f0b6 100644 (file)
@@ -339,6 +339,12 @@ export const initializeConnectorsMapStatus = (
 };
 
 export const resetConnectorStatus = (connectorStatus: ConnectorStatus): void => {
+  connectorStatus.chargingProfiles =
+    connectorStatus.transactionId && isNotEmptyArray(connectorStatus.chargingProfiles)
+      ? connectorStatus.chargingProfiles?.filter(
+          (chargingProfile) => chargingProfile.transactionId !== connectorStatus.transactionId,
+        )
+      : [];
   connectorStatus.idTagLocalAuthorized = false;
   connectorStatus.idTagAuthorized = false;
   connectorStatus.transactionRemoteStarted = false;
@@ -517,7 +523,7 @@ export const getAmperageLimitationUnitDivider = (stationInfo: ChargingStationInf
 
 /**
  * Gets the connector cloned charging profiles applying a power limitation
- * and sorted by connector id ascending then stack level descending
+ * and sorted by connector id descending then stack level descending
  *
  * @param chargingStation -
  * @param connectorId -
@@ -528,10 +534,10 @@ export const getConnectorChargingProfiles = (
   connectorId: number,
 ) => {
   return cloneObject<ChargingProfile[]>(
-    (chargingStation.getConnectorStatus(0)?.chargingProfiles ?? [])
+    (chargingStation.getConnectorStatus(connectorId)?.chargingProfiles ?? [])
       .sort((a, b) => b.stackLevel - a.stackLevel)
       .concat(
-        (chargingStation.getConnectorStatus(connectorId)?.chargingProfiles ?? []).sort(
+        (chargingStation.getConnectorStatus(0)?.chargingProfiles ?? []).sort(
           (a, b) => b.stackLevel - a.stackLevel,
         ),
       ),
@@ -735,7 +741,7 @@ interface ChargingProfilesLimit {
 }
 
 /**
- * Charging profiles shall already be sorted by connector id ascending then stack level descending
+ * Charging profiles shall already be sorted by connector id descending then stack level descending
  *
  * @param chargingStation -
  * @param connectorId -
@@ -761,6 +767,15 @@ const getLimitFromChargingProfiles = (
       // OCPP specifies that if startSchedule is not defined, it should be relative to start of the connector transaction
       chargingSchedule.startSchedule = connectorStatus?.transactionStart;
     }
+    if (
+      !isNullOrUndefined(chargingSchedule?.startSchedule) &&
+      !isDate(chargingSchedule?.startSchedule)
+    ) {
+      logger.warn(
+        `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} startSchedule property is not a Date instance. Trying to convert it to a Date instance`,
+      );
+      chargingSchedule.startSchedule = convertToDate(chargingSchedule?.startSchedule)!;
+    }
     if (
       !isNullOrUndefined(chargingSchedule?.startSchedule) &&
       isNullOrUndefined(chargingSchedule?.duration)
@@ -771,12 +786,6 @@ const getLimitFromChargingProfiles = (
       // OCPP specifies that if duration is not defined, it should be infinite
       chargingSchedule.duration = differenceInSeconds(maxTime, chargingSchedule.startSchedule!);
     }
-    if (!isDate(chargingSchedule?.startSchedule)) {
-      logger.warn(
-        `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} startSchedule property is not a Date object. Trying to convert it to a Date object`,
-      );
-      chargingSchedule.startSchedule = convertToDate(chargingSchedule?.startSchedule)!;
-    }
     if (!prepareChargingProfileKind(connectorStatus, chargingProfile, currentDate, logPrefix)) {
       continue;
     }
@@ -785,7 +794,6 @@ const getLimitFromChargingProfiles = (
     }
     // Check if the charging profile is active
     if (
-      isValidTime(chargingSchedule?.startSchedule) &&
       isWithinInterval(currentDate, {
         start: chargingSchedule.startSchedule!,
         end: addSeconds(chargingSchedule.startSchedule!, chargingSchedule.duration!),
@@ -891,8 +899,10 @@ export const prepareChargingProfileKind = (
         );
         delete chargingProfile.chargingSchedule.startSchedule;
       }
-      connectorStatus?.transactionStarted &&
-        (chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart);
+      if (connectorStatus?.transactionStarted) {
+        chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart;
+      }
+      // FIXME: Handle relative charging profile duration
       break;
   }
   return true;
@@ -914,10 +924,30 @@ export const canProceedChargingProfile = (
     );
     return false;
   }
-  const chargingSchedule = chargingProfile.chargingSchedule;
-  if (isNullOrUndefined(chargingSchedule?.startSchedule)) {
+  if (
+    isNullOrUndefined(chargingProfile.chargingSchedule.startSchedule) ||
+    isNullOrUndefined(chargingProfile.chargingSchedule.duration)
+  ) {
+    logger.error(
+      `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has no startSchedule or duration defined`,
+    );
+    return false;
+  }
+  if (
+    !isNullOrUndefined(chargingProfile.chargingSchedule.startSchedule) &&
+    !isValidTime(chargingProfile.chargingSchedule.startSchedule)
+  ) {
     logger.error(
-      `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has no startSchedule defined`,
+      `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has an invalid startSchedule date defined`,
+    );
+    return false;
+  }
+  if (
+    !isNullOrUndefined(chargingProfile.chargingSchedule.duration) &&
+    !Number.isSafeInteger(chargingProfile.chargingSchedule.duration)
+  ) {
+    logger.error(
+      `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has non integer duration defined`,
     );
     return false;
   }
@@ -937,6 +967,15 @@ const canProceedRecurringChargingProfile = (
     );
     return false;
   }
+  if (
+    chargingProfile.chargingProfileKind === ChargingProfileKindType.RECURRING &&
+    isNullOrUndefined(chargingProfile.chargingSchedule.startSchedule)
+  ) {
+    logger.error(
+      `${logPrefix} ${moduleName}.canProceedRecurringChargingProfile: Recurring charging profile id ${chargingProfile.chargingProfileId} has no startSchedule defined`,
+    );
+    return false;
+  }
   return true;
 };