Add Power.Active.Import measurand support.
authorJérôme Benoit <jerome.benoit@sap.com>
Fri, 30 Oct 2020 22:40:58 +0000 (23:40 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Fri, 30 Oct 2020 22:40:58 +0000 (23:40 +0100)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/assets/station-templates/abb.station-template.json
src/assets/station-templates/evlink.station-template.json
src/assets/station-templates/keba.station-template.json
src/assets/station-templates/schneider-imredd.station-template.json
src/assets/station-templates/schneider.station-template.json
src/assets/station-templates/siemens.station-template.json
src/charging-station/ChargingStation.js
src/utils/Utils.js

index 55e5c174d60ab4ac1c89be6bf182ab1fff4471ee..155526efb29141bee22f78e19d60310c9eb3959d 100644 (file)
@@ -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",
           "context": "Sample.Periodic",
           "measurand": "Voltage"
         },
+        {
+          "unit": "W",
+          "context": "Sample.Periodic",
+          "measurand": "Power.Active.Import"
+        },
         {
           "unit": "A",
           "context": "Sample.Periodic",
           "context": "Sample.Periodic",
           "measurand": "Voltage"
         },
+        {
+          "unit": "W",
+          "context": "Sample.Periodic",
+          "measurand": "Power.Active.Import"
+        },
         {
           "unit": "A",
           "context": "Sample.Periodic",
index 75b8f2e342cc22b09bb2b6d2ebf11740c26e8586..caa18f745b6397695e6bf639eabebd649e464cba 100644 (file)
@@ -10,6 +10,7 @@
   "numberOfPhases": 1,
   "numberOfConnectors": 1,
   "randomConnectors": false,
+  "voltageOut": 231,
   "Configuration": {
     "configurationKey": [
       {
index 97fd48ea00c9afe59abb7b6581d42961b06d30a5..5c0834253c2ae0bf8ed0ed51c4b06bc588f0954f 100644 (file)
@@ -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",
           "unit": "V",
           "measurand": "Voltage"
         },
+        {
+          "unit": "W",
+          "measurand": "Power.Active.Import"
+        },
         {
           "unit": "A",
           "measurand": "Current.Import"
           "unit": "V",
           "measurand": "Voltage"
         },
+        {
+          "unit": "W",
+          "measurand": "Power.Active.Import"
+        },
         {
           "unit": "A",
           "measurand": "Current.Import"
index c467d3be55d3a17ea08915447b8240c78d3cca05..40529ff9ad554e0284f679dde6331b96cf99c01c 100644 (file)
@@ -9,6 +9,7 @@
   "powerUnit": "W",
   "numberOfConnectors": 1,
   "randomConnectors": false,
+  "voltageOut": 231,
   "Configuration": {
     "configurationKey": [
       {
index 2961938ee61fa10869d2fe091bc2ac143d967904..9b442401bd8a3ff4e67eff9991fe19324dff1646 100644 (file)
@@ -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",
     "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"
         }
       ]
     }
index e8e234a2ef02d952df2e2410cfa804175f35bf77..ddf1c9b71b1c004d8d701ea4f8380ad04755a7e0 100644 (file)
@@ -8,6 +8,7 @@
   "powerUnit": "W",
   "numberOfConnectors": 2,
   "randomConnectors": false,
+  "voltageOut": 240,
   "Configuration": {
     "configurationKey": [
       {
index 6f9ec98eb0fe80b3e27a7580474895ff11e2ac31..f5e1f460021394d7f427b21a99625a342f5aabcd 100644 (file)
@@ -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);
index 6b6aba4292e7b77fc5af4406bc61f45c8ccaa13f..9d071a415faabcb5a086ce1a6ab765d8320736bc 100644 (file)
@@ -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) {