From d71ce3fa734fcefeb3dce31d78968b847c625c92 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Thu, 16 Nov 2023 12:35:04 +0100 Subject: [PATCH] feat: ensure measurand min value are taken into account MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../ocpp/1.6/OCPP16ServiceUtils.ts | 54 +++++++++++++------ src/charging-station/ocpp/OCPPServiceUtils.ts | 15 ++++-- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts b/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts index c329a2c8..391f2f0a 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts @@ -287,7 +287,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { const connectorMaximumPowerPerPhase = Math.round( connectorMaximumAvailablePower / chargingStation.getNumberOfPhases(), ); - const connectorMinimumPower = Math.round(powerSampledValueTemplate.minimumValue!) ?? 0; + const connectorMinimumPower = Math.round(powerSampledValueTemplate.minimumValue ?? 0); const connectorMinimumPowerPerPhase = Math.round( connectorMinimumPower / chargingStation.getNumberOfPhases(), ); @@ -300,10 +300,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( powerSampledValueTemplate.value, connectorMaximumPower / unitDivider, + connectorMinimumPower / unitDivider, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumPower / unitDivider, + fallbackValue: connectorMinimumPower / unitDivider, }, ) / chargingStation.getNumberOfPhases(), powerSampledValueTemplate.fluctuationPercent ?? @@ -315,10 +316,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( powerPerPhaseSampledValueTemplates.L1.value, connectorMaximumPowerPerPhase / unitDivider, + connectorMinimumPowerPerPhase / unitDivider, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumPowerPerPhase / unitDivider, + fallbackValue: connectorMinimumPowerPerPhase / unitDivider, }, ), powerPerPhaseSampledValueTemplates.L1.fluctuationPercent ?? @@ -330,10 +332,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( powerPerPhaseSampledValueTemplates.L2.value, connectorMaximumPowerPerPhase / unitDivider, + connectorMinimumPowerPerPhase / unitDivider, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumPowerPerPhase / unitDivider, + fallbackValue: connectorMinimumPowerPerPhase / unitDivider, }, ), powerPerPhaseSampledValueTemplates.L2.fluctuationPercent ?? @@ -345,10 +348,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( powerPerPhaseSampledValueTemplates.L3.value, connectorMaximumPowerPerPhase / unitDivider, + connectorMinimumPowerPerPhase / unitDivider, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumPowerPerPhase / unitDivider, + fallbackValue: connectorMinimumPowerPerPhase / unitDivider, }, ), powerPerPhaseSampledValueTemplates.L3.fluctuationPercent ?? @@ -381,10 +385,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( powerSampledValueTemplate.value, connectorMaximumPower / unitDivider, + connectorMinimumPower / unitDivider, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumPower / unitDivider, + fallbackValue: connectorMinimumPower / unitDivider, }, ), powerSampledValueTemplate.fluctuationPercent ?? @@ -408,10 +413,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( powerSampledValueTemplate.value, connectorMaximumPower / unitDivider, + connectorMinimumPower / unitDivider, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumPower / unitDivider, + fallbackValue: connectorMinimumPower / unitDivider, }, ), powerSampledValueTemplate.fluctuationPercent ?? @@ -558,10 +564,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( currentSampledValueTemplate.value, connectorMaximumAmperage, + connectorMinimumAmperage, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumAmperage, + fallbackValue: connectorMinimumAmperage, }, ), currentSampledValueTemplate.fluctuationPercent ?? @@ -573,10 +580,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( currentPerPhaseSampledValueTemplates.L1.value, connectorMaximumAmperage, + connectorMinimumAmperage, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumAmperage, + fallbackValue: connectorMinimumAmperage, }, ), currentPerPhaseSampledValueTemplates.L1.fluctuationPercent ?? @@ -588,10 +596,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( currentPerPhaseSampledValueTemplates.L2.value, connectorMaximumAmperage, + connectorMinimumAmperage, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumAmperage, + fallbackValue: connectorMinimumAmperage, }, ), currentPerPhaseSampledValueTemplates.L2.fluctuationPercent ?? @@ -603,10 +612,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( currentPerPhaseSampledValueTemplates.L3.value, connectorMaximumAmperage, + connectorMinimumAmperage, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumAmperage, + fallbackValue: connectorMinimumAmperage, }, ), currentPerPhaseSampledValueTemplates.L3.fluctuationPercent ?? @@ -630,10 +640,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( currentSampledValueTemplate.value, connectorMaximumAmperage, + connectorMinimumAmperage, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumAmperage, + fallbackValue: connectorMinimumAmperage, }, ), currentSampledValueTemplate.fluctuationPercent ?? @@ -659,10 +670,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( currentSampledValueTemplate.value, connectorMaximumAmperage, + connectorMinimumAmperage, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, - defaultValue: connectorMinimumAmperage, + fallbackValue: connectorMinimumAmperage, }, ), currentSampledValueTemplate.fluctuationPercent ?? @@ -752,20 +764,26 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { (connectorMaximumAvailablePower * interval) / (3600 * 1000), 2, ); + const connectorMinimumEnergyRounded = roundTo( + energySampledValueTemplate.minimumValue ?? 0, + 2, + ); const energyValueRounded = isNotEmptyString(energySampledValueTemplate.value) ? // Cumulate the fluctuated value around the static one getRandomFloatFluctuatedRounded( OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue( energySampledValueTemplate.value, connectorMaximumEnergyRounded, + connectorMinimumEnergyRounded, { limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues, unitMultiplier: unitDivider, + fallbackValue: connectorMinimumEnergyRounded, }, ), energySampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT, ) - : getRandomFloatRounded(connectorMaximumEnergyRounded); + : getRandomFloatRounded(connectorMaximumEnergyRounded, connectorMinimumEnergyRounded); // Persist previous value on connector if (connector) { if ( @@ -792,12 +810,16 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { ), ); const sampledValuesIndex = meterValue.sampledValue.length - 1; - if (energyValueRounded > connectorMaximumEnergyRounded || debug) { + if ( + energyValueRounded > connectorMaximumEnergyRounded || + energyValueRounded < connectorMinimumEnergyRounded || + debug + ) { logger.error( `${chargingStation.logPrefix()} MeterValues measurand ${ meterValue.sampledValue[sampledValuesIndex].measurand ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER - }: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${energyValueRounded}/${connectorMaximumEnergyRounded}, duration: ${interval}ms`, + }: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumEnergyRounded}/${energyValueRounded}/${connectorMaximumEnergyRounded}, duration: ${interval}ms`, ); } } diff --git a/src/charging-station/ocpp/OCPPServiceUtils.ts b/src/charging-station/ocpp/OCPPServiceUtils.ts index 8036079a..46603f0b 100644 --- a/src/charging-station/ocpp/OCPPServiceUtils.ts +++ b/src/charging-station/ocpp/OCPPServiceUtils.ts @@ -41,6 +41,7 @@ import { isNotEmptyString, logPrefix, logger, + max, min, } from '../../utils'; @@ -418,22 +419,26 @@ export class OCPPServiceUtils { protected static getLimitFromSampledValueTemplateCustomValue( value: string, - limit: number, - options?: { limitationEnabled?: boolean; unitMultiplier?: number; defaultValue?: number }, + maxLimit: number, + minLimit: number, + options?: { limitationEnabled?: boolean; fallbackValue?: number; unitMultiplier?: number }, ): number { options = { ...{ limitationEnabled: true, unitMultiplier: 1, - defaultValue: 0, + fallbackValue: 0, }, ...options, }; const parsedValue = parseInt(value); if (options?.limitationEnabled) { - return min((!isNaN(parsedValue) ? parsedValue : Infinity) * options.unitMultiplier!, limit); + return max( + min((!isNaN(parsedValue) ? parsedValue : Infinity) * options.unitMultiplier!, maxLimit), + minLimit, + ); } - return (!isNaN(parsedValue) ? parsedValue : options.defaultValue!) * options.unitMultiplier!; + return (!isNaN(parsedValue) ? parsedValue : options.fallbackValue!) * options.unitMultiplier!; } private static isIdTagLocalAuthorized(chargingStation: ChargingStation, idTag: string): boolean { -- 2.34.1