Add initial support to start/stop ATG with the UI services
authorJérôme Benoit <jerome.benoit@sap.com>
Mon, 29 Aug 2022 21:33:25 +0000 (23:33 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Mon, 29 Aug 2022 21:33:25 +0000 (23:33 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/assets/Insomnia_CSSimulatorUIProtocol.json
src/charging-station/ChargingStation.ts
src/charging-station/ChargingStationWorkerBroadcastChannel.ts
src/charging-station/ui-server/ui-services/UIService001.ts
src/types/UIProtocol.ts
src/types/WorkerBroadcastChannel.ts

index bd7de8601445ee60bb3fd97801e32a576062902e..36f80849157e725830d966b3cc4e905e3e688dda 100644 (file)
@@ -1,13 +1,13 @@
 {
   "_type": "export",
   "__export_format": 4,
-  "__export_date": "2022-08-29T19:54:32.270Z",
+  "__export_date": "2022-08-29T21:30:31.588Z",
   "__export_source": "insomnia.desktop.app:v2022.5.1",
   "resources": [
     {
       "_id": "req_606dcee139984772877def40fcbb5c76",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661802828976,
+      "modified": 1661806107269,
       "created": 1661789624987,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/listChargingStations",
       "name": "listChargingStations",
@@ -46,7 +46,7 @@
     {
       "_id": "req_7d5f9506e7ac49208a4f960a7740663e",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661802825491,
+      "modified": 1661803912361,
       "created": 1661789624990,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/startSimulator",
       "name": "startSimulator",
@@ -75,7 +75,7 @@
     {
       "_id": "req_59056be11534481c80a0b0da32e2a06a",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661802785193,
+      "modified": 1661803913261,
       "created": 1661789624994,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/stopSimulator",
       "name": "stopSimulator",
     {
       "_id": "req_aad7fd6db4c64869b60048b915010efc",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661802832021,
+      "modified": 1661803915999,
       "created": 1661789624998,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/startChargingStation",
       "name": "startChargingStation",
     {
       "_id": "req_d72d91cf3fb044179b8ae9d92a74f99c",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661802835221,
+      "modified": 1661803917031,
       "created": 1661789625002,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/stopChargingStation",
       "name": "stopChargingStation",
     {
       "_id": "req_747f458d196f4681b5fe15204b0067aa",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661802838358,
+      "modified": 1661803918135,
       "created": 1661789625005,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/openConnection",
       "name": "openConnection",
     {
       "_id": "req_401e6a62a33c4b6c90aaa2e019daab6d",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661802841482,
+      "modified": 1661803955362,
       "created": 1661789625014,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/closeConnection",
       "name": "closeConnection",
     {
       "_id": "req_2f757efe92fb4936ad4fa4b6763f9293",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661802844317,
+      "modified": 1661808615447,
       "created": 1661789625017,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/startTransaction",
       "name": "startTransaction",
     {
       "_id": "req_7c285fb6cb6948a08235a6c73cbeb1f9",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661802847088,
+      "modified": 1661808613804,
       "created": 1661789625020,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/stopTransaction",
       "name": "stopTransaction",
       "settingFollowRedirects": "global",
       "_type": "request"
     },
+    {
+      "_id": "req_b33c704fe3464dc5a5d3694abd9320d0",
+      "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
+      "modified": 1661808616683,
+      "created": 1661803778569,
+      "url": "{{baseUrl}}/{{protocol}}/{{version}}/startAutomaticTransactionGenerator",
+      "name": "startAutomaticTransactionGenerator",
+      "description": "",
+      "method": "POST",
+      "body": {
+        "mimeType": "application/json",
+        "text": "{\n\t\"hashIds\": [\n\t\t\"e4a2cd1d8b719aca0a3655bc19cd5f98edceea6aef6af25bf3306c49b342df881cec2a00ba8db95dffabea9b309563d2\"\n\t]\n}"
+      },
+      "parameters": [],
+      "headers": [
+        {
+          "name": "Content-Type",
+          "value": "application/json",
+          "id": "pair_6186d06e91364153b6bc0461db66b2c1"
+        }
+      ],
+      "authentication": {},
+      "metaSortKey": -999999650,
+      "isPrivate": false,
+      "settingStoreCookies": true,
+      "settingSendCookies": true,
+      "settingDisableRenderRequestBody": false,
+      "settingEncodeUrl": true,
+      "settingRebuildPath": true,
+      "settingFollowRedirects": "global",
+      "_type": "request"
+    },
+    {
+      "_id": "req_24c1c55fe3ba4ddb94702408f21a64df",
+      "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
+      "modified": 1661808612661,
+      "created": 1661803846882,
+      "url": "{{baseUrl}}/{{protocol}}/{{version}}/stopAutomaticTransactionGenerator",
+      "name": "stopAutomaticTransactionGenerator",
+      "description": "",
+      "method": "POST",
+      "body": {
+        "mimeType": "application/json",
+        "text": "{\n\t\"hashIds\": [\n\t\t\"e4a2cd1d8b719aca0a3655bc19cd5f98edceea6aef6af25bf3306c49b342df881cec2a00ba8db95dffabea9b309563d2\"\n\t]\n}"
+      },
+      "parameters": [],
+      "headers": [
+        {
+          "name": "Content-Type",
+          "value": "application/json",
+          "id": "pair_3224616dd6604605a1e48b71f6e9f795"
+        }
+      ],
+      "authentication": {},
+      "metaSortKey": -999999600,
+      "isPrivate": false,
+      "settingStoreCookies": true,
+      "settingSendCookies": true,
+      "settingDisableRenderRequestBody": false,
+      "settingEncodeUrl": true,
+      "settingRebuildPath": true,
+      "settingFollowRedirects": "global",
+      "_type": "request"
+    },
     {
       "_id": "env_74b29d59b9f04298b97fc9750476a4ca",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
index c3aea8421acf7f86abdab84edec612fce1f391c9..ccd72ff21e96177b2c0fdfa79ed4b9e7623fe0c9 100644 (file)
@@ -503,7 +503,9 @@ export default class ChargingStation {
             this.initialize();
             // Restart the ATG
             this.stopAutomaticTransactionGenerator();
-            this.startAutomaticTransactionGenerator();
+            if (this.getAutomaticTransactionGeneratorConfigurationFromTemplate()?.enable) {
+              this.startAutomaticTransactionGenerator();
+            }
             if (this.getEnableStatistics()) {
               this.performanceStatistics.restart();
             } else {
@@ -746,6 +748,25 @@ export default class ChargingStation {
     }
   }
 
+  public startAutomaticTransactionGenerator() {
+    if (!this.automaticTransactionGenerator) {
+      this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(
+        this.getAutomaticTransactionGeneratorConfigurationFromTemplate(),
+        this
+      );
+    }
+    if (!this.automaticTransactionGenerator.started) {
+      this.automaticTransactionGenerator.start();
+    }
+  }
+
+  public stopAutomaticTransactionGenerator(): void {
+    if (this.automaticTransactionGenerator?.started) {
+      this.automaticTransactionGenerator.stop();
+      this.automaticTransactionGenerator = null;
+    }
+  }
+
   private flushMessageBuffer() {
     if (this.messageBuffer.size > 0) {
       this.messageBuffer.forEach((message) => {
@@ -1745,27 +1766,8 @@ export default class ChargingStation {
       }
     }
     // Start the ATG
-    this.startAutomaticTransactionGenerator();
-  }
-
-  private startAutomaticTransactionGenerator() {
     if (this.getAutomaticTransactionGeneratorConfigurationFromTemplate()?.enable) {
-      if (!this.automaticTransactionGenerator) {
-        this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(
-          this.getAutomaticTransactionGeneratorConfigurationFromTemplate(),
-          this
-        );
-      }
-      if (!this.automaticTransactionGenerator.started) {
-        this.automaticTransactionGenerator.start();
-      }
-    }
-  }
-
-  private stopAutomaticTransactionGenerator(): void {
-    if (this.automaticTransactionGenerator?.started) {
-      this.automaticTransactionGenerator.stop();
-      this.automaticTransactionGenerator = null;
+      this.startAutomaticTransactionGenerator();
     }
   }
 
@@ -1777,42 +1779,44 @@ export default class ChargingStation {
     // Stop heartbeat
     this.stopHeartbeat();
     // Stop ongoing transactions
-    if (this.automaticTransactionGenerator?.configuration?.enable) {
-      this.stopAutomaticTransactionGenerator();
-    } else {
-      for (const connectorId of this.connectors.keys()) {
-        if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted) {
-          const transactionId = this.getConnectorStatus(connectorId).transactionId;
-          if (
-            this.getBeginEndMeterValues() &&
-            this.getOcppStrictCompliance() &&
-            !this.getOutOfOrderEndMeterValues()
-          ) {
-            // FIXME: Implement OCPP version agnostic helpers
-            const transactionEndMeterValue = OCPP16ServiceUtils.buildTransactionEndMeterValue(
-              this,
-              connectorId,
-              this.getEnergyActiveImportRegisterByTransactionId(transactionId)
-            );
-            await this.ocppRequestService.requestHandler<MeterValuesRequest, MeterValuesResponse>(
-              this,
-              RequestCommand.METER_VALUES,
-              {
+    if (this.getNumberOfRunningTransactions() > 0) {
+      if (this.automaticTransactionGenerator?.started) {
+        this.stopAutomaticTransactionGenerator();
+      } else {
+        for (const connectorId of this.connectors.keys()) {
+          if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted) {
+            const transactionId = this.getConnectorStatus(connectorId).transactionId;
+            if (
+              this.getBeginEndMeterValues() &&
+              this.getOcppStrictCompliance() &&
+              !this.getOutOfOrderEndMeterValues()
+            ) {
+              // FIXME: Implement OCPP version agnostic helpers
+              const transactionEndMeterValue = OCPP16ServiceUtils.buildTransactionEndMeterValue(
+                this,
                 connectorId,
-                transactionId,
-                meterValue: [transactionEndMeterValue],
-              }
-            );
+                this.getEnergyActiveImportRegisterByTransactionId(transactionId)
+              );
+              await this.ocppRequestService.requestHandler<MeterValuesRequest, MeterValuesResponse>(
+                this,
+                RequestCommand.METER_VALUES,
+                {
+                  connectorId,
+                  transactionId,
+                  meterValue: [transactionEndMeterValue],
+                }
+              );
+            }
+            await this.ocppRequestService.requestHandler<
+              StopTransactionRequest,
+              StopTransactionResponse
+            >(this, RequestCommand.STOP_TRANSACTION, {
+              transactionId,
+              meterStop: this.getEnergyActiveImportRegisterByTransactionId(transactionId),
+              idTag: this.getTransactionIdTag(transactionId),
+              reason,
+            });
           }
-          await this.ocppRequestService.requestHandler<
-            StopTransactionRequest,
-            StopTransactionResponse
-          >(this, RequestCommand.STOP_TRANSACTION, {
-            transactionId,
-            meterStop: this.getEnergyActiveImportRegisterByTransactionId(transactionId),
-            idTag: this.getTransactionIdTag(transactionId),
-            reason,
-          });
         }
       }
     }
index 6fd226fa326632d42ef251ae4e59707207c9590f..6fc700d29c8d2f322fffffd32150e592a2e02898 100644 (file)
@@ -105,6 +105,18 @@ export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadca
     requestPayload: BroadcastChannelRequestPayload
   ): Promise<CommandResponse | undefined> {
     switch (command) {
+      case BroadcastChannelProcedureName.START_CHARGING_STATION:
+        this.chargingStation.start();
+        break;
+      case BroadcastChannelProcedureName.STOP_CHARGING_STATION:
+        await this.chargingStation.stop();
+        break;
+      case BroadcastChannelProcedureName.OPEN_CONNECTION:
+        this.chargingStation.openWSConnection();
+        break;
+      case BroadcastChannelProcedureName.CLOSE_CONNECTION:
+        this.chargingStation.closeWSConnection();
+        break;
       case BroadcastChannelProcedureName.START_TRANSACTION:
         return this.chargingStation.ocppRequestService.requestHandler<
           StartTransactionRequest,
@@ -125,17 +137,11 @@ export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadca
           idTag: this.chargingStation.getTransactionIdTag(requestPayload.transactionId),
           reason: StopTransactionReason.NONE,
         });
-      case BroadcastChannelProcedureName.START_CHARGING_STATION:
-        this.chargingStation.start();
-        break;
-      case BroadcastChannelProcedureName.STOP_CHARGING_STATION:
-        await this.chargingStation.stop();
+      case BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR:
+        this.chargingStation.startAutomaticTransactionGenerator();
         break;
-      case BroadcastChannelProcedureName.OPEN_CONNECTION:
-        this.chargingStation.openWSConnection();
-        break;
-      case BroadcastChannelProcedureName.CLOSE_CONNECTION:
-        this.chargingStation.closeWSConnection();
+      case BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR:
+        this.chargingStation.stopAutomaticTransactionGenerator();
         break;
       default:
         // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
index 11925ee48a26789997e54818d5b9f03e27f14c21..8176772b54bd008ec587cda37546d72f8f611b91 100644 (file)
@@ -14,14 +14,6 @@ import AbstractUIService from './AbstractUIService';
 export default class UIService001 extends AbstractUIService {
   constructor(uiServer: AbstractUIServer) {
     super(uiServer, ProtocolVersion['0.0.1']);
-    this.requestHandlers.set(
-      ProcedureName.START_TRANSACTION,
-      this.handleStartTransaction.bind(this) as ProtocolRequestHandler
-    );
-    this.requestHandlers.set(
-      ProcedureName.STOP_TRANSACTION,
-      this.handleStopTransaction.bind(this) as ProtocolRequestHandler
-    );
     this.requestHandlers.set(
       ProcedureName.START_CHARGING_STATION,
       this.handleStartChargingStation.bind(this) as ProtocolRequestHandler
@@ -38,52 +30,84 @@ export default class UIService001 extends AbstractUIService {
       ProcedureName.CLOSE_CONNECTION,
       this.handleCloseConnection.bind(this) as ProtocolRequestHandler
     );
+    this.requestHandlers.set(
+      ProcedureName.START_TRANSACTION,
+      this.handleStartTransaction.bind(this) as ProtocolRequestHandler
+    );
+    this.requestHandlers.set(
+      ProcedureName.STOP_TRANSACTION,
+      this.handleStopTransaction.bind(this) as ProtocolRequestHandler
+    );
+    this.requestHandlers.set(
+      ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
+      this.handleStartAutomaticTransactionGenerator.bind(this) as ProtocolRequestHandler
+    );
+    this.requestHandlers.set(
+      ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
+      this.handleStopAutomaticTransactionGenerator.bind(this) as ProtocolRequestHandler
+    );
   }
 
-  private handleStartTransaction(uuid: string, payload: RequestPayload): void {
+  private handleStartChargingStation(uuid: string, payload: RequestPayload): void {
     this.uiServiceWorkerBroadcastChannel.sendRequest([
       uuid,
-      BroadcastChannelProcedureName.START_TRANSACTION,
+      BroadcastChannelProcedureName.START_CHARGING_STATION,
       payload as BroadcastChannelRequestPayload,
     ]);
   }
 
-  private handleStopTransaction(uuid: string, payload: RequestPayload): void {
+  private handleStopChargingStation(uuid: string, payload: RequestPayload): void {
     this.uiServiceWorkerBroadcastChannel.sendRequest([
       uuid,
-      BroadcastChannelProcedureName.STOP_TRANSACTION,
+      BroadcastChannelProcedureName.STOP_CHARGING_STATION,
       payload as BroadcastChannelRequestPayload,
     ]);
   }
 
-  private handleStartChargingStation(uuid: string, payload: RequestPayload): void {
+  private handleOpenConnection(uuid: string, payload: RequestPayload): void {
     this.uiServiceWorkerBroadcastChannel.sendRequest([
       uuid,
-      BroadcastChannelProcedureName.START_CHARGING_STATION,
+      BroadcastChannelProcedureName.OPEN_CONNECTION,
       payload as BroadcastChannelRequestPayload,
     ]);
   }
 
-  private handleStopChargingStation(uuid: string, payload: RequestPayload): void {
+  private handleCloseConnection(uuid: string, payload: RequestPayload): void {
     this.uiServiceWorkerBroadcastChannel.sendRequest([
       uuid,
-      BroadcastChannelProcedureName.STOP_CHARGING_STATION,
+      BroadcastChannelProcedureName.CLOSE_CONNECTION,
       payload as BroadcastChannelRequestPayload,
     ]);
   }
 
-  private handleOpenConnection(uuid: string, payload: RequestPayload): void {
+  private handleStartTransaction(uuid: string, payload: RequestPayload): void {
     this.uiServiceWorkerBroadcastChannel.sendRequest([
       uuid,
-      BroadcastChannelProcedureName.OPEN_CONNECTION,
+      BroadcastChannelProcedureName.START_TRANSACTION,
       payload as BroadcastChannelRequestPayload,
     ]);
   }
 
-  private handleCloseConnection(uuid: string, payload: RequestPayload): void {
+  private handleStopTransaction(uuid: string, payload: RequestPayload): void {
     this.uiServiceWorkerBroadcastChannel.sendRequest([
       uuid,
-      BroadcastChannelProcedureName.CLOSE_CONNECTION,
+      BroadcastChannelProcedureName.STOP_TRANSACTION,
+      payload as BroadcastChannelRequestPayload,
+    ]);
+  }
+
+  private handleStartAutomaticTransactionGenerator(uuid: string, payload: RequestPayload): void {
+    this.uiServiceWorkerBroadcastChannel.sendRequest([
+      uuid,
+      BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
+      payload as BroadcastChannelRequestPayload,
+    ]);
+  }
+
+  private handleStopAutomaticTransactionGenerator(uuid: string, payload: RequestPayload): void {
+    this.uiServiceWorkerBroadcastChannel.sendRequest([
+      uuid,
+      BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
       payload as BroadcastChannelRequestPayload,
     ]);
   }
index 3a76bd0007302ec8a11540a6c317bd59fd3c4675..3906512d2240470317bc094caec64a3de9949f69 100644 (file)
@@ -25,12 +25,14 @@ export enum ProcedureName {
   LIST_CHARGING_STATIONS = 'listChargingStations',
   START_CHARGING_STATION = 'startChargingStation',
   STOP_CHARGING_STATION = 'stopChargingStation',
-  START_TRANSACTION = 'startTransaction',
-  STOP_TRANSACTION = 'stopTransaction',
   START_SIMULATOR = 'startSimulator',
   STOP_SIMULATOR = 'stopSimulator',
   OPEN_CONNECTION = 'openConnection',
   CLOSE_CONNECTION = 'closeConnection',
+  START_TRANSACTION = 'startTransaction',
+  STOP_TRANSACTION = 'stopTransaction',
+  START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
+  STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
 }
 
 export interface RequestPayload extends JsonObject {
index 0ca44adac903f816f6917a60e1587762235b26e9..65c431404a44d2e842f56c12784a9613a49ea4e3 100644 (file)
@@ -10,10 +10,12 @@ export type BroadcastChannelResponse = [string, BroadcastChannelResponsePayload]
 export enum BroadcastChannelProcedureName {
   START_CHARGING_STATION = 'startChargingStation',
   STOP_CHARGING_STATION = 'stopChargingStation',
-  START_TRANSACTION = 'startTransaction',
-  STOP_TRANSACTION = 'stopTransaction',
   OPEN_CONNECTION = 'openConnection',
   CLOSE_CONNECTION = 'closeConnection',
+  START_TRANSACTION = 'startTransaction',
+  STOP_TRANSACTION = 'stopTransaction',
+  START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
+  STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
 }
 
 interface BaseBroadcastChannelRequestPayload extends Omit<RequestPayload, 'hashId' | 'hashIds'> {