X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2FHelpers.ts;h=05773f0159f3f1378dd78af4cf2a46ac3395b373;hb=ad490d5f65e55103448a5c933cf9ea1ae4f512a5;hp=6cd270ffee29855891f0d79a6565af6547283c85;hpb=cfdf901dfbdf4cf745a1ced9b7870251cb9c6f10;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/Helpers.ts b/src/charging-station/Helpers.ts index 6cd270ff..05773f01 100644 --- a/src/charging-station/Helpers.ts +++ b/src/charging-station/Helpers.ts @@ -14,6 +14,7 @@ import { isAfter, isBefore, isDate, + isPast, isWithinInterval, toDate, } from 'date-fns'; @@ -42,6 +43,8 @@ import { type OCPP20BootNotificationRequest, OCPPVersion, RecurrencyKindType, + type Reservation, + ReservationTerminationReason, StandardParametersKey, SupportedFeatureProfiles, Voltage, @@ -82,17 +85,49 @@ export const getChargingStationId = ( )}${idSuffix}`; }; -export const countReservableConnectors = (connectors: Map) => { - let reservableConnectors = 0; +export const hasReservationExpired = (reservation: Reservation): boolean => { + return isPast(reservation.expiryDate); +}; + +export const removeExpiredReservations = async ( + chargingStation: ChargingStation, +): Promise => { + if (chargingStation.hasEvses) { + for (const evseStatus of chargingStation.evses.values()) { + for (const connectorStatus of evseStatus.connectors.values()) { + if (connectorStatus.reservation && hasReservationExpired(connectorStatus.reservation)) { + await chargingStation.removeReservation( + connectorStatus.reservation, + ReservationTerminationReason.EXPIRED, + ); + } + } + } + } else { + for (const connectorStatus of chargingStation.connectors.values()) { + if (connectorStatus.reservation && hasReservationExpired(connectorStatus.reservation)) { + await chargingStation.removeReservation( + connectorStatus.reservation, + ReservationTerminationReason.EXPIRED, + ); + } + } + } +}; + +export const getNumberOfReservableConnectors = ( + connectors: Map, +): number => { + let numberOfReservableConnectors = 0; for (const [connectorId, connectorStatus] of connectors) { if (connectorId === 0) { continue; } if (connectorStatus.status === ConnectorStatusEnum.Available) { - ++reservableConnectors; + ++numberOfReservableConnectors; } } - return reservableConnectors; + return numberOfReservableConnectors; }; export const getHashId = (index: number, stationTemplate: ChargingStationTemplate): string => { @@ -222,7 +257,7 @@ export const checkConnectorsConfiguration = ( templateMaxConnectors: number; templateMaxAvailableConnectors: number; } => { - const configuredMaxConnectors = getConfiguredNumberOfConnectors(stationTemplate); + const configuredMaxConnectors = getConfiguredMaxNumberOfConnectors(stationTemplate); checkConfiguredMaxConnectors(configuredMaxConnectors, logPrefix, templateFile); const templateMaxConnectors = getMaxNumberOfConnectors(stationTemplate.Connectors!); checkTemplateMaxConnectors(templateMaxConnectors, logPrefix, templateFile); @@ -485,18 +520,11 @@ export const getChargingStationConnectorChargingProfilesPowerLimit = ( ): number | undefined => { let limit: number | undefined, matchingChargingProfile: ChargingProfile | undefined; // Get charging profiles for connector id and sort by stack level - const chargingProfiles = - cloneObject( - chargingStation.getConnectorStatus(connectorId)!.chargingProfiles!, - )?.sort((a, b) => b.stackLevel - a.stackLevel) ?? []; - // Get charging profiles on connector 0 and sort by stack level - if (isNotEmptyArray(chargingStation.getConnectorStatus(0)?.chargingProfiles)) { - chargingProfiles.push( - ...cloneObject( - chargingStation.getConnectorStatus(0)!.chargingProfiles!, - ).sort((a, b) => b.stackLevel - a.stackLevel), - ); - } + const chargingProfiles = cloneObject( + (chargingStation.getConnectorStatus(connectorId)?.chargingProfiles ?? []).concat( + chargingStation.getConnectorStatus(0)?.chargingProfiles ?? [], + ), + ).sort((a, b) => b.stackLevel - a.stackLevel); if (isNotEmptyArray(chargingProfiles)) { const result = getLimitFromChargingProfiles( chargingStation, @@ -587,16 +615,16 @@ export const waitChargingStationEvents = async ( }); }; -const getConfiguredNumberOfConnectors = (stationTemplate: ChargingStationTemplate): number => { - let configuredMaxConnectors = 0; +const getConfiguredMaxNumberOfConnectors = (stationTemplate: ChargingStationTemplate): number => { + let configuredMaxNumberOfConnectors = 0; if (isNotEmptyArray(stationTemplate.numberOfConnectors) === true) { const numberOfConnectors = stationTemplate.numberOfConnectors as number[]; - configuredMaxConnectors = + configuredMaxNumberOfConnectors = numberOfConnectors[Math.floor(secureRandom() * numberOfConnectors.length)]; } else if (isUndefined(stationTemplate.numberOfConnectors) === false) { - configuredMaxConnectors = stationTemplate.numberOfConnectors as number; + configuredMaxNumberOfConnectors = stationTemplate.numberOfConnectors as number; } else if (stationTemplate.Connectors && !stationTemplate.Evses) { - configuredMaxConnectors = stationTemplate.Connectors[0] + configuredMaxNumberOfConnectors = stationTemplate.Connectors[0] ? getMaxNumberOfConnectors(stationTemplate.Connectors) - 1 : getMaxNumberOfConnectors(stationTemplate.Connectors); } else if (stationTemplate.Evses && !stationTemplate.Connectors) { @@ -604,10 +632,12 @@ const getConfiguredNumberOfConnectors = (stationTemplate: ChargingStationTemplat if (evse === '0') { continue; } - configuredMaxConnectors += getMaxNumberOfConnectors(stationTemplate.Evses[evse].Connectors); + configuredMaxNumberOfConnectors += getMaxNumberOfConnectors( + stationTemplate.Evses[evse].Connectors, + ); } } - return configuredMaxConnectors; + return configuredMaxNumberOfConnectors; }; const checkConfiguredMaxConnectors = ( @@ -704,6 +734,12 @@ const getLimitFromChargingProfiles = ( const debugLogMsg = `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Matching charging profile found for power limitation: %j`; const currentDate = new Date(); const connectorStatus = chargingStation.getConnectorStatus(connectorId); + if (!isArraySorted(chargingProfiles, (a, b) => b.stackLevel - a.stackLevel)) { + logger.warn( + `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profiles are not sorted by stack level. Trying to sort them`, + ); + chargingProfiles.sort((a, b) => b.stackLevel - a.stackLevel); + } for (const chargingProfile of chargingProfiles) { const chargingSchedule = chargingProfile.chargingSchedule; if (connectorStatus?.transactionStarted && isNullOrUndefined(chargingSchedule?.startSchedule)) { @@ -823,7 +859,7 @@ const getLimitFromChargingProfiles = ( } }; -const canProceedChargingProfile = ( +export const canProceedChargingProfile = ( chargingProfile: ChargingProfile, currentDate: Date, logPrefix: string, @@ -842,7 +878,7 @@ const canProceedChargingProfile = ( const chargingSchedule = chargingProfile.chargingSchedule; if (isNullOrUndefined(chargingSchedule?.startSchedule)) { logger.error( - `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has (still) no startSchedule defined`, + `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has no startSchedule defined`, ); return false; } @@ -855,7 +891,7 @@ const canProceedChargingProfile = ( return true; }; -const canProceedRecurringChargingProfile = ( +export const canProceedRecurringChargingProfile = ( chargingProfile: ChargingProfile, logPrefix: string, ): boolean => { @@ -878,7 +914,7 @@ const canProceedRecurringChargingProfile = ( * @param currentDate - * @param logPrefix - */ -const prepareRecurringChargingProfile = ( +export const prepareRecurringChargingProfile = ( chargingProfile: ChargingProfile, currentDate: Date, logPrefix: string,