Refine comment at CS configuration file handling
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStation.ts
index d2d509f0386bb89472c2eb313490db780529f260..757cea0f8eb448cd73906fbcf97db6a4a28d2929 100644 (file)
@@ -895,8 +895,14 @@ export default class ChargingStation {
     try {
       const measureId = `${FileType.ChargingStationTemplate} read`;
       const beginId = PerformanceStatistics.beginMeasure(measureId);
-      template = JSON.parse(fs.readFileSync(this.templateFile, 'utf8')) as ChargingStationTemplate;
+      template =
+        (JSON.parse(fs.readFileSync(this.templateFile, 'utf8')) as ChargingStationTemplate) ??
+        ({} as ChargingStationTemplate);
       PerformanceStatistics.endMeasure(measureId, beginId);
+      template.templateHash = crypto
+        .createHash(Constants.DEFAULT_HASH_ALGORITHM)
+        .update(JSON.stringify(template))
+        .digest('hex');
     } catch (error) {
       FileUtils.handleFileException(
         this.logPrefix(),
@@ -943,12 +949,7 @@ export default class ChargingStation {
   }
 
   private getStationInfoFromTemplate(): ChargingStationInfo {
-    const stationInfo: ChargingStationInfo =
-      this.getTemplateFromFile() ?? ({} as ChargingStationInfo);
-    stationInfo.hash = crypto
-      .createHash(Constants.DEFAULT_HASH_ALGORITHM)
-      .update(JSON.stringify(stationInfo))
-      .digest('hex');
+    const stationInfo: ChargingStationInfo = this.getTemplateFromFile();
     const chargingStationId = this.getChargingStationId(stationInfo);
     // Deprecation template keys section
     this.warnDeprecatedTemplateKey(
@@ -982,8 +983,13 @@ export default class ChargingStation {
     return stationInfo;
   }
 
-  private getStationInfoFromFile(): ChargingStationInfo | null {
-    return this.getConfigurationFromFile()?.stationInfo ?? null;
+  private getStationInfoFromFile(): ChargingStationInfo {
+    const stationInfo = this.getConfigurationFromFile()?.stationInfo ?? ({} as ChargingStationInfo);
+    stationInfo.infoHash = crypto
+      .createHash(Constants.DEFAULT_HASH_ALGORITHM)
+      .update(JSON.stringify(stationInfo))
+      .digest('hex');
+    return stationInfo;
   }
 
   private getStationInfo(): ChargingStationInfo {
@@ -996,11 +1002,17 @@ export default class ChargingStation {
       this.hashId + '.json'
     );
     const stationInfoFromFile: ChargingStationInfo = this.getStationInfoFromFile();
-    if (stationInfoFromFile?.hash === stationInfoFromTemplate.hash) {
+    // Priority: charging station info from template > charging station info from configuration file > charging station info attribute
+    if (stationInfoFromFile?.templateHash === stationInfoFromTemplate.templateHash) {
       return stationInfoFromFile;
+    } else if (stationInfoFromFile?.templateHash !== stationInfoFromTemplate.templateHash) {
+      this.createSerialNumber(stationInfoFromTemplate, stationInfoFromFile);
+      return stationInfoFromTemplate;
     }
-    this.createSerialNumber(stationInfoFromTemplate, stationInfoFromFile);
-    return stationInfoFromTemplate;
+    if (this.stationInfo?.infoHash === stationInfoFromFile?.infoHash) {
+      return this.stationInfo;
+    }
+    return stationInfoFromFile;
   }
 
   private saveStationInfo(): void {
@@ -1486,12 +1498,12 @@ export default class ChargingStation {
     try {
       const request = JSON.parse(data.toString()) as IncomingRequest | Response | ErrorResponse;
       if (Utils.isIterable(request)) {
-        [messageType] = request;
+        [messageType, messageId] = request;
         // Check the type of message
         switch (messageType) {
           // Incoming Message
           case MessageType.CALL_MESSAGE:
-            [, messageId, commandName, commandPayload] = request as IncomingRequest;
+            [, , commandName, commandPayload] = request as IncomingRequest;
             if (this.getEnableStatistics()) {
               this.performanceStatistics.addRequestStatistic(commandName, messageType);
             }
@@ -1509,7 +1521,7 @@ export default class ChargingStation {
             break;
           // Outcome Message
           case MessageType.CALL_RESULT_MESSAGE:
-            [, messageId, commandPayload] = request as Response;
+            [, , commandPayload] = request as Response;
             // Respond
             cachedRequest = this.requests.get(messageId);
             if (Utils.isIterable(cachedRequest)) {
@@ -1518,47 +1530,52 @@ export default class ChargingStation {
               throw new OCPPError(
                 ErrorType.PROTOCOL_ERROR,
                 `Cached request for message id ${messageId} response is not iterable`,
-                requestCommandName
+                null,
+                cachedRequest as unknown as JsonType
               );
             }
             logger.debug(
-              `${this.logPrefix()} << Command '${requestCommandName}' received response payload: ${JSON.stringify(
-                request
-              )}`
+              `${this.logPrefix()} << Command '${
+                requestCommandName ?? ''
+              }' received response payload: ${JSON.stringify(request)}`
             );
             if (!responseCallback) {
               // Error
               throw new OCPPError(
                 ErrorType.INTERNAL_ERROR,
                 `Response for unknown message id ${messageId}`,
-                requestCommandName
+                null,
+                commandPayload
               );
             }
             responseCallback(commandPayload, requestPayload);
             break;
           // Error Message
           case MessageType.CALL_ERROR_MESSAGE:
-            [, messageId, errorType, errorMessage, errorDetails] = request as ErrorResponse;
+            [, , errorType, errorMessage, errorDetails] = request as ErrorResponse;
             cachedRequest = this.requests.get(messageId);
             if (Utils.isIterable(cachedRequest)) {
               [, rejectCallback, requestCommandName] = cachedRequest;
             } else {
               throw new OCPPError(
                 ErrorType.PROTOCOL_ERROR,
-                `Cached request for message id ${messageId} error response is not iterable`
+                `Cached request for message id ${messageId} error response is not iterable`,
+                null,
+                cachedRequest as unknown as JsonType
               );
             }
             logger.debug(
-              `${this.logPrefix()} << Command '${requestCommandName}' received error payload: ${JSON.stringify(
-                request
-              )}`
+              `${this.logPrefix()} << Command '${
+                requestCommandName ?? ''
+              }' received error payload: ${JSON.stringify(request)}`
             );
             if (!rejectCallback) {
               // Error
               throw new OCPPError(
                 ErrorType.INTERNAL_ERROR,
                 `Error response for unknown message id ${messageId}`,
-                requestCommandName
+                null,
+                { errorType, errorMessage, errorDetails }
               );
             }
             rejectCallback(
@@ -1573,12 +1590,9 @@ export default class ChargingStation {
             throw new OCPPError(ErrorType.PROTOCOL_ERROR, errMsg);
         }
       } else {
-        throw new OCPPError(
-          ErrorType.PROTOCOL_ERROR,
-          'Incoming message is not iterable',
-          Utils.isString(commandName) ? commandName : requestCommandName,
-          { payload: request }
-        );
+        throw new OCPPError(ErrorType.PROTOCOL_ERROR, 'Incoming message is not iterable', null, {
+          payload: request,
+        });
       }
     } catch (error) {
       // Log
@@ -1594,7 +1608,7 @@ export default class ChargingStation {
         (await this.ocppRequestService.sendError(
           messageId,
           error as OCPPError,
-          Utils.isString(commandName) ? commandName : requestCommandName
+          Utils.isString(commandName) ? commandName : requestCommandName ?? null
         ));
     }
   }