From fee830211b36e79b9d89d4c0d689d02bc6da4156 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Fri, 30 Oct 2020 23:40:58 +0100 Subject: [PATCH] Add Power.Active.Import measurand support. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../abb.station-template.json | 12 +++- .../evlink.station-template.json | 1 + .../keba.station-template.json | 10 ++- .../schneider-imredd.station-template.json | 1 + .../schneider.station-template.json | 25 ++++++-- .../siemens.station-template.json | 1 + src/charging-station/ChargingStation.js | 64 ++++++++++++++++++- src/utils/Utils.js | 9 +-- 8 files changed, 109 insertions(+), 14 deletions(-) diff --git a/src/assets/station-templates/abb.station-template.json b/src/assets/station-templates/abb.station-template.json index 55e5c174..155526ef 100644 --- a/src/assets/station-templates/abb.station-template.json +++ b/src/assets/station-templates/abb.station-template.json @@ -18,7 +18,7 @@ { "key": "MeterValuesSampledData", "readonly": false, - "value": "SoC,Energy.Active.Import.Register,Current.Import,Voltage" + "value": "SoC,Energy.Active.Import.Register,Power.Active.Import,Current.Import,Voltage" }, { "key": "MeterValueSampleInterval", @@ -74,6 +74,11 @@ "context": "Sample.Periodic", "measurand": "Voltage" }, + { + "unit": "W", + "context": "Sample.Periodic", + "measurand": "Power.Active.Import" + }, { "unit": "A", "context": "Sample.Periodic", @@ -98,6 +103,11 @@ "context": "Sample.Periodic", "measurand": "Voltage" }, + { + "unit": "W", + "context": "Sample.Periodic", + "measurand": "Power.Active.Import" + }, { "unit": "A", "context": "Sample.Periodic", diff --git a/src/assets/station-templates/evlink.station-template.json b/src/assets/station-templates/evlink.station-template.json index 75b8f2e3..caa18f74 100644 --- a/src/assets/station-templates/evlink.station-template.json +++ b/src/assets/station-templates/evlink.station-template.json @@ -10,6 +10,7 @@ "numberOfPhases": 1, "numberOfConnectors": 1, "randomConnectors": false, + "voltageOut": 231, "Configuration": { "configurationKey": [ { diff --git a/src/assets/station-templates/keba.station-template.json b/src/assets/station-templates/keba.station-template.json index 97fd48ea..5c083425 100644 --- a/src/assets/station-templates/keba.station-template.json +++ b/src/assets/station-templates/keba.station-template.json @@ -13,7 +13,7 @@ { "key": "MeterValuesSampledData", "readonly": false, - "value": "Energy.Active.Import.Register,Current.Import,Voltage" + "value": "Energy.Active.Import.Register,Power.Active.Import,Current.Import,Voltage" }, { "key": "MeterValueSampleInterval", @@ -54,6 +54,10 @@ "unit": "V", "measurand": "Voltage" }, + { + "unit": "W", + "measurand": "Power.Active.Import" + }, { "unit": "A", "measurand": "Current.Import" @@ -69,6 +73,10 @@ "unit": "V", "measurand": "Voltage" }, + { + "unit": "W", + "measurand": "Power.Active.Import" + }, { "unit": "A", "measurand": "Current.Import" diff --git a/src/assets/station-templates/schneider-imredd.station-template.json b/src/assets/station-templates/schneider-imredd.station-template.json index c467d3be..40529ff9 100644 --- a/src/assets/station-templates/schneider-imredd.station-template.json +++ b/src/assets/station-templates/schneider-imredd.station-template.json @@ -9,6 +9,7 @@ "powerUnit": "W", "numberOfConnectors": 1, "randomConnectors": false, + "voltageOut": 231, "Configuration": { "configurationKey": [ { diff --git a/src/assets/station-templates/schneider.station-template.json b/src/assets/station-templates/schneider.station-template.json index 2961938e..9b442401 100644 --- a/src/assets/station-templates/schneider.station-template.json +++ b/src/assets/station-templates/schneider.station-template.json @@ -9,12 +9,13 @@ "powerUnit": "W", "numberOfConnectors": 2, "randomConnectors": false, + "voltageOut": 231, "Configuration": { "configurationKey": [ { "key": "MeterValuesSampledData", "readonly": false, - "value": "Energy.Active.Import.Register" + "value": "Energy.Active.Import.Register,Current.Import,Voltage" }, { "key": "MeterValueSampleInterval", @@ -52,16 +53,30 @@ "1": { "MeterValues": [ { - "unit": "Wh", - "context": "Sample.Periodic" + "unit": "V", + "measurand": "Voltage" + }, + { + "unit": "A", + "measurand": "Current.Import" + }, + { + "unit": "Wh" } ] }, "2": { "MeterValues": [ { - "unit": "Wh", - "context": "Sample.Periodic" + "unit": "V", + "measurand": "Voltage" + }, + { + "unit": "A", + "measurand": "Current.Import" + }, + { + "unit": "Wh" } ] } diff --git a/src/assets/station-templates/siemens.station-template.json b/src/assets/station-templates/siemens.station-template.json index e8e234a2..ddf1c9b7 100644 --- a/src/assets/station-templates/siemens.station-template.json +++ b/src/assets/station-templates/siemens.station-template.json @@ -8,6 +8,7 @@ "powerUnit": "W", "numberOfConnectors": 2, "randomConnectors": false, + "voltageOut": 240, "Configuration": { "configurationKey": [ { diff --git a/src/charging-station/ChargingStation.js b/src/charging-station/ChargingStation.js index 6f9ec98e..f5e1f460 100644 --- a/src/charging-station/ChargingStation.js +++ b/src/charging-station/ChargingStation.js @@ -672,6 +672,66 @@ export default class ChargingStation { phase: phaseValue, }); } + // Power.Active.Import measurand + } else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === 'Power.Active.Import' && self._getConfigurationKey('MeterValuesSampledData').value.includes('Power.Active.Import')) { + // FIXME: factor out powerDivider checks + if (Utils.isUndefined(self._stationInfo.powerDivider)) { + const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: powerDivider is undefined`; + logger.error(errMsg); + throw Error(errMsg); + } else if (self._stationInfo.powerDivider && self._stationInfo.powerDivider <= 0) { + const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: powerDivider have zero or below value ${self._stationInfo.powerDivider}`; + logger.error(errMsg); + throw Error(errMsg); + } + const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: Unknown ${self._getPowerOutType()} powerOutType in template file ${self._stationTemplateFile}, cannot calculate ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'} measurand value`; + const powerMeasurandValues = {}; + const maxPower = Math.round(self._stationInfo.maxPower / self._stationInfo.powerDivider); + const maxPowerPerPhase = Math.round((self._stationInfo.maxPower / self._stationInfo.powerDivider) / self._getNumberOfPhases()); + switch (self._getPowerOutType()) { + case 'AC': + if (Utils.isUndefined(meterValuesTemplate[index].value)) { + powerMeasurandValues.L1 = Utils.getRandomFloatRounded(maxPowerPerPhase); + powerMeasurandValues.L2 = 0; + powerMeasurandValues.L3 = 0; + if (self._getNumberOfPhases() === 3) { + powerMeasurandValues.L2 = Utils.getRandomFloatRounded(maxPowerPerPhase); + powerMeasurandValues.L3 = Utils.getRandomFloatRounded(maxPowerPerPhase); + } + powerMeasurandValues.all = Utils.roundTo(powerMeasurandValues.L1 + powerMeasurandValues.L2 + powerMeasurandValues.L3, 2); + } + break; + case 'DC': + if (Utils.isUndefined(meterValuesTemplate[index].value)) { + powerMeasurandValues.all = Utils.getRandomFloatRounded(maxPower); + } + break; + default: + logger.error(errMsg); + throw Error(errMsg); + } + sampledValues.sampledValue.push({ + ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? {unit: meterValuesTemplate[index].unit} : {unit: 'W'}, + ...!Utils.isUndefined(meterValuesTemplate[index].context) && {context: meterValuesTemplate[index].context}, + measurand: meterValuesTemplate[index].measurand, + ...!Utils.isUndefined(meterValuesTemplate[index].location) && {location: meterValuesTemplate[index].location}, + ...!Utils.isUndefined(meterValuesTemplate[index].value) ? {value: meterValuesTemplate[index].value} : {value: powerMeasurandValues.all}, + }); + const sampledValuesIndex = sampledValues.sampledValue.length - 1; + if (sampledValues.sampledValue[sampledValuesIndex].value > maxPower || debug) { + logger.error(`${self._logPrefix()} MeterValues measurand ${sampledValues.sampledValue[sampledValuesIndex].measurand ? sampledValues.sampledValue[sampledValuesIndex].measurand : 'Energy.Active.Import.Register'}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${sampledValues.sampledValue[sampledValuesIndex].value}/${maxPower}`); + } + for (let phase = 1; self._getPowerOutType() === 'AC' && self._getNumberOfPhases() === 3 && phase <= self._getNumberOfPhases(); phase++) { + const phaseValue = `L${phase}-N`; + sampledValues.sampledValue.push({ + ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? {unit: meterValuesTemplate[index].unit} : {unit: 'W'}, + ...!Utils.isUndefined(meterValuesTemplate[index].context) && {context: meterValuesTemplate[index].context}, + ...!Utils.isUndefined(meterValuesTemplate[index].measurand) && {measurand: meterValuesTemplate[index].measurand}, + ...!Utils.isUndefined(meterValuesTemplate[index].location) && {location: meterValuesTemplate[index].location}, + ...!Utils.isUndefined(meterValuesTemplate[index].value) ? {value: meterValuesTemplate[index].value} : {value: powerMeasurandValues[`L${phase}`]}, + phase: phaseValue, + }); + } // Current.Import measurand } else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === 'Current.Import' && self._getConfigurationKey('MeterValuesSampledData').value.includes('Current.Import')) { // FIXME: factor out powerDivider checks @@ -703,7 +763,9 @@ export default class ChargingStation { break; case 'DC': maxAmperage = ElectricUtils.ampTotalFromPower(self._stationInfo.maxPower / self._stationInfo.powerDivider, self._getVoltageOut()); - currentMeasurandValues.all = Utils.getRandomFloatRounded(maxAmperage); + if (Utils.isUndefined(meterValuesTemplate[index].value)) { + currentMeasurandValues.all = Utils.getRandomFloatRounded(maxAmperage); + } break; default: logger.error(errMsg); diff --git a/src/utils/Utils.js b/src/utils/Utils.js index 6b6aba42..9d071a41 100644 --- a/src/utils/Utils.js +++ b/src/utils/Utils.js @@ -100,17 +100,14 @@ export default class Utils { } static getRandomFloat(max, min = 0) { - if (min) { - return Math.random() * (max - min + 1) + min; - } - return Math.random() * max + 1; + return Math.random() < 0.5 ? (1 - Math.random()) * (max - min) + min : Math.random() * (max - min) + min; } static getRandomInt(max, min = 0) { if (min) { - return Math.floor(Utils.getRandomFloat(max, min)); + return Math.floor(Math.random() * (max - min + 1) + min); } - return Math.floor(Utils.getRandomFloat(max)); + return Math.floor(Math.random() * max + 1); } static roundTo(number, scale) { -- 2.34.1