+ if (
+ !ChargingStationConfigurationUtils.getConfigurationKey(
+ this,
+ StandardParametersKey.ConnectorPhaseRotation
+ )
+ ) {
+ const connectorPhaseRotation = [];
+ for (const connectorId of this.connectors.keys()) {
+ // AC/DC
+ if (connectorId === 0 && this.getNumberOfPhases() === 0) {
+ connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.RST}`);
+ } else if (connectorId > 0 && this.getNumberOfPhases() === 0) {
+ connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.NotApplicable}`);
+ // AC
+ } else if (connectorId > 0 && this.getNumberOfPhases() === 1) {
+ connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.NotApplicable}`);
+ } else if (connectorId > 0 && this.getNumberOfPhases() === 3) {
+ connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.RST}`);
+ }
+ }
+ ChargingStationConfigurationUtils.addConfigurationKey(
+ this,
+ StandardParametersKey.ConnectorPhaseRotation,
+ connectorPhaseRotation.toString()
+ );
+ }
+ if (
+ !ChargingStationConfigurationUtils.getConfigurationKey(
+ this,
+ StandardParametersKey.AuthorizeRemoteTxRequests
+ )
+ ) {
+ ChargingStationConfigurationUtils.addConfigurationKey(
+ this,
+ StandardParametersKey.AuthorizeRemoteTxRequests,
+ 'true'
+ );
+ }
+ if (
+ !ChargingStationConfigurationUtils.getConfigurationKey(
+ this,
+ StandardParametersKey.LocalAuthListEnabled
+ ) &&
+ ChargingStationConfigurationUtils.getConfigurationKey(
+ this,
+ StandardParametersKey.SupportedFeatureProfiles
+ )?.value.includes(SupportedFeatureProfiles.LocalAuthListManagement)
+ ) {
+ ChargingStationConfigurationUtils.addConfigurationKey(
+ this,
+ StandardParametersKey.LocalAuthListEnabled,
+ 'false'
+ );
+ }
+ if (
+ !ChargingStationConfigurationUtils.getConfigurationKey(
+ this,
+ StandardParametersKey.ConnectionTimeOut
+ )
+ ) {
+ ChargingStationConfigurationUtils.addConfigurationKey(
+ this,
+ StandardParametersKey.ConnectionTimeOut,
+ Constants.DEFAULT_CONNECTION_TIMEOUT.toString()
+ );
+ }
+ this.saveOcppConfiguration();
+ }
+
+ private initializeConnectors(
+ stationInfo: ChargingStationInfo,
+ configuredMaxConnectors: number,
+ templateMaxConnectors: number
+ ): void {
+ if (!stationInfo?.Connectors && this.connectors.size === 0) {
+ const logMsg = `No already defined connectors and charging station information from template ${this.templateFile} with no connectors configuration defined`;
+ logger.error(`${this.logPrefix()} ${logMsg}`);
+ throw new BaseError(logMsg);
+ }
+ if (!stationInfo?.Connectors[0]) {
+ logger.warn(
+ `${this.logPrefix()} Charging station information from template ${
+ this.templateFile
+ } with no connector Id 0 configuration`
+ );
+ }
+ if (stationInfo?.Connectors) {
+ const connectorsConfigHash = crypto
+ .createHash(Constants.DEFAULT_HASH_ALGORITHM)
+ .update(JSON.stringify(stationInfo?.Connectors) + configuredMaxConnectors.toString())
+ .digest('hex');
+ const connectorsConfigChanged =
+ this.connectors?.size !== 0 && this.connectorsConfigurationHash !== connectorsConfigHash;
+ if (this.connectors?.size === 0 || connectorsConfigChanged) {
+ connectorsConfigChanged && this.connectors.clear();
+ this.connectorsConfigurationHash = connectorsConfigHash;
+ // Add connector Id 0
+ let lastConnector = '0';
+ for (lastConnector in stationInfo?.Connectors) {
+ const connectorStatus = stationInfo?.Connectors[lastConnector];
+ const lastConnectorId = Utils.convertToInt(lastConnector);
+ if (
+ lastConnectorId === 0 &&
+ this.getUseConnectorId0(stationInfo) === true &&
+ connectorStatus
+ ) {
+ this.checkStationInfoConnectorStatus(lastConnectorId, connectorStatus);
+ this.connectors.set(
+ lastConnectorId,
+ Utils.cloneObject<ConnectorStatus>(connectorStatus)
+ );
+ this.getConnectorStatus(lastConnectorId).availability = AvailabilityType.OPERATIVE;
+ if (Utils.isUndefined(this.getConnectorStatus(lastConnectorId)?.chargingProfiles)) {
+ this.getConnectorStatus(lastConnectorId).chargingProfiles = [];
+ }
+ }
+ }
+ // Generate all connectors
+ if ((stationInfo?.Connectors[0] ? templateMaxConnectors - 1 : templateMaxConnectors) > 0) {
+ for (let index = 1; index <= configuredMaxConnectors; index++) {
+ const randConnectorId = stationInfo?.randomConnectors
+ ? Utils.getRandomInteger(Utils.convertToInt(lastConnector), 1)
+ : index;
+ const connectorStatus = stationInfo?.Connectors[randConnectorId.toString()];
+ this.checkStationInfoConnectorStatus(randConnectorId, connectorStatus);
+ this.connectors.set(index, Utils.cloneObject<ConnectorStatus>(connectorStatus));
+ this.getConnectorStatus(index).availability = AvailabilityType.OPERATIVE;
+ if (Utils.isUndefined(this.getConnectorStatus(index)?.chargingProfiles)) {
+ this.getConnectorStatus(index).chargingProfiles = [];
+ }
+ }
+ }
+ }
+ } else {
+ logger.warn(
+ `${this.logPrefix()} Charging station information from template ${
+ this.templateFile
+ } with no connectors configuration defined, using already defined connectors`
+ );
+ }
+ // Initialize transaction attributes on connectors
+ for (const connectorId of this.connectors.keys()) {
+ if (connectorId > 0 && this.getConnectorStatus(connectorId).transactionStarted === true) {
+ logger.warn(
+ `${this.logPrefix()} Connector ${connectorId} at initialization has a transaction started: ${
+ this.getConnectorStatus(connectorId).transactionId
+ }`
+ );
+ }
+ if (
+ connectorId > 0 &&
+ (this.getConnectorStatus(connectorId).transactionStarted === undefined ||
+ this.getConnectorStatus(connectorId).transactionStarted === null)
+ ) {
+ this.initializeConnectorStatus(connectorId);
+ }
+ }
+ }
+
+ private checkStationInfoConnectorStatus(
+ connectorId: number,
+ connectorStatus: ConnectorStatus
+ ): void {
+ if (!Utils.isNullOrUndefined(connectorStatus?.status)) {
+ logger.warn(
+ `${this.logPrefix()} Charging station information from template ${
+ this.templateFile
+ } with connector ${connectorId} status configuration defined, undefine it`
+ );
+ connectorStatus.status = undefined;
+ }
+ }
+
+ private getConfigurationFromFile(): ChargingStationConfiguration | null {
+ let configuration: ChargingStationConfiguration = null;
+ if (this.configurationFile && fs.existsSync(this.configurationFile)) {
+ try {
+ if (this.sharedLRUCache.hasChargingStationConfiguration(this.configurationFileHash)) {
+ configuration = this.sharedLRUCache.getChargingStationConfiguration(
+ this.configurationFileHash
+ );
+ } else {
+ const measureId = `${FileType.ChargingStationConfiguration} read`;
+ const beginId = PerformanceStatistics.beginMeasure(measureId);
+ configuration = JSON.parse(
+ fs.readFileSync(this.configurationFile, 'utf8')
+ ) as ChargingStationConfiguration;
+ PerformanceStatistics.endMeasure(measureId, beginId);
+ this.configurationFileHash = configuration.configurationHash;
+ this.sharedLRUCache.setChargingStationConfiguration(configuration);
+ }
+ } catch (error) {
+ FileUtils.handleFileException(
+ this.logPrefix(),
+ FileType.ChargingStationConfiguration,
+ this.configurationFile,
+ error as NodeJS.ErrnoException
+ );
+ }
+ }
+ return configuration;
+ }
+
+ private saveConfiguration(): void {
+ if (this.configurationFile) {
+ try {
+ if (!fs.existsSync(path.dirname(this.configurationFile))) {
+ fs.mkdirSync(path.dirname(this.configurationFile), { recursive: true });