server.
The distinction between request and response is not done.
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
let skip = 0;
if (start < this.chargingStation.stationInfo.AutomaticTransactionGenerator.probabilityOfStart) {
// Start transaction
- let startATGTransaction: (connectorId: number, self: AutomaticTransactionGenerator) => Promise<StartTransactionResponse | AuthorizeResponse>;
- if (this.chargingStation.getEnableStatistics()) {
- startATGTransaction = PerformanceStatistics.timedFunction(this.startATGTransaction.bind(this));
- } else {
- startATGTransaction = this.startATGTransaction.bind(this);
- }
- const startResponse = await startATGTransaction(connectorId, this);
+ const startResponse = await this.startTransaction(connectorId);
if (startResponse?.idTagInfo?.status !== AuthorizationStatus.ACCEPTED) {
logger.warn(this.logPrefix(connectorId) + ' transaction rejected');
await Utils.sleep(Constants.CHARGING_STATION_ATG_WAIT_TIME);
// Stop transaction
if (this.chargingStation.getConnector(connectorId)?.transactionStarted) {
logger.info(this.logPrefix(connectorId) + ' stop transaction ' + this.chargingStation.getConnector(connectorId).transactionId.toString());
- let stopATGTransaction: (connectorId: number, self: AutomaticTransactionGenerator) => Promise<StopTransactionResponse>;
- if (this.chargingStation.getEnableStatistics()) {
- stopATGTransaction = PerformanceStatistics.timedFunction(this.stopATGTransaction.bind(this));
- } else {
- stopATGTransaction = this.stopATGTransaction.bind(this);
- }
- await stopATGTransaction(connectorId, this);
+ await this.stopTransaction(connectorId);
}
}
} else {
}
// eslint-disable-next-line consistent-this
- private async startATGTransaction(connectorId: number, self: AutomaticTransactionGenerator): Promise<StartTransactionResponse | AuthorizeResponse> {
- if (self.chargingStation.hasAuthorizedTags()) {
- const tagId = self.chargingStation.getRandomTagId();
- if (self.chargingStation.getAutomaticTransactionGeneratorRequireAuthorize()) {
+ private async startTransaction(connectorId: number): Promise<StartTransactionResponse | AuthorizeResponse> {
+ const measureId = 'StartTransaction with ATG';
+ const beginId = PerformanceStatistics.beginMeasure(measureId);
+ let startResponse: StartTransactionResponse;
+ if (this.chargingStation.hasAuthorizedTags()) {
+ const tagId = this.chargingStation.getRandomTagId();
+ if (this.chargingStation.getAutomaticTransactionGeneratorRequireAuthorize()) {
// Authorize tagId
- const authorizeResponse = await self.chargingStation.ocppRequestService.sendAuthorize(connectorId, tagId);
+ const authorizeResponse = await this.chargingStation.ocppRequestService.sendAuthorize(connectorId, tagId);
if (authorizeResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
- logger.info(self.logPrefix(connectorId) + ' start transaction for tagID ' + tagId);
+ logger.info(this.logPrefix(connectorId) + ' start transaction for tagID ' + tagId);
// Start transaction
- return self.chargingStation.ocppRequestService.sendStartTransaction(connectorId, tagId);
+ startResponse = await this.chargingStation.ocppRequestService.sendStartTransaction(connectorId, tagId);
+ PerformanceStatistics.endMeasure(measureId, beginId);
+ return startResponse;
}
+ PerformanceStatistics.endMeasure(measureId, beginId);
return authorizeResponse;
}
- logger.info(self.logPrefix(connectorId) + ' start transaction for tagID ' + tagId);
+ logger.info(this.logPrefix(connectorId) + ' start transaction for tagID ' + tagId);
// Start transaction
- return self.chargingStation.ocppRequestService.sendStartTransaction(connectorId, tagId);
+ startResponse = await this.chargingStation.ocppRequestService.sendStartTransaction(connectorId, tagId);
+ PerformanceStatistics.endMeasure(measureId, beginId);
+ return startResponse;
}
- logger.info(self.logPrefix(connectorId) + ' start transaction without a tagID');
- return self.chargingStation.ocppRequestService.sendStartTransaction(connectorId);
+ logger.info(this.logPrefix(connectorId) + ' start transaction without a tagID');
+ startResponse = await this.chargingStation.ocppRequestService.sendStartTransaction(connectorId);
+ PerformanceStatistics.endMeasure(measureId, beginId);
+ return startResponse;
}
// eslint-disable-next-line consistent-this
- private async stopATGTransaction(connectorId: number, self: AutomaticTransactionGenerator): Promise<StopTransactionResponse> {
- const transactionId = self.chargingStation.getConnector(connectorId).transactionId;
- return self.chargingStation.ocppRequestService.sendStopTransaction(transactionId, self.chargingStation.getEnergyActiveImportRegisterByTransactionId(transactionId),
- self.chargingStation.getTransactionIdTag(transactionId));
+ private async stopTransaction(connectorId: number): Promise<StopTransactionResponse> {
+ const measureId = 'StopTransaction with ATG';
+ const beginId = PerformanceStatistics.beginMeasure(measureId);
+ const transactionId = this.chargingStation.getConnector(connectorId).transactionId;
+ const stopResponse = this.chargingStation.ocppRequestService.sendStopTransaction(transactionId,
+ this.chargingStation.getEnergyActiveImportRegisterByTransactionId(transactionId), this.chargingStation.getTransactionIdTag(transactionId));
+ PerformanceStatistics.endMeasure(measureId, beginId);
+ return stopResponse;
}
private logPrefix(connectorId?: number): string {
export default class Bootstrap {
private static instance: Bootstrap;
- private version: string = version ;
+ private version: string = version;
private started: boolean;
private workerScript: string;
private workerImplementationInstance: WorkerAbstract | null = null;
if (interval > 0) {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
this.getConnector(connectorId).transactionSetInterval = setInterval(async (): Promise<void> => {
- await this.ocppRequestService.sendMeterValues(connectorId, this.getConnector(connectorId).transactionId, interval, this.ocppRequestService);
+ await this.ocppRequestService.sendMeterValues(connectorId, this.getConnector(connectorId).transactionId, interval);
}, interval);
} else {
logger.error(`${this.logPrefix()} Charging station ${StandardParametersKey.MeterValueSampleInterval} configuration set to ${interval ? Utils.milliSecondsToHHMMSS(interval) : interval}, not sending MeterValues`);
if (!Utils.isEmptyArray(this.messageQueue)) {
this.messageQueue.forEach((message, index) => {
this.messageQueue.splice(index, 1);
+ // TODO: evaluate the need to track performance
this.wsConnection.send(message);
});
}
// Incoming Message
case MessageType.CALL_MESSAGE:
if (this.getEnableStatistics()) {
- this.performanceStatistics.addMessage(commandName, messageType);
+ this.performanceStatistics.addRequestStatistic(commandName, messageType);
}
// Process the call
await this.ocppIncomingRequestService.handleRequest(messageId, commandName, commandPayload);
}
// eslint-disable-next-line consistent-this
- public async sendMeterValues(connectorId: number, transactionId: number, interval: number, self: OCPPRequestService, debug = false): Promise<void> {
+ public async sendMeterValues(connectorId: number, transactionId: number, interval: number, debug = false): Promise<void> {
try {
const meterValue: OCPP16MeterValue = {
timestamp: new Date().toISOString(),
sampledValue: [],
};
- const connector = self.chargingStation.getConnector(connectorId);
+ const connector = this.chargingStation.getConnector(connectorId);
// SoC measurand
- const socSampledValueTemplate = self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.STATE_OF_CHARGE);
+ const socSampledValueTemplate = this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.STATE_OF_CHARGE);
if (socSampledValueTemplate) {
const socSampledValueTemplateValue = socSampledValueTemplate.value
? Utils.getRandomFloatFluctuatedRounded(parseInt(socSampledValueTemplate.value), socSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT)
meterValue.sampledValue.push(OCPP16ServiceUtils.buildSampledValue(socSampledValueTemplate, socSampledValueTemplateValue));
const sampledValuesIndex = meterValue.sampledValue.length - 1;
if (Utils.convertToInt(meterValue.sampledValue[sampledValuesIndex].value) > 100 || debug) {
- logger.error(`${self.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesIndex].value}/100`);
+ logger.error(`${this.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesIndex].value}/100`);
}
}
// Voltage measurand
- const voltageSampledValueTemplate = self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.VOLTAGE);
+ const voltageSampledValueTemplate = this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.VOLTAGE);
if (voltageSampledValueTemplate) {
- const voltageSampledValueTemplateValue = voltageSampledValueTemplate.value ? parseInt(voltageSampledValueTemplate.value) : self.chargingStation.getVoltageOut();
+ const voltageSampledValueTemplateValue = voltageSampledValueTemplate.value ? parseInt(voltageSampledValueTemplate.value) : this.chargingStation.getVoltageOut();
const fluctuationPercent = voltageSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT;
const voltageMeasurandValue = Utils.getRandomFloatFluctuatedRounded(voltageSampledValueTemplateValue, fluctuationPercent);
- if (self.chargingStation.getNumberOfPhases() !== 3 || (self.chargingStation.getNumberOfPhases() === 3 && self.chargingStation.getMainVoltageMeterValues())) {
+ if (this.chargingStation.getNumberOfPhases() !== 3 || (this.chargingStation.getNumberOfPhases() === 3 && this.chargingStation.getMainVoltageMeterValues())) {
meterValue.sampledValue.push(OCPP16ServiceUtils.buildSampledValue(voltageSampledValueTemplate, voltageMeasurandValue));
}
- for (let phase = 1; self.chargingStation.getNumberOfPhases() === 3 && phase <= self.chargingStation.getNumberOfPhases(); phase++) {
+ for (let phase = 1; this.chargingStation.getNumberOfPhases() === 3 && phase <= this.chargingStation.getNumberOfPhases(); phase++) {
const phaseLineToNeutralValue = `L${phase}-N`;
- const voltagePhaseLineToNeutralSampledValueTemplate = self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.VOLTAGE,
+ const voltagePhaseLineToNeutralSampledValueTemplate = this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.VOLTAGE,
phaseLineToNeutralValue as OCPP16MeterValuePhase);
let voltagePhaseLineToNeutralMeasurandValue: number;
if (voltagePhaseLineToNeutralSampledValueTemplate) {
- const voltagePhaseLineToNeutralSampledValueTemplateValue = voltagePhaseLineToNeutralSampledValueTemplate.value ? parseInt(voltagePhaseLineToNeutralSampledValueTemplate.value) : self.chargingStation.getVoltageOut();
+ const voltagePhaseLineToNeutralSampledValueTemplateValue = voltagePhaseLineToNeutralSampledValueTemplate.value ? parseInt(voltagePhaseLineToNeutralSampledValueTemplate.value) : this.chargingStation.getVoltageOut();
const fluctuationPhaseToNeutralPercent = voltagePhaseLineToNeutralSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT;
voltagePhaseLineToNeutralMeasurandValue = Utils.getRandomFloatFluctuatedRounded(voltagePhaseLineToNeutralSampledValueTemplateValue, fluctuationPhaseToNeutralPercent);
}
meterValue.sampledValue.push(OCPP16ServiceUtils.buildSampledValue(voltagePhaseLineToNeutralSampledValueTemplate ?? voltageSampledValueTemplate,
voltagePhaseLineToNeutralMeasurandValue ?? voltageMeasurandValue, null, phaseLineToNeutralValue as OCPP16MeterValuePhase));
- if (self.chargingStation.getPhaseLineToLineVoltageMeterValues()) {
- const phaseLineToLineValue = `L${phase}-L${(phase + 1) % self.chargingStation.getNumberOfPhases() !== 0 ? (phase + 1) % self.chargingStation.getNumberOfPhases() : self.chargingStation.getNumberOfPhases()}`;
- const voltagePhaseLineToLineSampledValueTemplate = self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.VOLTAGE, phaseLineToLineValue as OCPP16MeterValuePhase);
+ if (this.chargingStation.getPhaseLineToLineVoltageMeterValues()) {
+ const phaseLineToLineValue = `L${phase}-L${(phase + 1) % this.chargingStation.getNumberOfPhases() !== 0 ? (phase + 1) % this.chargingStation.getNumberOfPhases() : this.chargingStation.getNumberOfPhases()}`;
+ const voltagePhaseLineToLineSampledValueTemplate = this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.VOLTAGE, phaseLineToLineValue as OCPP16MeterValuePhase);
let voltagePhaseLineToLineMeasurandValue: number;
if (voltagePhaseLineToLineSampledValueTemplate) {
const voltagePhaseLineToLineSampledValueTemplateValue = voltagePhaseLineToLineSampledValueTemplate.value ? parseInt(voltagePhaseLineToLineSampledValueTemplate.value) : Voltage.VOLTAGE_400;
}
}
// Power.Active.Import measurand
- const powerSampledValueTemplate = self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT);
+ const powerSampledValueTemplate = this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT);
let powerPerPhaseSampledValueTemplates: MeasurandPerPhaseSampledValueTemplates = {};
- if (self.chargingStation.getNumberOfPhases() === 3) {
+ if (this.chargingStation.getNumberOfPhases() === 3) {
powerPerPhaseSampledValueTemplates = {
- L1: self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT, OCPP16MeterValuePhase.L1_N),
- L2: self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT, OCPP16MeterValuePhase.L2_N),
- L3: self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT, OCPP16MeterValuePhase.L3_N),
+ L1: this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT, OCPP16MeterValuePhase.L1_N),
+ L2: this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT, OCPP16MeterValuePhase.L2_N),
+ L3: this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT, OCPP16MeterValuePhase.L3_N),
};
}
if (powerSampledValueTemplate) {
- OCPP16ServiceUtils.checkMeasurandPowerDivider(self.chargingStation, powerSampledValueTemplate.measurand);
- const errMsg = `${self.chargingStation.logPrefix()} MeterValues measurand ${powerSampledValueTemplate.measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: Unknown ${self.chargingStation.getCurrentOutType()} currentOutType in template file ${self.chargingStation.stationTemplateFile}, cannot calculate ${powerSampledValueTemplate.measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER} measurand value`;
+ OCPP16ServiceUtils.checkMeasurandPowerDivider(this.chargingStation, powerSampledValueTemplate.measurand);
+ const errMsg = `${this.chargingStation.logPrefix()} MeterValues measurand ${powerSampledValueTemplate.measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: Unknown ${this.chargingStation.getCurrentOutType()} currentOutType in template file ${this.chargingStation.stationTemplateFile}, cannot calculate ${powerSampledValueTemplate.measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER} measurand value`;
const powerMeasurandValues = {} as MeasurandValues;
const unitDivider = powerSampledValueTemplate?.unit === MeterValueUnit.KILO_WATT ? 1000 : 1;
- const maxPower = Math.round(self.chargingStation.stationInfo.maxPower / self.chargingStation.stationInfo.powerDivider);
- const maxPowerPerPhase = Math.round((self.chargingStation.stationInfo.maxPower / self.chargingStation.stationInfo.powerDivider) / self.chargingStation.getNumberOfPhases());
- switch (self.chargingStation.getCurrentOutType()) {
+ const maxPower = Math.round(this.chargingStation.stationInfo.maxPower / this.chargingStation.stationInfo.powerDivider);
+ const maxPowerPerPhase = Math.round((this.chargingStation.stationInfo.maxPower / this.chargingStation.stationInfo.powerDivider) / this.chargingStation.getNumberOfPhases());
+ switch (this.chargingStation.getCurrentOutType()) {
case CurrentType.AC:
- if (self.chargingStation.getNumberOfPhases() === 3) {
+ if (this.chargingStation.getNumberOfPhases() === 3) {
const defaultFluctuatedPowerPerPhase = powerSampledValueTemplate.value
- && Utils.getRandomFloatFluctuatedRounded(parseInt(powerSampledValueTemplate.value) / self.chargingStation.getNumberOfPhases(), powerSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT);
+ && Utils.getRandomFloatFluctuatedRounded(parseInt(powerSampledValueTemplate.value) / this.chargingStation.getNumberOfPhases(), powerSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT);
const phase1FluctuatedValue = powerPerPhaseSampledValueTemplates?.L1?.value
&& Utils.getRandomFloatFluctuatedRounded(parseInt(powerPerPhaseSampledValueTemplates.L1.value), powerPerPhaseSampledValueTemplates.L1.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT);
const phase2FluctuatedValue = powerPerPhaseSampledValueTemplates?.L2?.value
const sampledValuesIndex = meterValue.sampledValue.length - 1;
const maxPowerRounded = Utils.roundTo(maxPower / unitDivider, 2);
if (Utils.convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) > maxPowerRounded || debug) {
- logger.error(`${self.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesIndex].value}/${maxPowerRounded}`);
+ logger.error(`${this.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesIndex].value}/${maxPowerRounded}`);
}
- for (let phase = 1; self.chargingStation.getNumberOfPhases() === 3 && phase <= self.chargingStation.getNumberOfPhases(); phase++) {
+ for (let phase = 1; this.chargingStation.getNumberOfPhases() === 3 && phase <= this.chargingStation.getNumberOfPhases(); phase++) {
const phaseValue = `L${phase}-N`;
meterValue.sampledValue.push(OCPP16ServiceUtils.buildSampledValue(powerPerPhaseSampledValueTemplates[`L${phase}`] ?? powerSampledValueTemplate, powerMeasurandValues[`L${phase}`], null,
phaseValue as OCPP16MeterValuePhase));
const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1;
const maxPowerPerPhaseRounded = Utils.roundTo(maxPowerPerPhase / unitDivider, 2);
if (Utils.convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) > maxPowerPerPhaseRounded || debug) {
- logger.error(`${self.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesPerPhaseIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: phase ${meterValue.sampledValue[sampledValuesPerPhaseIndex].phase}, connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesPerPhaseIndex].value}/${maxPowerPerPhaseRounded}`);
+ logger.error(`${this.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesPerPhaseIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: phase ${meterValue.sampledValue[sampledValuesPerPhaseIndex].phase}, connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesPerPhaseIndex].value}/${maxPowerPerPhaseRounded}`);
}
}
}
// Current.Import measurand
- const currentSampledValueTemplate = self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.CURRENT_IMPORT);
+ const currentSampledValueTemplate = this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.CURRENT_IMPORT);
let currentPerPhaseSampledValueTemplates: MeasurandPerPhaseSampledValueTemplates = {};
- if (self.chargingStation.getNumberOfPhases() === 3) {
+ if (this.chargingStation.getNumberOfPhases() === 3) {
currentPerPhaseSampledValueTemplates = {
- L1: self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.CURRENT_IMPORT, OCPP16MeterValuePhase.L1),
- L2: self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.CURRENT_IMPORT, OCPP16MeterValuePhase.L2),
- L3: self.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.CURRENT_IMPORT, OCPP16MeterValuePhase.L3),
+ L1: this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.CURRENT_IMPORT, OCPP16MeterValuePhase.L1),
+ L2: this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.CURRENT_IMPORT, OCPP16MeterValuePhase.L2),
+ L3: this.chargingStation.getSampledValueTemplate(connectorId, OCPP16MeterValueMeasurand.CURRENT_IMPORT, OCPP16MeterValuePhase.L3),
};
}
if (currentSampledValueTemplate) {
- OCPP16ServiceUtils.checkMeasurandPowerDivider(self.chargingStation, currentSampledValueTemplate.measurand);
- const errMsg = `${self.chargingStation.logPrefix()} MeterValues measurand ${currentSampledValueTemplate.measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: Unknown ${self.chargingStation.getCurrentOutType()} currentOutType in template file ${self.chargingStation.stationTemplateFile}, cannot calculate ${currentSampledValueTemplate.measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER} measurand value`;
+ OCPP16ServiceUtils.checkMeasurandPowerDivider(this.chargingStation, currentSampledValueTemplate.measurand);
+ const errMsg = `${this.chargingStation.logPrefix()} MeterValues measurand ${currentSampledValueTemplate.measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: Unknown ${this.chargingStation.getCurrentOutType()} currentOutType in template file ${this.chargingStation.stationTemplateFile}, cannot calculate ${currentSampledValueTemplate.measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER} measurand value`;
const currentMeasurandValues: MeasurandValues = {} as MeasurandValues;
let maxAmperage: number;
- switch (self.chargingStation.getCurrentOutType()) {
+ switch (this.chargingStation.getCurrentOutType()) {
case CurrentType.AC:
- maxAmperage = ACElectricUtils.amperagePerPhaseFromPower(self.chargingStation.getNumberOfPhases(), self.chargingStation.stationInfo.maxPower / self.chargingStation.stationInfo.powerDivider, self.chargingStation.getVoltageOut());
- if (self.chargingStation.getNumberOfPhases() === 3) {
+ maxAmperage = ACElectricUtils.amperagePerPhaseFromPower(this.chargingStation.getNumberOfPhases(), this.chargingStation.stationInfo.maxPower / this.chargingStation.stationInfo.powerDivider, this.chargingStation.getVoltageOut());
+ if (this.chargingStation.getNumberOfPhases() === 3) {
const defaultFluctuatedAmperagePerPhase = currentSampledValueTemplate.value
&& Utils.getRandomFloatFluctuatedRounded(parseInt(currentSampledValueTemplate.value), currentSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT);
const phase1FluctuatedValue = currentPerPhaseSampledValueTemplates?.L1?.value
currentMeasurandValues.L2 = 0;
currentMeasurandValues.L3 = 0;
}
- currentMeasurandValues.allPhases = Utils.roundTo((currentMeasurandValues.L1 + currentMeasurandValues.L2 + currentMeasurandValues.L3) / self.chargingStation.getNumberOfPhases(), 2);
+ currentMeasurandValues.allPhases = Utils.roundTo((currentMeasurandValues.L1 + currentMeasurandValues.L2 + currentMeasurandValues.L3) / this.chargingStation.getNumberOfPhases(), 2);
break;
case CurrentType.DC:
- maxAmperage = DCElectricUtils.amperage(self.chargingStation.stationInfo.maxPower / self.chargingStation.stationInfo.powerDivider, self.chargingStation.getVoltageOut());
+ maxAmperage = DCElectricUtils.amperage(this.chargingStation.stationInfo.maxPower / this.chargingStation.stationInfo.powerDivider, this.chargingStation.getVoltageOut());
currentMeasurandValues.allPhases = currentSampledValueTemplate.value
? Utils.getRandomFloatFluctuatedRounded(parseInt(currentSampledValueTemplate.value), currentSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT)
: Utils.getRandomFloatRounded(maxAmperage);
meterValue.sampledValue.push(OCPP16ServiceUtils.buildSampledValue(currentSampledValueTemplate, currentMeasurandValues.allPhases));
const sampledValuesIndex = meterValue.sampledValue.length - 1;
if (Utils.convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) > maxAmperage || debug) {
- logger.error(`${self.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesIndex].value}/${maxAmperage}`);
+ logger.error(`${this.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesIndex].value}/${maxAmperage}`);
}
- for (let phase = 1; self.chargingStation.getNumberOfPhases() === 3 && phase <= self.chargingStation.getNumberOfPhases(); phase++) {
+ for (let phase = 1; this.chargingStation.getNumberOfPhases() === 3 && phase <= this.chargingStation.getNumberOfPhases(); phase++) {
const phaseValue = `L${phase}`;
meterValue.sampledValue.push(OCPP16ServiceUtils.buildSampledValue(currentPerPhaseSampledValueTemplates[phaseValue] ?? currentSampledValueTemplate,
currentMeasurandValues[phaseValue], null, phaseValue as OCPP16MeterValuePhase));
const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1;
if (Utils.convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) > maxAmperage || debug) {
- logger.error(`${self.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesPerPhaseIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: phase ${meterValue.sampledValue[sampledValuesPerPhaseIndex].phase}, connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesPerPhaseIndex].value}/${maxAmperage}`);
+ logger.error(`${this.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesPerPhaseIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: phase ${meterValue.sampledValue[sampledValuesPerPhaseIndex].phase}, connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesPerPhaseIndex].value}/${maxAmperage}`);
}
}
}
// Energy.Active.Import.Register measurand (default)
- const energySampledValueTemplate = self.chargingStation.getSampledValueTemplate(connectorId);
+ const energySampledValueTemplate = this.chargingStation.getSampledValueTemplate(connectorId);
if (energySampledValueTemplate) {
- OCPP16ServiceUtils.checkMeasurandPowerDivider(self.chargingStation, energySampledValueTemplate.measurand);
+ OCPP16ServiceUtils.checkMeasurandPowerDivider(this.chargingStation, energySampledValueTemplate.measurand);
const unitDivider = energySampledValueTemplate?.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1;
const energyMeasurandValue = energySampledValueTemplate.value
// Cumulate the fluctuated value around the static one
? Utils.getRandomFloatFluctuatedRounded(parseInt(energySampledValueTemplate.value), energySampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT)
- : Utils.getRandomInt(self.chargingStation.stationInfo.maxPower / (self.chargingStation.stationInfo.powerDivider * 3600000) * interval);
+ : Utils.getRandomInt(this.chargingStation.stationInfo.maxPower / (this.chargingStation.stationInfo.powerDivider * 3600000) * interval);
// Persist previous value on connector
if (connector && !Utils.isNullOrUndefined(connector.energyActiveImportRegisterValue) && connector.energyActiveImportRegisterValue >= 0 &&
!Utils.isNullOrUndefined(connector.transactionEnergyActiveImportRegisterValue) && connector.transactionEnergyActiveImportRegisterValue >= 0) {
connector.transactionEnergyActiveImportRegisterValue = 0;
}
meterValue.sampledValue.push(OCPP16ServiceUtils.buildSampledValue(energySampledValueTemplate,
- Utils.roundTo(self.chargingStation.getEnergyActiveImportRegisterByTransactionId(transactionId) / unitDivider, 4)));
+ Utils.roundTo(this.chargingStation.getEnergyActiveImportRegisterByTransactionId(transactionId) / unitDivider, 4)));
const sampledValuesIndex = meterValue.sampledValue.length - 1;
- const maxEnergy = Math.round(self.chargingStation.stationInfo.maxPower * 3600 / (self.chargingStation.stationInfo.powerDivider * interval));
+ const maxEnergy = Math.round(this.chargingStation.stationInfo.maxPower * 3600 / (this.chargingStation.stationInfo.powerDivider * interval));
const maxEnergyRounded = Utils.roundTo(maxEnergy / unitDivider, 4);
if (Utils.convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) > maxEnergyRounded || debug) {
- logger.error(`${self.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesIndex].value}/${maxEnergyRounded}`);
+ logger.error(`${this.chargingStation.logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesIndex].value}/${maxEnergyRounded}`);
}
}
const payload: MeterValuesRequest = {
transactionId,
meterValue,
};
- await self.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, OCPP16RequestCommand.METER_VALUES);
+ await this.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, OCPP16RequestCommand.METER_VALUES);
} catch (error) {
- self.handleRequestError(OCPP16RequestCommand.METER_VALUES, error);
+ this.handleRequestError(OCPP16RequestCommand.METER_VALUES, error);
}
}
import { MeterValue } from '../../types/ocpp/MeterValues';
import OCPPError from '../OCPPError';
import OCPPResponseService from './OCPPResponseService';
+import PerformanceStatistics from '../../utils/PerformanceStatistics';
import logger from '../../utils/Logger';
export default abstract class OCPPRequestService {
// Check if wsConnection opened and charging station registered
if (this.chargingStation.isWebSocketOpen() && (this.chargingStation.isRegistered() || commandName === RequestCommand.BOOT_NOTIFICATION)) {
if (this.chargingStation.getEnableStatistics()) {
- this.chargingStation.performanceStatistics.addMessage(commandName, messageType);
+ this.chargingStation.performanceStatistics.addRequestStatistic(commandName, messageType);
}
// Yes: Send Message
+ const beginId = PerformanceStatistics.beginMeasure(commandName);
this.chargingStation.wsConnection.send(messageToSend);
+ PerformanceStatistics.endMeasure(commandName, beginId);
} else if (commandName !== RequestCommand.BOOT_NOTIFICATION) {
// Buffer it
this.chargingStation.addToMessageQueue(messageToSend);
*/
async function responseCallback(payload: Record<string, unknown> | string, requestPayload: Record<string, unknown>): Promise<void> {
if (self.chargingStation.getEnableStatistics()) {
- self.chargingStation.performanceStatistics.addMessage(commandName, MessageType.CALL_RESULT_MESSAGE);
+ self.chargingStation.performanceStatistics.addRequestStatistic(commandName, MessageType.CALL_RESULT_MESSAGE);
}
// Send the response
await self.ocppResponseService.handleResponse(commandName as RequestCommand, payload, requestPayload);
*/
function rejectCallback(error: OCPPError): void {
if (self.chargingStation.getEnableStatistics()) {
- self.chargingStation.performanceStatistics.addMessage(commandName, MessageType.CALL_ERROR_MESSAGE);
+ self.chargingStation.performanceStatistics.addRequestStatistic(commandName, MessageType.CALL_ERROR_MESSAGE);
}
logger.debug(`${self.chargingStation.logPrefix()} Error: %j occurred when calling command %s with parameters: %j`, error, commandName, commandParams);
// Build Exception
public abstract sendAuthorize(connectorId: number, idTag?: string): Promise<AuthorizeResponse>;
public abstract sendStartTransaction(connectorId: number, idTag?: string): Promise<StartTransactionResponse>;
public abstract sendStopTransaction(transactionId: number, meterStop: number, idTag?: string, reason?: StopTransactionReason): Promise<StopTransactionResponse>;
- public abstract sendMeterValues(connectorId: number, transactionId: number, interval: number, self: OCPPRequestService): Promise<void>;
+ public abstract sendMeterValues(connectorId: number, transactionId: number, interval: number): Promise<void>;
public abstract sendTransactionBeginMeterValues(connectorId: number, transactionId: number, beginMeterValue: MeterValue): Promise<void>;
public abstract sendTransactionEndMeterValues(connectorId: number, transactionId: number, endMeterValue: MeterValue): Promise<void>;
public abstract sendDiagnosticsStatusNotification(diagnosticsStatus: DiagnosticsStatus): Promise<void>;
import { CircularArray } from '../utils/CircularArray';
-import { EntryType } from 'perf_hooks';
-export interface PerfEntry {
- name: string;
- entryType: EntryType;
- startTime: number;
- duration: number;
-}
-
-export interface CommandStatisticsData {
+export interface StatisticsData {
countRequest: number;
countResponse: number;
countError: number;
stdDevTimeMeasurement: number;
}
-export default interface CommandStatistics {
+export default interface Statistics {
id: string;
- commandsStatisticsData: Record<string, CommandStatisticsData>;
+ statisticsData: Record<string, StatisticsData>;
}
import { CircularArray, DEFAULT_CIRCULAR_ARRAY_SIZE } from './CircularArray';
-import CommandStatistics, { CommandStatisticsData, PerfEntry } from '../types/CommandStatistics';
import { IncomingRequestCommand, RequestCommand } from '../types/ocpp/Requests';
import { PerformanceEntry, PerformanceObserver, performance } from 'perf_hooks';
+import Statistics, { StatisticsData } from '../types/Statistics';
import Configuration from './Configuration';
import { MessageType } from '../types/ocpp/MessageType';
export default class PerformanceStatistics {
private objId: string;
- private commandsStatistics: CommandStatistics;
+ private performanceObserver: PerformanceObserver;
+ private statistics: Statistics;
+ private displayInterval: NodeJS.Timeout;
public constructor(objId: string) {
- this.initFunctionPerformanceObserver();
this.objId = objId;
- this.commandsStatistics = { id: this.objId ? this.objId : 'Object id not specified', commandsStatisticsData: {} };
+ this.initializePerformanceObserver();
+ this.statistics = { id: this.objId ?? 'Object id not specified', statisticsData: {} };
}
- public static timedFunction(method: (...optionalParams: any[]) => any): (...optionalParams: any[]) => any {
- return performance.timerify(method);
+ public static beginMeasure(id: string): string {
+ const beginId = 'begin' + id.charAt(0).toUpperCase() + id.slice(1);
+ performance.mark(beginId);
+ return beginId;
}
- public addMessage(command: RequestCommand | IncomingRequestCommand, messageType: MessageType): void {
+ public static endMeasure(name: string, beginId: string): void {
+ performance.measure(name, beginId);
+ }
+
+ public addRequestStatistic(command: RequestCommand | IncomingRequestCommand, messageType: MessageType): void {
switch (messageType) {
case MessageType.CALL_MESSAGE:
- if (this.commandsStatistics.commandsStatisticsData[command] && this.commandsStatistics.commandsStatisticsData[command].countRequest) {
- this.commandsStatistics.commandsStatisticsData[command].countRequest++;
+ if (this.statistics.statisticsData[command] && this.statistics.statisticsData[command].countRequest) {
+ this.statistics.statisticsData[command].countRequest++;
} else {
- this.commandsStatistics.commandsStatisticsData[command] = {} as CommandStatisticsData;
- this.commandsStatistics.commandsStatisticsData[command].countRequest = 1;
+ this.statistics.statisticsData[command] = {} as StatisticsData;
+ this.statistics.statisticsData[command].countRequest = 1;
}
break;
case MessageType.CALL_RESULT_MESSAGE:
- if (this.commandsStatistics.commandsStatisticsData[command]) {
- if (this.commandsStatistics.commandsStatisticsData[command].countResponse) {
- this.commandsStatistics.commandsStatisticsData[command].countResponse++;
+ if (this.statistics.statisticsData[command]) {
+ if (this.statistics.statisticsData[command].countResponse) {
+ this.statistics.statisticsData[command].countResponse++;
} else {
- this.commandsStatistics.commandsStatisticsData[command].countResponse = 1;
+ this.statistics.statisticsData[command].countResponse = 1;
}
} else {
- this.commandsStatistics.commandsStatisticsData[command] = {} as CommandStatisticsData;
- this.commandsStatistics.commandsStatisticsData[command].countResponse = 1;
+ this.statistics.statisticsData[command] = {} as StatisticsData;
+ this.statistics.statisticsData[command].countResponse = 1;
}
break;
case MessageType.CALL_ERROR_MESSAGE:
- if (this.commandsStatistics.commandsStatisticsData[command]) {
- if (this.commandsStatistics.commandsStatisticsData[command].countError) {
- this.commandsStatistics.commandsStatisticsData[command].countError++;
+ if (this.statistics.statisticsData[command]) {
+ if (this.statistics.statisticsData[command].countError) {
+ this.statistics.statisticsData[command].countError++;
} else {
- this.commandsStatistics.commandsStatisticsData[command].countError = 1;
+ this.statistics.statisticsData[command].countError = 1;
}
} else {
- this.commandsStatistics.commandsStatisticsData[command] = {} as CommandStatisticsData;
- this.commandsStatistics.commandsStatisticsData[command].countError = 1;
+ this.statistics.statisticsData[command] = {} as StatisticsData;
+ this.statistics.statisticsData[command].countError = 1;
}
break;
default:
}
}
- public logPerformance(entry: PerformanceEntry): void {
- this.addPerformanceTimer(entry.name, entry.duration);
- const perfEntry: PerfEntry = {
- name: entry.name,
- entryType: entry.entryType,
- startTime: entry.startTime,
- duration: entry.duration
- };
- logger.debug(`${this.logPrefix()} method or function '${entry.name}' performance entry: %j`, perfEntry);
+ public start(): void {
+ this.startDisplayInterval();
}
- public start(): void {
- this.displayInterval();
+ public stop(): void {
+ clearInterval(this.displayInterval);
+ performance.clearMarks();
+ this.performanceObserver.disconnect();
}
- private initFunctionPerformanceObserver(): void {
- const performanceObserver = new PerformanceObserver((list, observer) => {
- this.logPerformance(list.getEntries()[0]);
- observer.disconnect();
+ private initializePerformanceObserver(): void {
+ this.performanceObserver = new PerformanceObserver((list) => {
+ this.logPerformanceEntry(list.getEntries()[0]);
});
- performanceObserver.observe({ entryTypes: ['function'] });
+ this.performanceObserver.observe({ entryTypes: ['measure'] });
+ }
+
+ private logPerformanceEntry(entry: PerformanceEntry): void {
+ this.addPerformanceStatistic(entry.name, entry.duration);
+ logger.debug(`${this.logPrefix()} '${entry.name}' performance entry: %j`, entry);
}
- private display(): void {
- logger.info(this.logPrefix() + ' %j', this.commandsStatistics);
+ private logStatistics(): void {
+ logger.info(this.logPrefix() + ' %j', this.statistics);
}
- private displayInterval(): void {
+ private startDisplayInterval(): void {
if (Configuration.getStatisticsDisplayInterval() > 0) {
- setInterval(() => {
- this.display();
+ this.displayInterval = setInterval(() => {
+ this.logStatistics();
}, Configuration.getStatisticsDisplayInterval() * 1000);
logger.info(this.logPrefix() + ' displayed every ' + Utils.secondsToHHMMSS(Configuration.getStatisticsDisplayInterval()));
+ } else {
+ logger.info(this.logPrefix() + ' display interval is set to ' + Configuration.getStatisticsDisplayInterval().toString() + '. Not displaying statistics');
}
}
return Math.sqrt(totalGeometricDeviation / dataSet.length);
}
- private addPerformanceTimer(name: string, duration: number): void {
+ private addPerformanceStatistic(name: string, duration: number): void {
// Rename entry name
- const MAP_NAME = {
- startATGTransaction: 'StartATGTransaction',
- stopATGTransaction: 'StartATGTransaction'
- };
+ const MAP_NAME = {};
if (MAP_NAME[name]) {
name = MAP_NAME[name] as string;
}
// Initialize command statistics
- if (!this.commandsStatistics.commandsStatisticsData[name]) {
- this.commandsStatistics.commandsStatisticsData[name] = {} as CommandStatisticsData;
+ if (!this.statistics.statisticsData[name]) {
+ this.statistics.statisticsData[name] = {} as StatisticsData;
}
// Update current statistics timers
- this.commandsStatistics.commandsStatisticsData[name].countTimeMeasurement = this.commandsStatistics.commandsStatisticsData[name].countTimeMeasurement ? this.commandsStatistics.commandsStatisticsData[name].countTimeMeasurement + 1 : 1;
- this.commandsStatistics.commandsStatisticsData[name].currentTimeMeasurement = duration;
- this.commandsStatistics.commandsStatisticsData[name].minTimeMeasurement = this.commandsStatistics.commandsStatisticsData[name].minTimeMeasurement ? (this.commandsStatistics.commandsStatisticsData[name].minTimeMeasurement > duration ? duration : this.commandsStatistics.commandsStatisticsData[name].minTimeMeasurement) : duration;
- this.commandsStatistics.commandsStatisticsData[name].maxTimeMeasurement = this.commandsStatistics.commandsStatisticsData[name].maxTimeMeasurement ? (this.commandsStatistics.commandsStatisticsData[name].maxTimeMeasurement < duration ? duration : this.commandsStatistics.commandsStatisticsData[name].maxTimeMeasurement) : duration;
- this.commandsStatistics.commandsStatisticsData[name].totalTimeMeasurement = this.commandsStatistics.commandsStatisticsData[name].totalTimeMeasurement ? this.commandsStatistics.commandsStatisticsData[name].totalTimeMeasurement + duration : duration;
- this.commandsStatistics.commandsStatisticsData[name].avgTimeMeasurement = this.commandsStatistics.commandsStatisticsData[name].totalTimeMeasurement / this.commandsStatistics.commandsStatisticsData[name].countTimeMeasurement;
- Array.isArray(this.commandsStatistics.commandsStatisticsData[name].timeMeasurementSeries) ? this.commandsStatistics.commandsStatisticsData[name].timeMeasurementSeries.push(duration) : this.commandsStatistics.commandsStatisticsData[name].timeMeasurementSeries = new CircularArray<number>(DEFAULT_CIRCULAR_ARRAY_SIZE, duration);
- this.commandsStatistics.commandsStatisticsData[name].medTimeMeasurement = this.median(this.commandsStatistics.commandsStatisticsData[name].timeMeasurementSeries);
- this.commandsStatistics.commandsStatisticsData[name].stdDevTimeMeasurement = this.stdDeviation(this.commandsStatistics.commandsStatisticsData[name].timeMeasurementSeries);
+ this.statistics.statisticsData[name].countTimeMeasurement = this.statistics.statisticsData[name].countTimeMeasurement ? this.statistics.statisticsData[name].countTimeMeasurement + 1 : 1;
+ this.statistics.statisticsData[name].currentTimeMeasurement = duration;
+ this.statistics.statisticsData[name].minTimeMeasurement = this.statistics.statisticsData[name].minTimeMeasurement ? (this.statistics.statisticsData[name].minTimeMeasurement > duration ? duration : this.statistics.statisticsData[name].minTimeMeasurement) : duration;
+ this.statistics.statisticsData[name].maxTimeMeasurement = this.statistics.statisticsData[name].maxTimeMeasurement ? (this.statistics.statisticsData[name].maxTimeMeasurement < duration ? duration : this.statistics.statisticsData[name].maxTimeMeasurement) : duration;
+ this.statistics.statisticsData[name].totalTimeMeasurement = this.statistics.statisticsData[name].totalTimeMeasurement ? this.statistics.statisticsData[name].totalTimeMeasurement + duration : duration;
+ this.statistics.statisticsData[name].avgTimeMeasurement = this.statistics.statisticsData[name].totalTimeMeasurement / this.statistics.statisticsData[name].countTimeMeasurement;
+ Array.isArray(this.statistics.statisticsData[name].timeMeasurementSeries) ? this.statistics.statisticsData[name].timeMeasurementSeries.push(duration) : this.statistics.statisticsData[name].timeMeasurementSeries = new CircularArray<number>(DEFAULT_CIRCULAR_ARRAY_SIZE, duration);
+ this.statistics.statisticsData[name].medTimeMeasurement = this.median(this.statistics.statisticsData[name].timeMeasurementSeries);
+ this.statistics.statisticsData[name].stdDevTimeMeasurement = this.stdDeviation(this.statistics.statisticsData[name].timeMeasurementSeries);
}
private logPrefix(): string {