Various initialization fixes.
authorJérôme Benoit <jerome.benoit@sap.com>
Sat, 17 Oct 2020 20:47:04 +0000 (22:47 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Sat, 17 Oct 2020 20:47:04 +0000 (22:47 +0200)
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.mougins69.station-template.json
src/assets/station-templates/virtual-simple-atg.station-template.json
src/assets/station-templates/virtual-simple.station-template.json
src/assets/station-templates/virtual.station-template.json
src/charging-station/AutomaticTransactionGenerator.js
src/charging-station/ChargingStation.js

index 161febe4c3ffb37626b6e8a59d5b5b2fb3ec0eaf..f256c37e61d059141b4dded5b081140076985ee4 100644 (file)
@@ -1,11 +1,13 @@
 {
   "authorizationFile": "./src/assets/authorization-tags.json",
   "baseName": "CS-ABB",
-  "chargePointModel": "ABB 5678",
+  "chargePointModel": "MD_TERRA_53",
   "chargePointVendor": "ABB",
+  "firmwareVersion": "4.0.4.22",
   "power": 50000,
   "powerUnit": "W",
   "numberOfConnectors": 2,
+  "useConnectorId0": false,
   "randomConnectors": false,
   "Configuration": {
     "configurationKey": [
     ]
   },
   "AutomaticTransactionGenerator": {
-    "enable": false,
+    "enable": true,
     "minDuration": 60,
     "maxDuration": 80,
     "minDelayBetweenTwoTransaction": 15,
     "maxDelayBetweenTwoTransaction": 30,
     "probabilityOfStart": 1,
-    "stopAutomaticTransactionGeneratorAfterHours": 0.3
+    "stopAfterHours": 0.3,
+    "stopOnConnectionFailure": true
   },
   "Connectors": {
     "0": {},
index 95251174c232148baa324b544120da64f28dab67..41ba8e3ebafedf9f393733b810b61234cdff1635 100644 (file)
@@ -43,7 +43,8 @@
     "minDelayBetweenTwoTransaction": 15,
     "maxDelayBetweenTwoTransaction": 30,
     "probabilityOfStart": 1,
-    "stopAutomaticTransactionGeneratorAfterHours": 0.3
+    "stopAfterHours": 0.3,
+    "stopOnConnectionFailure": false
   },
   "Connectors": {
     "1": {
index 8c00f7cc767ab2217d46aafeccd858a9f47fd024..9366edd38d4b760a33c35fde2a42ba84fcd845be 100644 (file)
@@ -3,6 +3,7 @@
   "baseName": "CS-KEBA",
   "chargePointModel": "KC-P30-ESS400C2-E0R",
   "chargePointVendor": "Keba AG",
+  "firmwareVersion": "1.10.1",
   "power": 22000,
   "powerUnit": "W",
   "numberOfConnectors": 1,
@@ -43,7 +44,8 @@
     "minDelayBetweenTwoTransaction": 15,
     "maxDelayBetweenTwoTransaction": 30,
     "probabilityOfStart": 1,
-    "stopAutomaticTransactionGeneratorAfterHours": 0.3
+    "stopAfterHours": 0.3,
+    "stopOnConnectionFailure": false
   },
   "Connectors": {
     "1": {
index 26c92a672f9a6ddebde84acca5f25e993d7aeddb..0c7c53b6a8e960fc5fe32ea68207c9b653cdd3ed 100644 (file)
@@ -43,7 +43,8 @@
     "minDelayBetweenTwoTransaction": 15,
     "maxDelayBetweenTwoTransaction": 30,
     "probabilityOfStart": 1,
-    "stopAutomaticTransactionGeneratorAfterHours": 0.3
+    "stopAfterHours": 0.3,
+    "stopOnConnectionFailure": false
   },
   "Connectors": {
     "1": {
index 26c92a672f9a6ddebde84acca5f25e993d7aeddb..0c7c53b6a8e960fc5fe32ea68207c9b653cdd3ed 100644 (file)
@@ -43,7 +43,8 @@
     "minDelayBetweenTwoTransaction": 15,
     "maxDelayBetweenTwoTransaction": 30,
     "probabilityOfStart": 1,
-    "stopAutomaticTransactionGeneratorAfterHours": 0.3
+    "stopAfterHours": 0.3,
+    "stopOnConnectionFailure": false
   },
   "Connectors": {
     "1": {
index 87a538af5faf283386109fbfe3533595f615c19c..9eecbc4816f0fa3619d91c22e4f455e7de65b38e 100644 (file)
@@ -44,7 +44,8 @@
     "minDelayBetweenTwoTransaction": 15,
     "maxDelayBetweenTwoTransaction": 30,
     "probabilityOfStart": 1,
-    "stopAutomaticTransactionGeneratorAfterHours": 0.3
+    "stopAfterHours": 0.3,
+    "stopOnConnectionFailure": false
   },
   "Connectors": {
     "1": {
index fcc809558f10225f16a1be430fd2128b6a6160ca..808d4c0c90abef2ba7b07579c7e7fcb14ec815fe 100644 (file)
@@ -43,7 +43,8 @@
     "minDelayBetweenTwoTransaction": 15,
     "maxDelayBetweenTwoTransaction": 30,
     "probabilityOfStart": 1,
-    "stopAutomaticTransactionGeneratorAfterHours": 0.3
+    "stopAfterHours": 0.3,
+    "stopOnConnectionFailure": false
   },
   "Connectors": {
     "0": {},
index 0bef7cfdc97eac60d966777faa5ca931ac25b7ae..f2cc557c2956d32cfa00710a084b54f2b42db286 100644 (file)
@@ -43,7 +43,8 @@
     "minDelayBetweenTwoTransaction": 15,
     "maxDelayBetweenTwoTransaction": 30,
     "probabilityOfStart": 1,
-    "stopAutomaticTransactionGeneratorAfterHours": 0.3
+    "stopAfterHours": 0.3,
+    "stopOnConnectionFailure": false
   },
   "Connectors": {
     "0": {},
index 6eb7d2eca5eb0d8b960894dc48c5bf136bfd5b80..2b8a2bc18fc0e842ccdf40723378bfeccf3fc79c 100644 (file)
@@ -43,7 +43,8 @@
     "minDelayBetweenTwoTransaction": 15,
     "maxDelayBetweenTwoTransaction": 30,
     "probabilityOfStart": 1,
-    "stopAutomaticTransactionGeneratorAfterHours": 0.3
+    "stopAfterHours": 0.3,
+    "stopOnConnectionFailure": false
   },
   "Connectors": {
     "0": {},
index e30fafd83dc8163e2c793e600968144fbf54d47f..6d46afee9c529a29506052b032ecdc83197c8202 100644 (file)
@@ -5,7 +5,7 @@ const {performance, PerformanceObserver} = require('perf_hooks');
 class AutomaticTransactionGenerator {
   constructor(chargingStation) {
     this._chargingStation = chargingStation;
-    this._timeToStop = false;
+    this._timeToStop = true;
     this._performanceObserver = new PerformanceObserver((list) => {
       const entry = list.getEntries()[0];
       this._chargingStation._statistics.logPerformance(entry, 'AutomaticTransactionGenerator');
@@ -13,9 +13,13 @@ class AutomaticTransactionGenerator {
     });
   }
 
+  get timeToStop() {
+    return this._timeToStop;
+  }
+
   _basicFormatLog(connectorId = null) {
     if (connectorId) {
-      return Utils.basicFormatLog(' ' + this._chargingStation._stationInfo.name + ' ATG on connector #' + connectorId);
+      return Utils.basicFormatLog(' ' + this._chargingStation._stationInfo.name + ' ATG on connector #' + connectorId + ':');
     }
     return Utils.basicFormatLog(' ' + this._chargingStation._stationInfo.name + ' ATG:');
   }
@@ -33,12 +37,12 @@ class AutomaticTransactionGenerator {
 
   async start() {
     this._timeToStop = false;
-    if (this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAutomaticTransactionGeneratorAfterHours &&
-      this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAutomaticTransactionGeneratorAfterHours > 0) {
-      logger.info(this._basicFormatLog() + ' ATG will stop in ' + Utils.secondstoHHMMSS(this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAutomaticTransactionGeneratorAfterHours * 3600));
+    if (this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAfterHours &&
+      this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAfterHours > 0) {
+      logger.info(this._basicFormatLog() + ' ATG will stop in ' + Utils.secondstoHHMMSS(this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAfterHours * 3600));
       setTimeout(() => {
         this.stop();
-      }, this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAutomaticTransactionGeneratorAfterHours * 3600 * 1000);
+      }, this._chargingStation._stationInfo.AutomaticTransactionGenerator.stopAfterHours * 3600 * 1000);
     }
     for (const connector in this._chargingStation._connectors) {
       if (connector > 0) {
@@ -49,7 +53,8 @@ class AutomaticTransactionGenerator {
 
   async startConnector(connectorId) {
     do {
-      const wait = Utils.getRandomInt(this._chargingStation._stationInfo.AutomaticTransactionGenerator.maxDelayBetweenTwoTransaction, this._chargingStation._stationInfo.AutomaticTransactionGenerator.minDelayBetweenTwoTransaction) * 1000;
+      const wait = Utils.getRandomInt(this._chargingStation._stationInfo.AutomaticTransactionGenerator.maxDelayBetweenTwoTransaction,
+          this._chargingStation._stationInfo.AutomaticTransactionGenerator.minDelayBetweenTwoTransaction) * 1000;
       logger.info(this._basicFormatLog(connectorId) + ' wait for ' + Utils.secondstoHHMMSS(wait / 1000));
       await Utils.sleep(wait);
       if (this._timeToStop) break;
@@ -66,7 +71,8 @@ class AutomaticTransactionGenerator {
           await Utils.sleep(2000);
         } else {
           // Wait until end of transaction
-          const wait = Utils.getRandomInt(this._chargingStation._stationInfo.AutomaticTransactionGenerator.maxDuration, this._chargingStation._stationInfo.AutomaticTransactionGenerator.minDuration) * 1000;
+          const wait = Utils.getRandomInt(this._chargingStation._stationInfo.AutomaticTransactionGenerator.maxDuration,
+              this._chargingStation._stationInfo.AutomaticTransactionGenerator.minDuration) * 1000;
           logger.info(this._basicFormatLog(connectorId) + ' transaction ' + this._chargingStation._connectors[connectorId].transactionId + ' will stop in ' + Utils.secondstoHHMMSS(wait / 1000));
           await Utils.sleep(wait);
           // Stop transaction
index ebc3509ce97c193dde369d4f9269d5e6a65b705f..38e9f582c1661fcb765e5d6c4da819ad579c09af 100644 (file)
@@ -23,6 +23,8 @@ class ChargingStation {
     this._messageQueue = [];
 
     this._isSocketRestart = false;
+
+    this._authorizedTags = this._getAuthorizedTags();
   }
 
   _initialize() {
@@ -30,9 +32,10 @@ class ChargingStation {
     this._bootNotificationMessage = {
       chargePointModel: this._stationInfo.chargePointModel,
       chargePointVendor: this._stationInfo.chargePointVendor,
+      // chargePointSerialNumber: this._stationInfo.chargePointSerialNumber,
+      firmwareVersion: this._stationInfo.firmwareVersion ? this._stationInfo.firmwareVersion : '',
     };
     this._configuration = this._getConfiguration();
-    this._authorizedTags = this._getAuthorizedTags();
     this._supervisionUrl = this._getSupervisionURL();
     this._statistics = new Statistics(this._stationInfo.name);
     this._performanceObserver = new PerformanceObserver((list) => {
@@ -148,13 +151,13 @@ class ChargingStation {
   }
 
   async start() {
+    this._url = this._supervisionUrl + '/' + this._stationInfo.name;
+    this._wsConnection = new WebSocket(this._url, 'ocpp1.6');
     logger.info(this._basicFormatLog() + ' Will communicate with ' + this._supervisionUrl);
     // Monitor authorization file
     this._startAuthorizationFileMonitoring();
     // Monitor station template file
     this._startStationTemplateFileMonitoring();
-    this._url = this._supervisionUrl + '/' + this._stationInfo.name;
-    this._wsConnection = new WebSocket(this._url, 'ocpp1.6');
     // Handle Socket incoming messages
     this._wsConnection.on('message', this.onMessage.bind(this));
     // Handle Socket error
@@ -306,9 +309,11 @@ class ChargingStation {
       clearInterval(this._heartbeatSetInterval);
       this._heartbeatSetInterval = null;
     }
-    // Stop the ATG
-    if (this._stationInfo.AutomaticTransactionGenerator.enable && this._automaticTransactionGeneration &&
-      !this._automaticTransactionGeneration._timeToStop) {
+    // Stop the ATG if needed
+    if (Utils.convertToBoolean(this._stationInfo.AutomaticTransactionGenerator.enable) &&
+      Utils.convertToBoolean(this._stationInfo.AutomaticTransactionGenerator.stopOnConnectionFailure) &&
+      this._automaticTransactionGeneration &&
+      !this._automaticTransactionGeneration.timeToStop) {
       this._automaticTransactionGeneration.stop();
     }
     if (this._autoReconnectTimeout !== 0 &&
@@ -433,7 +438,7 @@ class ChargingStation {
       let lastConnector;
       for (lastConnector in connectorsConfig) {
         // add connector 0, OCPP specification violation that for example KEBA have
-        if (Utils.convertToInt(lastConnector) === 0 && this._stationInfo.useConnectorId0) {
+        if (Utils.convertToInt(lastConnector) === 0 && Utils.convertToBoolean(this._stationInfo.useConnectorId0)) {
           this._connectors[lastConnector] = connectorsConfig[lastConnector];
         }
       }
@@ -446,7 +451,7 @@ class ChargingStation {
       }
       // generate all connectors
       for (let index = 1; index <= maxConnectors; index++) {
-        const randConnectorID = this._stationInfo.randomConnectors ? Utils.getRandomInt(maxConnectors, 1) : index;
+        const randConnectorID = Utils.convertToBoolean(this._stationInfo.randomConnectors) ? Utils.getRandomInt(lastConnector, 1) : index;
         this._connectors[index] = connectorsConfig[randConnectorID];
       }
     }
@@ -463,11 +468,13 @@ class ChargingStation {
       }
     }
 
-    if (this._stationInfo.AutomaticTransactionGenerator.enable) {
+    if (Utils.convertToBoolean(this._stationInfo.AutomaticTransactionGenerator.enable)) {
       if (!this._automaticTransactionGeneration) {
         this._automaticTransactionGeneration = new AutomaticTransactionGenerator(this);
       }
-      this._automaticTransactionGeneration.start();
+      if (this._automaticTransactionGeneration.timeToStop) {
+        this._automaticTransactionGeneration.start();
+      }
     }
     this._statistics.start();
   }
@@ -492,7 +499,7 @@ class ChargingStation {
   }
 
   handleResponseStartTransaction(payload, requestPayload) {
-    // Reset connector transaction related attributes
+    // Set connector transaction related attributes
     this._connectors[requestPayload.connectorId].transactionStarted = false;
     this._connectors[requestPayload.connectorId].idTag = requestPayload.idTag;
 
@@ -522,6 +529,14 @@ class ChargingStation {
     }
   }
 
+  handleResponseStopTransaction(payload, requestPayload) {
+    if (payload.idTagInfo && payload.idTagInfo.status) {
+      logger.debug(this._basicFormatLog() + ' Stop transaction ' + requestPayload.transactionId + ' response status: ' + payload.idTagInfo.status );
+    } else {
+      logger.debug(this._basicFormatLog() + ' Stop transaction ' + requestPayload.transactionId + ' response status: Unknown');
+    }
+  }
+
   handleResponseStatusNotification(payload) {
     logger.debug(this._basicFormatLog() + ' Status notification response received: %j', payload);
   }
@@ -557,7 +572,7 @@ class ChargingStation {
     await this.sendMessage(messageId, result, Constants.OCPP_JSON_CALL_RESULT_MESSAGE);
   }
 
-  async handleGetConfiguration() {
+  async handleGetConfiguration(commandPayload) {
     return this._configuration;
   }
 
@@ -649,7 +664,7 @@ class ChargingStation {
         if (sampledValueLcl.sampledValue[index].measurand && sampledValueLcl.sampledValue[index].measurand === 'SoC') {
           sampledValueLcl.sampledValue[index].value = Math.floor(Math.random() * 100) + 1;
           if (sampledValueLcl.sampledValue[index].value > 100) {
-            logger.info(self._basicFormatLog() + ' Meter type: ' +
+            logger.info(self._basicFormatLog() + ' MeterValues measurand: ' +
               (sampledValueLcl.sampledValue[index].measurand ? sampledValueLcl.sampledValue[index].measurand : 'default') +
               ', value: ' + sampledValueLcl.sampledValue[index].value);
           }
@@ -664,10 +679,10 @@ class ChargingStation {
             connector.lastConsumptionValue = 0;
           }
           consumption = Math.round(connector.lastConsumptionValue * 3600 / interval);
-          logger.info(self._basicFormatLog() + ' ConnectorID ' + connectorID + ' transaction ' + connector.transactionId + ' value ' + connector.lastConsumptionValue);
+          logger.info(self._basicFormatLog() + ' MeterValues: connectorID ' + connectorID + ', transaction ' + connector.transactionId + ', value ' + connector.lastConsumptionValue);
           sampledValueLcl.sampledValue[index].value = connector.lastConsumptionValue;
           if (sampledValueLcl.sampledValue[index].value > (self._stationInfo.maxPower * 3600 / interval) || sampledValueLcl.sampledValue[index].value < 500) {
-            logger.info(self._basicFormatLog() + ' Meter type: ' +
+            logger.info(self._basicFormatLog() + ' MeterValues measurand: ' +
               (sampledValueLcl.sampledValue[index].measurand ? sampledValueLcl.sampledValue[index].measurand : 'default') +
               ', value: ' + sampledValueLcl.sampledValue[index].value + '/' + (self._stationInfo.maxPower * 3600 / interval));
           }
@@ -681,15 +696,15 @@ class ChargingStation {
       };
       await self.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'MeterValues');
     } catch (error) {
-      logger.error(self._basicFormatLog() + ' Send meter values error: ' + error);
+      logger.error(self._basicFormatLog() + ' Send MeterValues error: ' + error);
     }
   }
 
   async startMeterValues(connectorID, interval, self) {
     if (!this._connectors[connectorID].transactionStarted) {
-      logger.debug(`${self._basicFormatLog()} Trying to start meter values on connector ID ${connectorID} with no transaction started`);
+      logger.debug(`${self._basicFormatLog()} Trying to start MeterValues on connector ID ${connectorID} with no transaction started`);
     } else if (this._connectors[connectorID].transactionStarted && !this._connectors[connectorID].transactionId) {
-      logger.debug(`${self._basicFormatLog()} Trying to start meter values on connector ID ${connectorID} with no transaction id`);
+      logger.debug(`${self._basicFormatLog()} Trying to start MeterValues on connector ID ${connectorID} with no transaction id`);
     }
     this._connectors[connectorID].transactionInterval = setInterval(async () => {
       const sendMeterValues = performance.timerify(this.sendMeterValues);