+export const getHashId = (index: number, stationTemplate: ChargingStationTemplate): string => {
+ const chargingStationInfo = {
+ chargePointModel: stationTemplate.chargePointModel,
+ chargePointVendor: stationTemplate.chargePointVendor,
+ ...(!isUndefined(stationTemplate.chargeBoxSerialNumberPrefix) && {
+ chargeBoxSerialNumber: stationTemplate.chargeBoxSerialNumberPrefix,
+ }),
+ ...(!isUndefined(stationTemplate.chargePointSerialNumberPrefix) && {
+ chargePointSerialNumber: stationTemplate.chargePointSerialNumberPrefix,
+ }),
+ ...(!isUndefined(stationTemplate.meterSerialNumberPrefix) && {
+ meterSerialNumber: stationTemplate.meterSerialNumberPrefix,
+ }),
+ ...(!isUndefined(stationTemplate.meterType) && {
+ meterType: stationTemplate.meterType,
+ }),
+ };
+ return createHash(Constants.DEFAULT_HASH_ALGORITHM)
+ .update(`${JSON.stringify(chargingStationInfo)}${getChargingStationId(index, stationTemplate)}`)
+ .digest('hex');
+};
+
+export const checkChargingStation = (
+ chargingStation: ChargingStation,
+ logPrefix: string,
+): boolean => {
+ if (chargingStation.started === false && chargingStation.starting === false) {
+ logger.warn(`${logPrefix} charging station is stopped, cannot proceed`);
+ return false;
+ }
+ return true;
+};
+
+export const getPhaseRotationValue = (
+ connectorId: number,
+ numberOfPhases: number,
+): string | undefined => {
+ // AC/DC
+ if (connectorId === 0 && numberOfPhases === 0) {
+ return `${connectorId}.${ConnectorPhaseRotation.RST}`;
+ } else if (connectorId > 0 && numberOfPhases === 0) {
+ return `${connectorId}.${ConnectorPhaseRotation.NotApplicable}`;
+ // AC
+ } else if (connectorId > 0 && numberOfPhases === 1) {
+ return `${connectorId}.${ConnectorPhaseRotation.NotApplicable}`;
+ } else if (connectorId > 0 && numberOfPhases === 3) {
+ return `${connectorId}.${ConnectorPhaseRotation.RST}`;
+ }
+};
+
+export const getMaxNumberOfEvses = (evses: Record<string, EvseTemplate>): number => {
+ if (!evses) {
+ return -1;
+ }
+ return Object.keys(evses).length;
+};
+
+const getMaxNumberOfConnectors = (connectors: Record<string, ConnectorStatus>): number => {
+ if (!connectors) {
+ return -1;
+ }
+ return Object.keys(connectors).length;
+};
+
+export const getBootConnectorStatus = (
+ chargingStation: ChargingStation,
+ connectorId: number,
+ connectorStatus: ConnectorStatus,
+): ConnectorStatusEnum => {
+ let connectorBootStatus: ConnectorStatusEnum;
+ if (
+ !connectorStatus?.status &&
+ (chargingStation.isChargingStationAvailable() === false ||
+ chargingStation.isConnectorAvailable(connectorId) === false)
+ ) {
+ connectorBootStatus = ConnectorStatusEnum.Unavailable;
+ } else if (!connectorStatus?.status && connectorStatus?.bootStatus) {
+ // Set boot status in template at startup
+ connectorBootStatus = connectorStatus?.bootStatus;
+ } else if (connectorStatus?.status) {
+ // Set previous status at startup
+ connectorBootStatus = connectorStatus?.status;
+ } else {
+ // Set default status
+ connectorBootStatus = ConnectorStatusEnum.Available;
+ }
+ return connectorBootStatus;
+};
+
+export const checkTemplate = (
+ stationTemplate: ChargingStationTemplate,
+ logPrefix: string,
+ templateFile: string,
+): void => {
+ if (isNullOrUndefined(stationTemplate)) {
+ const errorMsg = `Failed to read charging station template file ${templateFile}`;
+ logger.error(`${logPrefix} ${errorMsg}`);
+ throw new BaseError(errorMsg);
+ }
+ if (isEmptyObject(stationTemplate)) {
+ const errorMsg = `Empty charging station information from template file ${templateFile}`;
+ logger.error(`${logPrefix} ${errorMsg}`);
+ throw new BaseError(errorMsg);
+ }
+ if (isEmptyObject(stationTemplate.AutomaticTransactionGenerator!)) {
+ stationTemplate.AutomaticTransactionGenerator = Constants.DEFAULT_ATG_CONFIGURATION;
+ logger.warn(
+ `${logPrefix} Empty automatic transaction generator configuration from template file ${templateFile}, set to default: %j`,
+ Constants.DEFAULT_ATG_CONFIGURATION,
+ );
+ }
+ if (isNullOrUndefined(stationTemplate.idTagsFile) || isEmptyString(stationTemplate.idTagsFile)) {
+ logger.warn(
+ `${logPrefix} Missing id tags file in template file ${templateFile}. That can lead to issues with the Automatic Transaction Generator`,
+ );
+ }
+};
+
+export const checkConnectorsConfiguration = (
+ stationTemplate: ChargingStationTemplate,
+ logPrefix: string,
+ templateFile: string,
+): {
+ configuredMaxConnectors: number;
+ templateMaxConnectors: number;
+ templateMaxAvailableConnectors: number;
+} => {
+ const configuredMaxConnectors = getConfiguredNumberOfConnectors(stationTemplate);
+ checkConfiguredMaxConnectors(configuredMaxConnectors, logPrefix, templateFile);
+ const templateMaxConnectors = getMaxNumberOfConnectors(stationTemplate.Connectors!);
+ checkTemplateMaxConnectors(templateMaxConnectors, logPrefix, templateFile);
+ const templateMaxAvailableConnectors = stationTemplate.Connectors![0]
+ ? templateMaxConnectors - 1
+ : templateMaxConnectors;
+ if (
+ configuredMaxConnectors > templateMaxAvailableConnectors &&
+ !stationTemplate?.randomConnectors
+ ) {
+ logger.warn(
+ `${logPrefix} Number of connectors exceeds the number of connector configurations in template ${templateFile}, forcing random connector configurations affectation`,
+ );
+ stationTemplate.randomConnectors = true;
+ }
+ return { configuredMaxConnectors, templateMaxConnectors, templateMaxAvailableConnectors };
+};
+
+export const checkStationInfoConnectorStatus = (
+ connectorId: number,
+ connectorStatus: ConnectorStatus,
+ logPrefix: string,
+ templateFile: string,
+): void => {
+ if (!isNullOrUndefined(connectorStatus?.status)) {
+ logger.warn(
+ `${logPrefix} Charging station information from template ${templateFile} with connector id ${connectorId} status configuration defined, undefine it`,
+ );
+ delete connectorStatus.status;