Improve OCPP types.
authorJérôme Benoit <jerome.benoit@sap.com>
Fri, 1 Jan 2021 12:17:11 +0000 (13:17 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Fri, 1 Jan 2021 12:17:11 +0000 (13:17 +0100)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/ChargingStation.ts
src/charging-station/OcppError.ts
src/types/ocpp/ErrorType.ts [new file with mode: 0644]
src/types/ocpp/MessageType.ts [new file with mode: 0644]
src/utils/Constants.ts
src/utils/Statistics.ts

index 96374d1dd68e87bb2e8e0cc2b8d99d5c805c176b..d43b975f0e248d8e06a08006704d2d268b9548cd 100644 (file)
@@ -16,7 +16,9 @@ import ChargingStationInfo from '../types/ChargingStationInfo';
 import Configuration from '../utils/Configuration';
 import Constants from '../utils/Constants';
 import ElectricUtils from '../utils/ElectricUtils';
+import { ErrorType } from '../types/ocpp/ErrorType';
 import MeasurandValues from '../types/MeasurandValues';
+import { MessageType } from '../types/ocpp/MessageType';
 import OCPPError from './OcppError';
 import Statistics from '../utils/Statistics';
 import Utils from '../utils/Utils';
@@ -693,7 +695,7 @@ export default class ChargingStation {
       // Check the Type of message
       switch (messageType) {
         // Incoming Message
-        case Constants.OCPP_JSON_CALL_MESSAGE:
+        case MessageType.CALL_MESSAGE:
           if (this.getEnableStatistics()) {
             this._statistics.addMessage(commandName, messageType);
           }
@@ -701,7 +703,7 @@ export default class ChargingStation {
           await this.handleRequest(messageId, commandName, commandPayload);
           break;
         // Outcome Message
-        case Constants.OCPP_JSON_CALL_RESULT_MESSAGE:
+        case MessageType.CALL_RESULT_MESSAGE:
           // Respond
           // eslint-disable-next-line no-case-declarations
           let responseCallback; let requestPayload;
@@ -718,7 +720,7 @@ export default class ChargingStation {
           responseCallback(commandName, requestPayload);
           break;
         // Error Message
-        case Constants.OCPP_JSON_CALL_ERROR_MESSAGE:
+        case MessageType.CALL_ERROR_MESSAGE:
           if (!this._requests[messageId]) {
             // Error
             throw new Error(`Error request for unknown message id ${messageId}`);
@@ -744,14 +746,14 @@ export default class ChargingStation {
       // Log
       logger.error('%s Incoming message %j processing error %s on request content type %s', this._logPrefix(), messageEvent, error, this._requests[messageId]);
       // Send error
-      messageType !== Constants.OCPP_JSON_CALL_ERROR_MESSAGE && await this.sendError(messageId, error, commandName);
+      messageType !== MessageType.CALL_ERROR_MESSAGE && await this.sendError(messageId, error, commandName);
     }
   }
 
   async sendHeartbeat(): Promise<void> {
     try {
       const payload: HeartbeatRequest = {};
-      await this.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'Heartbeat');
+      await this.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, 'Heartbeat');
     } catch (error) {
       logger.error(this._logPrefix() + ' Send Heartbeat error: %j', error);
       throw error;
@@ -760,7 +762,7 @@ export default class ChargingStation {
 
   async sendBootNotification(): Promise<BootNotificationResponse> {
     try {
-      return await this.sendMessage(Utils.generateUUID(), this._bootNotificationRequest, Constants.OCPP_JSON_CALL_MESSAGE, 'BootNotification') as BootNotificationResponse;
+      return await this.sendMessage(Utils.generateUUID(), this._bootNotificationRequest, MessageType.CALL_MESSAGE, 'BootNotification') as BootNotificationResponse;
     } catch (error) {
       logger.error(this._logPrefix() + ' Send BootNotification error: %j', error);
       throw error;
@@ -775,7 +777,7 @@ export default class ChargingStation {
         errorCode,
         status,
       };
-      await this.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'StatusNotification');
+      await this.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, 'StatusNotification');
     } catch (error) {
       logger.error(this._logPrefix() + ' Send StatusNotification error: %j', error);
       throw error;
@@ -790,7 +792,7 @@ export default class ChargingStation {
         meterStart: 0,
         timestamp: new Date().toISOString(),
       };
-      return await this.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'StartTransaction') as StartTransactionResponse;
+      return await this.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, 'StartTransaction') as StartTransactionResponse;
     } catch (error) {
       logger.error(this._logPrefix() + ' Send StartTransaction error: %j', error);
       throw error;
@@ -807,7 +809,7 @@ export default class ChargingStation {
         timestamp: new Date().toISOString(),
         ...reason && { reason },
       };
-      return await this.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'StopTransaction') as StartTransactionResponse;
+      return await this.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, 'StopTransaction') as StartTransactionResponse;
     } catch (error) {
       logger.error(this._logPrefix() + ' Send StopTransaction error: %j', error);
       throw error;
@@ -1028,7 +1030,7 @@ export default class ChargingStation {
         transactionId: self.getConnector(connectorId).transactionId,
         meterValue: meterValue,
       };
-      await self.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'MeterValues');
+      await self.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, 'MeterValues');
     } catch (error) {
       logger.error(self._logPrefix() + ' Send MeterValues error: %j', error);
       throw error;
@@ -1037,12 +1039,12 @@ export default class ChargingStation {
 
   async sendError(messageId: string, err: Error | OCPPError, commandName: string): Promise<unknown> {
     // Check exception type: only OCPP error are accepted
-    const error = err instanceof OCPPError ? err : new OCPPError(Constants.OCPP_ERROR_INTERNAL_ERROR, err.message, err.stack && err.stack);
+    const error = err instanceof OCPPError ? err : new OCPPError(ErrorType.INTERNAL_ERROR, err.message, err.stack && err.stack);
     // Send error
-    return this.sendMessage(messageId, error, Constants.OCPP_JSON_CALL_ERROR_MESSAGE, commandName);
+    return this.sendMessage(messageId, error, MessageType.CALL_ERROR_MESSAGE, commandName);
   }
 
-  async sendMessage(messageId: string, commandParams, messageType = Constants.OCPP_JSON_CALL_RESULT_MESSAGE, commandName: string): Promise<any> {
+  async sendMessage(messageId: string, commandParams, messageType = MessageType.CALL_RESULT_MESSAGE, commandName: string): Promise<any> {
     // eslint-disable-next-line @typescript-eslint/no-this-alias
     const self = this;
     // Send a message through wsConnection
@@ -1051,20 +1053,20 @@ export default class ChargingStation {
       // Type of message
       switch (messageType) {
         // Request
-        case Constants.OCPP_JSON_CALL_MESSAGE:
+        case MessageType.CALL_MESSAGE:
           // Build request
           this._requests[messageId] = [responseCallback, rejectCallback, commandParams];
           messageToSend = JSON.stringify([messageType, messageId, commandName, commandParams]);
           break;
         // Response
-        case Constants.OCPP_JSON_CALL_RESULT_MESSAGE:
+        case MessageType.CALL_RESULT_MESSAGE:
           // Build response
           messageToSend = JSON.stringify([messageType, messageId, commandParams]);
           break;
         // Error Message
-        case Constants.OCPP_JSON_CALL_ERROR_MESSAGE:
+        case MessageType.CALL_ERROR_MESSAGE:
           // Build Error Message
-          messageToSend = JSON.stringify([messageType, messageId, commandParams.code ? commandParams.code : Constants.OCPP_ERROR_GENERIC_ERROR, commandParams.message ? commandParams.message : '', commandParams.details ? commandParams.details : {}]);
+          messageToSend = JSON.stringify([messageType, messageId, commandParams.code ? commandParams.code : ErrorType.GENERIC_ERROR, commandParams.message ? commandParams.message : '', commandParams.details ? commandParams.details : {}]);
           break;
       }
       // Check if wsConnection opened and charging station registered
@@ -1089,15 +1091,15 @@ export default class ChargingStation {
           this._messageQueue.push(messageToSend);
         }
         // Reject it
-        return rejectCallback(new OCPPError(commandParams.code ? commandParams.code : Constants.OCPP_ERROR_GENERIC_ERROR, commandParams.message ? commandParams.message : `WebSocket closed for message id '${messageId}' with content '${messageToSend}', message buffered`, commandParams.details ? commandParams.details : {}));
+        return rejectCallback(new OCPPError(commandParams.code ? commandParams.code : ErrorType.GENERIC_ERROR, commandParams.message ? commandParams.message : `WebSocket closed for message id '${messageId}' with content '${messageToSend}', message buffered`, commandParams.details ? commandParams.details : {}));
       }
       // Response?
-      if (messageType === Constants.OCPP_JSON_CALL_RESULT_MESSAGE) {
+      if (messageType === MessageType.CALL_RESULT_MESSAGE) {
         // Yes: send Ok
         resolve();
-      } else if (messageType === Constants.OCPP_JSON_CALL_ERROR_MESSAGE) {
+      } else if (messageType === MessageType.CALL_ERROR_MESSAGE) {
         // Send timeout
-        setTimeout(() => rejectCallback(new OCPPError(commandParams.code ? commandParams.code : Constants.OCPP_ERROR_GENERIC_ERROR, commandParams.message ? commandParams.message : `Timeout for message id '${messageId}' with content '${messageToSend}'`, commandParams.details ? commandParams.details : {})), Constants.OCPP_SOCKET_TIMEOUT);
+        setTimeout(() => rejectCallback(new OCPPError(commandParams.code ? commandParams.code : ErrorType.GENERIC_ERROR, commandParams.message ? commandParams.message : `Timeout for message id '${messageId}' with content '${messageToSend}'`, commandParams.details ? commandParams.details : {})), Constants.OCPP_WEBSOCKET_TIMEOUT);
       }
 
       // Function that will receive the request's response
@@ -1252,11 +1254,11 @@ export default class ChargingStation {
       }
     } else {
       // Throw exception
-      await this.sendError(messageId, new OCPPError(Constants.OCPP_ERROR_NOT_IMPLEMENTED, `${commandName} is not implemented`, {}), commandName);
+      await this.sendError(messageId, new OCPPError(ErrorType.NOT_IMPLEMENTED, `${commandName} is not implemented`, {}), commandName);
       throw new Error(`${commandName} is not implemented ${JSON.stringify(commandPayload, null, ' ')}`);
     }
     // Send response
-    await this.sendMessage(messageId, response, Constants.OCPP_JSON_CALL_RESULT_MESSAGE, commandName);
+    await this.sendMessage(messageId, response, MessageType.CALL_RESULT_MESSAGE, commandName);
   }
 
   // Simulate charging station restart
index d11ad56f0b632d0ef826d8d8e9adad464057e5e8..d39cdef1c8f5baa039c7941d51cfb724ce8569df 100644 (file)
@@ -1,4 +1,4 @@
-import Constants from '../utils/Constants';
+import { ErrorType } from '../types/ocpp/ErrorType';
 
 export default class OCPPError extends Error {
   code: string;
@@ -7,7 +7,7 @@ export default class OCPPError extends Error {
   constructor(code: string, message: string, details?: any) {
     super(message);
 
-    this.code = code || Constants.OCPP_ERROR_GENERIC_ERROR;
+    this.code = code || ErrorType.GENERIC_ERROR;
     this.message = message || '';
     this.details = details || {};
 
diff --git a/src/types/ocpp/ErrorType.ts b/src/types/ocpp/ErrorType.ts
new file mode 100644 (file)
index 0000000..4dd459d
--- /dev/null
@@ -0,0 +1,22 @@
+export enum ErrorType {
+  // Requested Action is not known by receiver
+  NOT_IMPLEMENTED = 'NotImplemented',
+  // Requested Action is recognized but not supported by the receiver
+  NOT_SUPPORTED = 'NotSupported',
+  // An internal error occurred and the receiver was not able to process the requested Action successfully
+  INTERNAL_ERROR = 'InternalError',
+  // Payload for Action is incomplete
+  PROTOCOL_ERROR = 'ProtocolError',
+  // During the processing of Action a security issue occurred preventing receiver from completing the Action successfully
+  SECURITY_ERROR = 'SecurityError',
+  // Payload for Action is syntactically incorrect or not conform the PDU structure for Action
+  FORMATION_VIOLATION = 'FormationViolation',
+  // Payload is syntactically correct but at least one field contains an invalid value
+  PROPERTY_RAINT_VIOLATION = 'PropertyraintViolation',
+  // Payload for Action is syntactically correct but at least one of the fields violates occurrence raints
+  OCCURRENCE_RAINT_VIOLATION = 'OccurrenceraintViolation',
+  // Payload for Action is syntactically correct but at least one of the fields violates data type raints (e.g. "somestring" = 12)
+  TYPERAINT_VIOLATION = 'TyperaintViolation',
+  // Any other error not covered by the previous ones
+  GENERIC_ERROR = 'GenericError',
+}
diff --git a/src/types/ocpp/MessageType.ts b/src/types/ocpp/MessageType.ts
new file mode 100644 (file)
index 0000000..1346ee8
--- /dev/null
@@ -0,0 +1,5 @@
+export enum MessageType {
+  CALL_MESSAGE = 2, // Caller to Callee
+  CALL_RESULT_MESSAGE = 3, // Callee to Caller
+  CALL_ERROR_MESSAGE = 4, // Callee to Caller
+}
index 812b32273b0e7d4a4462c2fd123fd7b569dbf9eb..5d1825b688fd43227499664a38b4141d9e312992 100644 (file)
@@ -16,30 +16,6 @@ export default class Constants {
   static readonly OCPP_RESPONSE_UNLOCKED = Object.freeze({ status: UnlockStatus.UNLOCKED });
   static readonly OCPP_RESPONSE_UNLOCK_FAILED = Object.freeze({ status: UnlockStatus.UNLOCK_FAILED });
   static readonly OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED = Object.freeze({ status: UnlockStatus.NOT_SUPPORTED });
-  static readonly OCPP_SOCKET_TIMEOUT = 60000; // 60 sec
-  static readonly OCPP_JSON_CALL_MESSAGE = 2; // Caller to callee
-  static readonly OCPP_JSON_CALL_RESULT_MESSAGE = 3; // Callee to caller
-  static readonly OCPP_JSON_CALL_ERROR_MESSAGE = 4; // Callee to caller
-  // Requested Action is not known by receiver
-  static readonly OCPP_ERROR_NOT_IMPLEMENTED = 'NotImplemented';
-  // Requested Action is recognized but not supported by the receiver
-  static readonly OCPP_ERROR_NOT_SUPPORTED = 'NotSupported';
-  // An internal error occurred and the receiver was not able to process the requested Action successfully
-  static readonly OCPP_ERROR_INTERNAL_ERROR = 'InternalError';
-  // Payload for Action is incomplete
-  static readonly OCPP_ERROR_PROTOCOL_ERROR = 'ProtocolError';
-  // During the processing of Action a security issue occurred preventing receiver from completing the Action successfully
-  static readonly OCPP_ERROR_SECURITY_ERROR = 'SecurityError';
-  // Payload for Action is syntactically incorrect or not conform the PDU structure for Action
-  static readonly OCPP_ERROR_FORMATION_VIOLATION = 'FormationViolation';
-  // Payload is syntactically correct but at least one field contains an invalid value
-  static readonly OCPP_ERROR_PROPERTY_RAINT_VIOLATION = 'PropertyraintViolation';
-  // Payload for Action is syntactically correct but at least one of the fields violates occurrence raints
-  static readonly OCPP_ERROR_OCCURENCE_RAINT_VIOLATION = 'OccurenceraintViolation';
-  // Payload for Action is syntactically correct but at least one of the fields violates data type raints (e.g. “somestring” = 12)
-  static readonly OCPP_ERROR_TYPERAINT_VIOLATION = 'TyperaintViolation';
-  // Any other error not covered by the previous ones
-  static readonly OCPP_ERROR_GENERIC_ERROR = 'GenericError';
 
   static readonly OCPP_PROTOCOL_JSON = 'json';
   static readonly OCPP_PROTOCOL_SOAP = 'soap';
@@ -48,6 +24,8 @@ export default class Constants {
   static readonly OCPP_VERSION_16 = '1.6';
   static readonly OCPP_VERSION_20 = '2.0';
 
+  static readonly OCPP_WEBSOCKET_TIMEOUT = 60000; // 60 sec
+
   static readonly CHARGING_STATION_DEFAULT_RESET_TIME = 60000; // Ms
   static readonly CHARGING_STATION_ATG_WAIT_TIME = 2000; // Ms
 
index a7dfaaa7e4e2e0cd612bd643a3d7101345564a2e..1b69b30ed382311605b93cc449d0e2007559c6ab 100644 (file)
@@ -2,7 +2,7 @@ import CommandStatistics, { CommandStatisticsData, PerfEntry } from '../types/Co
 
 import CircularArray from './CircularArray';
 import Configuration from './Configuration';
-import Constants from './Constants';
+import { MessageType } from '../types/ocpp/MessageType';
 import { PerformanceEntry } from 'perf_hooks';
 import Utils from './Utils';
 import logger from './Logger';
@@ -29,7 +29,7 @@ export default class Statistics {
 
   addMessage(command: string, messageType: number): void {
     switch (messageType) {
-      case Constants.OCPP_JSON_CALL_MESSAGE:
+      case MessageType.CALL_MESSAGE:
         if (this._commandsStatistics[command] && this._commandsStatistics[command].countRequest) {
           this._commandsStatistics[command].countRequest++;
         } else {
@@ -37,7 +37,7 @@ export default class Statistics {
           this._commandsStatistics[command].countRequest = 1;
         }
         break;
-      case Constants.OCPP_JSON_CALL_RESULT_MESSAGE:
+      case MessageType.CALL_RESULT_MESSAGE:
         if (this._commandsStatistics[command]) {
           if (this._commandsStatistics[command].countResponse) {
             this._commandsStatistics[command].countResponse++;
@@ -49,7 +49,7 @@ export default class Statistics {
           this._commandsStatistics[command].countResponse = 1;
         }
         break;
-      case Constants.OCPP_JSON_CALL_ERROR_MESSAGE:
+      case MessageType.CALL_ERROR_MESSAGE:
         if (this._commandsStatistics[command]) {
           if (this._commandsStatistics[command].countError) {
             this._commandsStatistics[command].countError++;