type ChargingStationInfo,
type ChargingStationOcppConfiguration,
type ChargingStationTemplate,
- ConnectorPhaseRotation,
type ConnectorStatus,
ConnectorStatusEnum,
CurrentType,
type ErrorCallback,
type ErrorResponse,
ErrorType,
+ type EvseStatus,
+ type EvseStatusConfiguration,
FileType,
FirmwareStatus,
type FirmwareStatusNotificationRequest,
public ocppConfiguration!: ChargingStationOcppConfiguration | undefined;
public wsConnection!: WebSocket | null;
public readonly connectors: Map<number, ConnectorStatus>;
+ public readonly evses: Map<number, EvseStatus>;
public readonly requests: Map<string, CachedRequest>;
public performanceStatistics!: PerformanceStatistics | undefined;
public heartbeatSetInterval!: NodeJS.Timeout;
private configurationFile!: string;
private configurationFileHash!: string;
private connectorsConfigurationHash!: string;
+ private evsesConfigurationHash!: string;
private ocppIncomingRequestService!: OCPPIncomingRequestService;
private readonly messageBuffer: Set<string>;
private configuredSupervisionUrl!: URL;
this.index = index;
this.templateFile = templateFile;
this.connectors = new Map<number, ConnectorStatus>();
+ this.evses = new Map<number, EvseStatus>();
this.requests = new Map<string, CachedRequest>();
this.messageBuffer = new Set<string>();
this.sharedLRUCache = SharedLRUCache.getInstance();
this.initialize();
}
+ public get hasEvses(): boolean {
+ return this.connectors.size === 0 && this.evses.size > 0;
+ }
+
private get wsConnectionUrl(): URL {
return new URL(
`${
}
public isChargingStationAvailable(): boolean {
- return this.getConnectorStatus(0)?.availability === AvailabilityType.OPERATIVE;
+ return this.getConnectorStatus(0)?.availability === AvailabilityType.Operative;
+ }
+
+ public hasConnector(connectorId: number): boolean {
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ if (evseStatus.connectors.has(connectorId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return this.connectors.has(connectorId);
}
- public isConnectorAvailable(id: number): boolean {
- return id > 0 && this.getConnectorStatus(id)?.availability === AvailabilityType.OPERATIVE;
+ public isConnectorAvailable(connectorId: number): boolean {
+ return (
+ connectorId > 0 &&
+ this.getConnectorStatus(connectorId)?.availability === AvailabilityType.Operative
+ );
}
public getNumberOfConnectors(): number {
- return this.connectors.get(0) ? this.connectors.size - 1 : this.connectors.size;
+ if (this.hasEvses) {
+ let numberOfConnectors = 0;
+ for (const [evseId, evseStatus] of this.evses) {
+ if (evseId > 0) {
+ numberOfConnectors += evseStatus.connectors.size;
+ }
+ }
+ return numberOfConnectors;
+ }
+ return this.connectors.has(0) ? this.connectors.size - 1 : this.connectors.size;
}
- public getConnectorStatus(id: number): ConnectorStatus | undefined {
- return this.connectors.get(id);
+ public getNumberOfEvses(): number {
+ return this.evses.has(0) ? this.evses.size - 1 : this.evses.size;
+ }
+
+ public getConnectorStatus(connectorId: number): ConnectorStatus | undefined {
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ if (evseStatus.connectors.has(connectorId)) {
+ return evseStatus.connectors.get(connectorId);
+ }
+ }
+ return undefined;
+ }
+ return this.connectors.get(connectorId);
}
public getCurrentOutType(stationInfo?: ChargingStationInfo): CurrentType {
}
public getTransactionIdTag(transactionId: number): string | undefined {
- for (const connectorId of this.connectors.keys()) {
- if (
- connectorId > 0 &&
- this.getConnectorStatus(connectorId)?.transactionId === transactionId
- ) {
- return this.getConnectorStatus(connectorId)?.transactionIdTag;
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ for (const connectorStatus of evseStatus.connectors.values()) {
+ if (connectorStatus.transactionId === transactionId) {
+ return connectorStatus.transactionIdTag;
+ }
+ }
+ }
+ } else {
+ for (const connectorId of this.connectors.keys()) {
+ if (
+ connectorId > 0 &&
+ this.getConnectorStatus(connectorId)?.transactionId === transactionId
+ ) {
+ return this.getConnectorStatus(connectorId)?.transactionIdTag;
+ }
}
}
}
}
public getConnectorIdByTransactionId(transactionId: number): number | undefined {
- for (const connectorId of this.connectors.keys()) {
- if (
- connectorId > 0 &&
- this.getConnectorStatus(connectorId)?.transactionId === transactionId
- ) {
- return connectorId;
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ for (const [connectorId, connectorStatus] of evseStatus.connectors) {
+ if (connectorStatus.transactionId === transactionId) {
+ return connectorId;
+ }
+ }
+ }
+ } else {
+ for (const connectorId of this.connectors.keys()) {
+ if (
+ connectorId > 0 &&
+ this.getConnectorStatus(connectorId)?.transactionId === transactionId
+ ) {
+ return connectorId;
+ }
}
}
}
public startMeterValues(connectorId: number, interval: number): void {
if (connectorId === 0) {
logger.error(
- `${this.logPrefix()} Trying to start MeterValues on connector Id ${connectorId.toString()}`
+ `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId.toString()}`
);
return;
}
if (!this.getConnectorStatus(connectorId)) {
logger.error(
- `${this.logPrefix()} Trying to start MeterValues on non existing connector Id ${connectorId.toString()}`
+ `${this.logPrefix()} Trying to start MeterValues on non existing connector id ${connectorId.toString()}`
);
return;
}
if (this.getConnectorStatus(connectorId)?.transactionStarted === false) {
logger.error(
- `${this.logPrefix()} Trying to start MeterValues on connector Id ${connectorId} with no transaction started`
+ `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId} with no transaction started`
);
return;
} else if (
Utils.isNullOrUndefined(this.getConnectorStatus(connectorId)?.transactionId)
) {
logger.error(
- `${this.logPrefix()} Trying to start MeterValues on connector Id ${connectorId} with no transaction id`
+ `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId} with no transaction id`
);
return;
}
}
}
+ public stopMeterValues(connectorId: number) {
+ if (this.getConnectorStatus(connectorId)?.transactionSetInterval) {
+ clearInterval(this.getConnectorStatus(connectorId)?.transactionSetInterval);
+ }
+ }
+
public start(): void {
if (this.started === false) {
if (this.starting === false) {
public saveOcppConfiguration(): void {
if (this.getOcppPersistentConfiguration()) {
- this.saveConfiguration();
- }
- }
-
- public resetConnectorStatus(connectorId: number): void {
- this.getConnectorStatus(connectorId).idTagLocalAuthorized = false;
- this.getConnectorStatus(connectorId).idTagAuthorized = false;
- this.getConnectorStatus(connectorId).transactionRemoteStarted = false;
- this.getConnectorStatus(connectorId).transactionStarted = false;
- delete this.getConnectorStatus(connectorId)?.localAuthorizeIdTag;
- delete this.getConnectorStatus(connectorId)?.authorizeIdTag;
- delete this.getConnectorStatus(connectorId)?.transactionId;
- delete this.getConnectorStatus(connectorId)?.transactionIdTag;
- this.getConnectorStatus(connectorId).transactionEnergyActiveImportRegisterValue = 0;
- delete this.getConnectorStatus(connectorId)?.transactionBeginMeterValue;
- this.stopMeterValues(connectorId);
- parentPort?.postMessage(MessageChannelUtils.buildUpdatedMessage(this));
+ this.saveConfiguration({ stationInfo: false, connectors: false, evses: false });
+ }
}
public hasFeatureProfile(featureProfile: SupportedFeatureProfiles): boolean | undefined {
private flushMessageBuffer(): void {
if (this.messageBuffer.size > 0) {
- this.messageBuffer.forEach((message) => {
+ for (const message of this.messageBuffer.values()) {
let beginId: string;
let commandName: RequestCommand;
const [messageType] = JSON.parse(message) as OutgoingRequest | Response | ErrorResponse;
)} payload sent: ${message}`
);
this.messageBuffer.delete(message);
- });
+ }
}
}
stationInfo.resetTime = !Utils.isNullOrUndefined(stationTemplate?.resetTime)
? stationTemplate.resetTime * 1000
: Constants.CHARGING_STATION_DEFAULT_RESET_TIME;
- const configuredMaxConnectors =
- ChargingStationUtils.getConfiguredNumberOfConnectors(stationTemplate);
- ChargingStationUtils.checkConfiguredMaxConnectors(
- configuredMaxConnectors,
- this.templateFile,
- this.logPrefix()
- );
- const templateMaxConnectors =
- ChargingStationUtils.getTemplateMaxNumberOfConnectors(stationTemplate);
- ChargingStationUtils.checkTemplateMaxConnectors(
- templateMaxConnectors,
- this.templateFile,
- this.logPrefix()
- );
- if (
- configuredMaxConnectors >
- (stationTemplate?.Connectors[0] ? templateMaxConnectors - 1 : templateMaxConnectors) &&
- !stationTemplate?.randomConnectors
- ) {
- logger.warn(
- `${this.logPrefix()} Number of connectors exceeds the number of connector configurations in template ${
- this.templateFile
- }, forcing random connector configurations affectation`
- );
- stationInfo.randomConnectors = true;
- }
- // Build connectors if needed (FIXME: should be factored out)
- this.initializeConnectors(stationInfo, configuredMaxConnectors, templateMaxConnectors);
+ // Initialize evses or connectors if needed (FIXME: should be factored out)
+ this.initializeConnectorsOrEvses(stationInfo);
stationInfo.maximumAmperage = this.getMaximumAmperage(stationInfo);
ChargingStationUtils.createStationInfoHash(stationInfo);
return stationInfo;
private getStationInfo(): ChargingStationInfo {
const stationInfoFromTemplate: ChargingStationInfo = this.getStationInfoFromTemplate();
const stationInfoFromFile: ChargingStationInfo | undefined = this.getStationInfoFromFile();
- // Priority: charging station info from template > charging station info from configuration file > charging station info attribute
+ // Priority:
+ // 1. charging station info from template
+ // 2. charging station info from configuration file
+ // 3. charging station info attribute
if (stationInfoFromFile?.templateHash === stationInfoFromTemplate.templateHash) {
if (this.stationInfo?.infoHash === stationInfoFromFile?.infoHash) {
return this.stationInfo;
private saveStationInfo(): void {
if (this.getStationInfoPersistentConfiguration()) {
- this.saveConfiguration();
+ this.saveConfiguration({ ocppConfiguration: false, connectors: false, evses: false });
}
}
this.stationInfo.firmwareVersion = match?.join('.');
}
this.saveStationInfo();
- // Avoid duplication of connectors related information in RAM
+ // Avoid duplication of connectors or evses related information in RAM
delete this.stationInfo?.Connectors;
+ delete this.stationInfo?.Evses;
this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl();
if (this.getEnableStatistics() === true) {
this.performanceStatistics = PerformanceStatistics.getInstance(
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}`);
+ const connectorsPhaseRotation: string[] = [];
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ for (const connectorId of evseStatus.connectors.keys()) {
+ connectorsPhaseRotation.push(
+ ChargingStationUtils.getPhaseRotationValue(connectorId, this.getNumberOfPhases())
+ );
+ }
+ }
+ } else {
+ for (const connectorId of this.connectors.keys()) {
+ connectorsPhaseRotation.push(
+ ChargingStationUtils.getPhaseRotationValue(connectorId, this.getNumberOfPhases())
+ );
}
}
ChargingStationConfigurationUtils.addConfigurationKey(
this,
StandardParametersKey.ConnectorPhaseRotation,
- connectorPhaseRotation.toString()
+ connectorsPhaseRotation.toString()
);
}
if (
this.saveOcppConfiguration();
}
- private initializeConnectors(
- stationInfo: ChargingStationInfo,
- configuredMaxConnectors: number,
- templateMaxConnectors: number
- ): void {
+ private initializeConnectorsOrEvses(stationInfo: ChargingStationInfo) {
+ if (stationInfo?.Connectors && !stationInfo?.Evses) {
+ this.initializeConnectors(stationInfo);
+ } else if (stationInfo?.Evses && !stationInfo?.Connectors) {
+ this.initializeEvses(stationInfo);
+ } else if (stationInfo?.Evses && stationInfo?.Connectors) {
+ const errorMsg = `Connectors and evses defined at the same time in template file ${this.templateFile}`;
+ logger.error(`${this.logPrefix()} ${errorMsg}`);
+ throw new BaseError(errorMsg);
+ } else {
+ const errorMsg = `No connectors or evses defined in template file ${this.templateFile}`;
+ logger.error(`${this.logPrefix()} ${errorMsg}`);
+ throw new BaseError(errorMsg);
+ }
+ }
+
+ private initializeConnectors(stationInfo: ChargingStationInfo): 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}`);
logger.warn(
`${this.logPrefix()} Charging station information from template ${
this.templateFile
- } with no connector Id 0 configuration`
+ } with no connector id 0 configuration`
);
}
if (stationInfo?.Connectors) {
+ const configuredMaxConnectors =
+ ChargingStationUtils.getConfiguredNumberOfConnectors(stationInfo);
+ ChargingStationUtils.checkConfiguredMaxConnectors(
+ configuredMaxConnectors,
+ this.templateFile,
+ this.logPrefix()
+ );
const connectorsConfigHash = crypto
.createHash(Constants.DEFAULT_HASH_ALGORITHM)
.update(`${JSON.stringify(stationInfo?.Connectors)}${configuredMaxConnectors.toString()}`)
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 = [];
- }
- }
+ const templateMaxConnectors = ChargingStationUtils.getMaxNumberOfConnectors(
+ stationInfo.Connectors
+ );
+ ChargingStationUtils.checkTemplateMaxConnectors(
+ templateMaxConnectors,
+ this.templateFile,
+ this.logPrefix()
+ );
+ const templateMaxAvailableConnectors = stationInfo?.Connectors[0]
+ ? templateMaxConnectors - 1
+ : templateMaxConnectors;
+ if (
+ configuredMaxConnectors > templateMaxAvailableConnectors &&
+ !stationInfo?.randomConnectors
+ ) {
+ logger.warn(
+ `${this.logPrefix()} Number of connectors exceeds the number of connector configurations in template ${
+ this.templateFile
+ }, forcing random connector configurations affectation`
+ );
+ stationInfo.randomConnectors = true;
}
- // 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 = [];
+ if (templateMaxConnectors > 0) {
+ for (let connectorId = 0; connectorId <= configuredMaxConnectors; connectorId++) {
+ if (
+ connectorId === 0 &&
+ (!stationInfo?.Connectors[connectorId] ||
+ this.getUseConnectorId0(stationInfo) === false)
+ ) {
+ continue;
}
+ const templateConnectorId =
+ connectorId > 0 && stationInfo?.randomConnectors
+ ? Utils.getRandomInteger(templateMaxAvailableConnectors, 1)
+ : connectorId;
+ const connectorStatus = stationInfo?.Connectors[templateConnectorId];
+ ChargingStationUtils.checkStationInfoConnectorStatus(
+ templateConnectorId,
+ connectorStatus,
+ this.logPrefix(),
+ this.templateFile
+ );
+ this.connectors.set(connectorId, Utils.cloneObject<ConnectorStatus>(connectorStatus));
}
+ ChargingStationUtils.initializeConnectorsMapStatus(this.connectors, this.logPrefix());
+ this.saveConnectorsStatus();
+ } else {
+ logger.warn(
+ `${this.logPrefix()} Charging station information from template ${
+ this.templateFile
+ } with no connectors configuration defined, cannot create connectors`
+ );
}
}
} else {
} 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)) {
+ private initializeEvses(stationInfo: ChargingStationInfo): void {
+ if (!stationInfo?.Evses && this.evses.size === 0) {
+ const logMsg = `No already defined evses and charging station information from template ${this.templateFile} with no evses configuration defined`;
+ logger.error(`${this.logPrefix()} ${logMsg}`);
+ throw new BaseError(logMsg);
+ }
+ if (!stationInfo?.Evses[0]) {
logger.warn(
`${this.logPrefix()} Charging station information from template ${
this.templateFile
- } with connector ${connectorId} status configuration defined, undefine it`
+ } with no evse id 0 configuration`
+ );
+ }
+ if (!stationInfo?.Evses[0]?.Connectors[0]) {
+ logger.warn(
+ `${this.logPrefix()} Charging station information from template ${
+ this.templateFile
+ } with evse id 0 with no connector id 0 configuration`
+ );
+ }
+ if (stationInfo?.Evses) {
+ const evsesConfigHash = crypto
+ .createHash(Constants.DEFAULT_HASH_ALGORITHM)
+ .update(`${JSON.stringify(stationInfo?.Evses)}`)
+ .digest('hex');
+ const evsesConfigChanged =
+ this.evses?.size !== 0 && this.evsesConfigurationHash !== evsesConfigHash;
+ if (this.evses?.size === 0 || evsesConfigChanged) {
+ evsesConfigChanged && this.evses.clear();
+ this.evsesConfigurationHash = evsesConfigHash;
+ const templateMaxEvses = ChargingStationUtils.getMaxNumberOfEvses(stationInfo?.Evses);
+ if (templateMaxEvses > 0) {
+ for (const evse in stationInfo.Evses) {
+ const evseId = Utils.convertToInt(evse);
+ this.evses.set(evseId, {
+ connectors: ChargingStationUtils.buildConnectorsMap(
+ stationInfo?.Evses[evse]?.Connectors,
+ this.logPrefix(),
+ this.templateFile
+ ),
+ availability: AvailabilityType.Operative,
+ });
+ ChargingStationUtils.initializeConnectorsMapStatus(
+ this.evses.get(evseId)?.connectors,
+ this.logPrefix()
+ );
+ }
+ this.saveEvsesStatus();
+ } else {
+ logger.warn(
+ `${this.logPrefix()} Charging station information from template ${
+ this.templateFile
+ } with no evses configuration defined, cannot create evses`
+ );
+ }
+ }
+ } else {
+ logger.warn(
+ `${this.logPrefix()} Charging station information from template ${
+ this.templateFile
+ } with no evses configuration defined, using already defined evses`
);
- delete connectorStatus.status;
}
}
return configuration;
}
- private saveConfiguration(): void {
+ private saveConnectorsStatus() {
+ if (this.getOcppPersistentConfiguration()) {
+ this.saveConfiguration({ stationInfo: false, ocppConfiguration: false, evses: false });
+ }
+ }
+
+ private saveEvsesStatus() {
+ if (this.getOcppPersistentConfiguration()) {
+ this.saveConfiguration({ stationInfo: false, ocppConfiguration: false, connectors: false });
+ }
+ }
+
+ private saveConfiguration(
+ params: {
+ stationInfo?: boolean;
+ ocppConfiguration?: boolean;
+ connectors?: boolean;
+ evses?: boolean;
+ } = { stationInfo: true, ocppConfiguration: true, connectors: true, evses: true }
+ ): void {
if (this.configurationFile) {
+ params = {
+ ...params,
+ ...{ stationInfo: true, ocppConfiguration: true, connectors: true, evses: true },
+ };
try {
if (!fs.existsSync(path.dirname(this.configurationFile))) {
fs.mkdirSync(path.dirname(this.configurationFile), { recursive: true });
}
const configurationData: ChargingStationConfiguration =
Utils.cloneObject(this.getConfigurationFromFile()) ?? {};
- this.ocppConfiguration?.configurationKey &&
- (configurationData.configurationKey = this.ocppConfiguration.configurationKey);
- this.stationInfo && (configurationData.stationInfo = this.stationInfo);
+ if (params.stationInfo && this.stationInfo) {
+ configurationData.stationInfo = this.stationInfo;
+ }
+ if (params.ocppConfiguration && this.ocppConfiguration?.configurationKey) {
+ configurationData.configurationKey = this.ocppConfiguration.configurationKey;
+ }
+ if (params.connectors && this.connectors.size > 0) {
+ configurationData.connectorsStatus = [...this.connectors.values()].map(
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ ({ transactionSetInterval, ...connectorStatusRest }) => connectorStatusRest
+ );
+ }
+ if (params.evses && this.evses.size > 0) {
+ configurationData.evsesStatus = [...this.evses.values()].map((evseStatus) => {
+ const status = {
+ ...evseStatus,
+ connectorsStatus: [...evseStatus.connectors.values()].map(
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ ({ transactionSetInterval, ...connectorStatusRest }) => connectorStatusRest
+ ),
+ };
+ delete status.connectors;
+ return status as EvseStatusConfiguration;
+ });
+ }
delete configurationData.configurationHash;
const configurationHash = crypto
.createHash(Constants.DEFAULT_HASH_ALGORITHM)
private getNumberOfRunningTransactions(): number {
let trxCount = 0;
- for (const connectorId of this.connectors.keys()) {
- if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
- trxCount++;
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ for (const connectorStatus of evseStatus.connectors.values()) {
+ if (connectorStatus.transactionStarted === true) {
+ trxCount++;
+ }
+ }
+ }
+ } else {
+ for (const connectorId of this.connectors.keys()) {
+ if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
+ trxCount++;
+ }
}
}
return trxCount;
}
private async stopRunningTransactions(reason = StopTransactionReason.NONE): Promise<void> {
- for (const connectorId of this.connectors.keys()) {
- if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
- await this.stopTransactionOnConnector(connectorId, reason);
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ for (const [connectorId, connectorStatus] of evseStatus.connectors) {
+ if (connectorStatus.transactionStarted === true) {
+ await this.stopTransactionOnConnector(connectorId, reason);
+ }
+ }
+ }
+ } else {
+ for (const connectorId of this.connectors.keys()) {
+ if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
+ await this.stopTransactionOnConnector(connectorId, reason);
+ }
}
}
}
// Start heartbeat
this.startHeartbeat();
// Initialize connectors status
- for (const connectorId of this.connectors.keys()) {
- let connectorStatus: ConnectorStatusEnum | undefined;
- if (connectorId === 0) {
- continue;
- } else if (
- !this.getConnectorStatus(connectorId)?.status &&
- (this.isChargingStationAvailable() === false ||
- this.isConnectorAvailable(connectorId) === false)
- ) {
- connectorStatus = ConnectorStatusEnum.Unavailable;
- } else if (
- !this.getConnectorStatus(connectorId)?.status &&
- this.getConnectorStatus(connectorId)?.bootStatus
- ) {
- // Set boot status in template at startup
- connectorStatus = this.getConnectorStatus(connectorId)?.bootStatus;
- } else if (this.getConnectorStatus(connectorId)?.status) {
- // Set previous status at startup
- connectorStatus = this.getConnectorStatus(connectorId)?.status;
- } else {
- // Set default status
- connectorStatus = ConnectorStatusEnum.Available;
+ if (this.hasEvses) {
+ for (const [evseId, evseStatus] of this.evses) {
+ if (evseId > 0) {
+ for (const [connectorId, connectorStatus] of evseStatus.connectors) {
+ const connectorBootStatus = ChargingStationUtils.getBootConnectorStatus(
+ this,
+ connectorId,
+ connectorStatus
+ );
+ await OCPPServiceUtils.sendAndSetConnectorStatus(
+ this,
+ connectorId,
+ connectorBootStatus
+ );
+ }
+ }
+ }
+ } else {
+ for (const connectorId of this.connectors.keys()) {
+ if (connectorId > 0) {
+ const connectorBootStatus = ChargingStationUtils.getBootConnectorStatus(
+ this,
+ connectorId,
+ this.getConnectorStatus(connectorId)
+ );
+ await OCPPServiceUtils.sendAndSetConnectorStatus(this, connectorId, connectorBootStatus);
+ }
}
- await this.ocppRequestService.requestHandler<
- StatusNotificationRequest,
- StatusNotificationResponse
- >(
- this,
- RequestCommand.STATUS_NOTIFICATION,
- OCPPServiceUtils.buildStatusNotificationRequest(this, connectorId, connectorStatus)
- );
- this.getConnectorStatus(connectorId).status = connectorStatus;
}
if (this.stationInfo?.firmwareStatus === FirmwareStatus.Installing) {
await this.ocppRequestService.requestHandler<
} else {
await this.stopRunningTransactions(reason);
}
- for (const connectorId of this.connectors.keys()) {
- if (connectorId > 0) {
- await this.ocppRequestService.requestHandler<
- StatusNotificationRequest,
- StatusNotificationResponse
- >(
- this,
- RequestCommand.STATUS_NOTIFICATION,
- OCPPServiceUtils.buildStatusNotificationRequest(
+ if (this.hasEvses) {
+ for (const [evseId, evseStatus] of this.evses) {
+ if (evseId > 0) {
+ for (const [connectorId, connectorStatus] of evseStatus.connectors) {
+ await this.ocppRequestService.requestHandler<
+ StatusNotificationRequest,
+ StatusNotificationResponse
+ >(
+ this,
+ RequestCommand.STATUS_NOTIFICATION,
+ OCPPServiceUtils.buildStatusNotificationRequest(
+ this,
+ connectorId,
+ ConnectorStatusEnum.Unavailable
+ )
+ );
+ delete connectorStatus?.status;
+ }
+ }
+ }
+ } else {
+ for (const connectorId of this.connectors.keys()) {
+ if (connectorId > 0) {
+ await this.ocppRequestService.requestHandler<
+ StatusNotificationRequest,
+ StatusNotificationResponse
+ >(
this,
- connectorId,
- ConnectorStatusEnum.Unavailable
- )
- );
- delete this.getConnectorStatus(connectorId)?.status;
+ RequestCommand.STATUS_NOTIFICATION,
+ OCPPServiceUtils.buildStatusNotificationRequest(
+ this,
+ connectorId,
+ ConnectorStatusEnum.Unavailable
+ )
+ );
+ delete this.getConnectorStatus(connectorId)?.status;
+ }
}
}
}
}
}
- private stopMeterValues(connectorId: number) {
- if (this.getConnectorStatus(connectorId)?.transactionSetInterval) {
- clearInterval(this.getConnectorStatus(connectorId)?.transactionSetInterval);
- }
- }
-
private getReconnectExponentialDelay(): boolean {
return this.stationInfo?.reconnectExponentialDelay ?? false;
}
| undefined {
return this.getTemplateFromFile()?.AutomaticTransactionGenerator;
}
-
- private initializeConnectorStatus(connectorId: number): void {
- this.getConnectorStatus(connectorId).idTagLocalAuthorized = false;
- this.getConnectorStatus(connectorId).idTagAuthorized = false;
- this.getConnectorStatus(connectorId).transactionRemoteStarted = false;
- this.getConnectorStatus(connectorId).transactionStarted = false;
- this.getConnectorStatus(connectorId).energyActiveImportRegisterValue = 0;
- this.getConnectorStatus(connectorId).transactionEnergyActiveImportRegisterValue = 0;
- }
}