X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcharging-station%2FChargingStation.ts;h=30b21bdc357bd2ab65c70e90c4232b5352961750;hb=4c2b490420d856ee0602b3806d6508b67643613b;hp=10806bd295bf93134f8ec3734c597378b2788fba;hpb=36f6a92e3ab0a4a452da57aad6510bda259296ce;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 10806bd2..30b21bdc 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -1,8 +1,9 @@ import { BootNotificationResponse, RegistrationStatus } from '../types/ocpp/Responses'; import ChargingStationConfiguration, { ConfigurationKey } from '../types/ChargingStationConfiguration'; -import ChargingStationTemplate, { CurrentOutType, PowerUnits, VoltageOut } from '../types/ChargingStationTemplate'; +import ChargingStationTemplate, { CurrentType, PowerUnits, Voltage } from '../types/ChargingStationTemplate'; import { ConnectorPhaseRotation, StandardParametersKey, SupportedFeatureProfiles } from '../types/ocpp/Configuration'; -import Connectors, { Connector } from '../types/Connectors'; +import Connectors, { Connector, SampledValueTemplate } from '../types/Connectors'; +import { MeterValueMeasurand, MeterValuePhase } from '../types/ocpp/MeterValues'; import { PerformanceObserver, performance } from 'perf_hooks'; import Requests, { AvailabilityType, BootNotificationRequest, IncomingRequest, IncomingRequestCommand } from '../types/ocpp/Requests'; import WebSocket, { MessageEvent } from 'ws'; @@ -15,7 +16,6 @@ import Configuration from '../utils/Configuration'; import Constants from '../utils/Constants'; import FileUtils from '../utils/FileUtils'; import { MessageType } from '../types/ocpp/MessageType'; -import { MeterValueMeasurand } from '../types/ocpp/MeterValues'; import OCPP16IncomingRequestService from './ocpp/1.6/OCCP16IncomingRequestService'; import OCPP16RequestService from './ocpp/1.6/OCPP16RequestService'; import OCPP16ResponseService from './ocpp/1.6/OCPP16ResponseService'; @@ -93,9 +93,9 @@ export default class ChargingStation { public getNumberOfPhases(): number | undefined { switch (this.getCurrentOutType()) { - case CurrentOutType.AC: + case CurrentType.AC: return !Utils.isUndefined(this.stationInfo.numberOfPhases) ? this.stationInfo.numberOfPhases : 3; - case CurrentOutType.DC: + case CurrentType.DC: return 0; } } @@ -120,19 +120,19 @@ export default class ChargingStation { return this.connectors[id]; } - public getCurrentOutType(): CurrentOutType | undefined { - return !Utils.isUndefined(this.stationInfo.currentOutType) ? this.stationInfo.currentOutType : CurrentOutType.AC; + public getCurrentOutType(): CurrentType | undefined { + return this.stationInfo.currentOutType ?? CurrentType.AC; } public getVoltageOut(): number | undefined { const errMsg = `${this.logPrefix()} Unknown ${this.getCurrentOutType()} currentOutType in template file ${this.stationTemplateFile}, cannot define default voltage out`; let defaultVoltageOut: number; switch (this.getCurrentOutType()) { - case CurrentOutType.AC: - defaultVoltageOut = VoltageOut.VOLTAGE_230; + case CurrentType.AC: + defaultVoltageOut = Voltage.VOLTAGE_230; break; - case CurrentOutType.DC: - defaultVoltageOut = VoltageOut.VOLTAGE_400; + case CurrentType.DC: + defaultVoltageOut = Voltage.VOLTAGE_400; break; default: logger.error(errMsg); @@ -144,7 +144,7 @@ export default class ChargingStation { public getTransactionIdTag(transactionId: number): string | undefined { for (const connector in this.connectors) { if (Utils.convertToInt(connector) > 0 && this.getConnector(Utils.convertToInt(connector)).transactionId === transactionId) { - return this.getConnector(Utils.convertToInt(connector)).idTag; + return this.getConnector(Utils.convertToInt(connector)).transactionIdTag; } } } @@ -165,6 +165,14 @@ export default class ChargingStation { return this.stationInfo.transactionDataMeterValues ?? false; } + public getMainVoltageMeterValues(): boolean { + return this.stationInfo.mainVoltageMeterValues ?? true; + } + + public getPhaseLineToLineVoltageMeterValues(): boolean { + return this.stationInfo.phaseLineToLineVoltageMeterValues ?? false; + } + public getEnergyActiveImportRegisterByTransactionId(transactionId: number): number | undefined { if (this.getMeteringPerTransaction()) { for (const connector in this.connectors) { @@ -204,6 +212,35 @@ export default class ChargingStation { this.startWebSocketPing(); } + public getSampledValueTemplate(connectorId: number, measurand: MeterValueMeasurand = MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER, + phase?: MeterValuePhase): SampledValueTemplate | undefined { + if (!Constants.SUPPORTED_MEASURANDS.includes(measurand)) { + logger.warn(`${this.logPrefix()} Trying to get unsupported MeterValues measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId}`); + return; + } + if (measurand !== MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER && !this.getConfigurationKey(StandardParametersKey.MeterValuesSampledData).value.includes(measurand)) { + logger.debug(`${this.logPrefix()} Trying to get MeterValues measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId} not found in '${StandardParametersKey.MeterValuesSampledData}' OCPP parameter`); + return; + } + const sampledValueTemplates: SampledValueTemplate[] = this.getConnector(connectorId).MeterValues; + for (let index = 0; !Utils.isEmptyArray(sampledValueTemplates) && index < sampledValueTemplates.length; index++) { + if (phase && sampledValueTemplates[index]?.phase === phase && sampledValueTemplates[index]?.measurand === measurand + && this.getConfigurationKey(StandardParametersKey.MeterValuesSampledData).value.includes(measurand)) { + return sampledValueTemplates[index]; + } else if (!phase && !sampledValueTemplates[index].phase && sampledValueTemplates[index]?.measurand === measurand + && this.getConfigurationKey(StandardParametersKey.MeterValuesSampledData).value.includes(measurand)) { + return sampledValueTemplates[index]; + } else if (measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER + && (!sampledValueTemplates[index].measurand || sampledValueTemplates[index].measurand === measurand)) { + return sampledValueTemplates[index]; + } + } + if (measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) { + logger.error(`${this.logPrefix()} Missing MeterValues for default measurand ${measurand} in template on connectorId ${connectorId}`); + } + logger.debug(`${this.logPrefix()} No MeterValues for measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId}`); + } + public getAutomaticTransactionGeneratorRequireAuthorize(): boolean { return this.stationInfo.AutomaticTransactionGenerator.requireAuthorize ?? true; } @@ -338,7 +375,7 @@ export default class ChargingStation { if (!Utils.isEmptyArray(this.getConnector(connectorId).chargingProfiles)) { this.getConnector(connectorId).chargingProfiles?.forEach((chargingProfile: ChargingProfile, index: number) => { if (chargingProfile.chargingProfileId === cp.chargingProfileId - || (chargingProfile.stackLevel === cp.stackLevel && chargingProfile.chargingProfilePurpose === cp.chargingProfilePurpose)) { + || (chargingProfile.stackLevel === cp.stackLevel && chargingProfile.chargingProfilePurpose === cp.chargingProfilePurpose)) { this.getConnector(connectorId).chargingProfiles[index] = cp; return true; } @@ -349,9 +386,11 @@ export default class ChargingStation { } public resetTransactionOnConnector(connectorId: number): void { + this.getConnector(connectorId).authorized = false; this.getConnector(connectorId).transactionStarted = false; + delete this.getConnector(connectorId).authorizeIdTag; delete this.getConnector(connectorId).transactionId; - delete this.getConnector(connectorId).idTag; + delete this.getConnector(connectorId).transactionIdTag; this.getConnector(connectorId).transactionEnergyActiveImportRegisterValue = 0; delete this.getConnector(connectorId).transactionBeginMeterValue; this.stopMeterValues(connectorId); @@ -384,9 +423,9 @@ export default class ChargingStation { private getChargingStationId(stationTemplate: ChargingStationTemplate): string { // In case of multiple instances: add instance index to charging station id - let instanceIndex = process.env.CF_INSTANCE_INDEX ? process.env.CF_INSTANCE_INDEX : 0; + let instanceIndex = process.env.CF_INSTANCE_INDEX ?? 0; instanceIndex = instanceIndex > 0 ? instanceIndex : ''; - const idSuffix = stationTemplate.nameSuffix ? stationTemplate.nameSuffix : ''; + const idSuffix = stationTemplate.nameSuffix ?? ''; return stationTemplate.fixedName ? stationTemplate.baseName : stationTemplate.baseName + '-' + instanceIndex.toString() + ('000000000' + this.index.toString()).substr(('000000000' + this.index.toString()).length - 4) + idSuffix; } @@ -476,8 +515,8 @@ export default class ChargingStation { // Generate all connectors if ((this.stationInfo.Connectors[0] ? templateMaxConnectors - 1 : templateMaxConnectors) > 0) { for (let index = 1; index <= maxConnectors; index++) { - const randConnectorID = this.stationInfo.randomConnectors ? Utils.getRandomInt(Utils.convertToInt(lastConnector), 1) : index; - this.connectors[index] = Utils.cloneObject(this.stationInfo.Connectors[randConnectorID]); + const randConnectorId = this.stationInfo.randomConnectors ? Utils.getRandomInt(Utils.convertToInt(lastConnector), 1) : index; + this.connectors[index] = Utils.cloneObject(this.stationInfo.Connectors[randConnectorId]); this.connectors[index].availability = AvailabilityType.OPERATIVE; if (Utils.isUndefined(this.connectors[lastConnector]?.chargingProfiles)) { this.connectors[index].chargingProfiles = []; @@ -503,6 +542,19 @@ export default class ChargingStation { break; } // OCPP parameters + this.initOCPPParameters(); + this.stationInfo.powerDivider = this.getPowerDivider(); + if (this.getEnableStatistics()) { + this.performanceStatistics = new PerformanceStatistics(this.stationInfo.chargingStationId); + this.performanceObserver = new PerformanceObserver((list) => { + const entry = list.getEntries()[0]; + this.performanceStatistics.logPerformance(entry, Constants.ENTITY_CHARGING_STATION); + this.performanceObserver.disconnect(); + }); + } + } + + private initOCPPParameters(): void { if (!this.getConfigurationKey(StandardParametersKey.SupportedFeatureProfiles)) { this.addConfigurationKey(StandardParametersKey.SupportedFeatureProfiles, `${SupportedFeatureProfiles.Core},${SupportedFeatureProfiles.Local_Auth_List_Management},${SupportedFeatureProfiles.Smart_Charging}`); } @@ -534,14 +586,8 @@ export default class ChargingStation { && this.getConfigurationKey(StandardParametersKey.SupportedFeatureProfiles).value.includes(SupportedFeatureProfiles.Local_Auth_List_Management)) { this.addConfigurationKey(StandardParametersKey.LocalAuthListEnabled, 'false'); } - this.stationInfo.powerDivider = this.getPowerDivider(); - if (this.getEnableStatistics()) { - this.performanceStatistics = new PerformanceStatistics(this.stationInfo.chargingStationId); - this.performanceObserver = new PerformanceObserver((list) => { - const entry = list.getEntries()[0]; - this.performanceStatistics.logPerformance(entry, Constants.ENTITY_CHARGING_STATION); - this.performanceObserver.disconnect(); - }); + if (!this.getConfigurationKey(StandardParametersKey.ConnectionTimeOut)) { + this.addConfigurationKey(StandardParametersKey.ConnectionTimeOut, Constants.DEFAULT_CONNECTION_TIMEOUT.toString()); } } @@ -707,13 +753,10 @@ export default class ChargingStation { // 0 for disabling private getConnectionTimeout(): number | undefined { - if (!Utils.isUndefined(this.stationInfo.connectionTimeout)) { - return this.stationInfo.connectionTimeout; - } - if (!Utils.isUndefined(Configuration.getConnectionTimeout())) { - return Configuration.getConnectionTimeout(); + if (this.getConfigurationKey(StandardParametersKey.ConnectionTimeOut)) { + return parseInt(this.getConfigurationKey(StandardParametersKey.ConnectionTimeOut).value) ?? Constants.DEFAULT_CONNECTION_TIMEOUT; } - return 30; + return Constants.DEFAULT_CONNECTION_TIMEOUT; } // -1 for unlimited, 0 for disabling @@ -986,6 +1029,7 @@ export default class ChargingStation { } private initTransactionAttributesOnConnector(connectorId: number): void { + this.getConnector(connectorId).authorized = false; this.getConnector(connectorId).transactionStarted = false; this.getConnector(connectorId).energyActiveImportRegisterValue = 0; this.getConnector(connectorId).transactionEnergyActiveImportRegisterValue = 0;