From 4f69be046f99592d0cc9c190aa8957f7eff1c936 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Mon, 29 Aug 2022 23:33:25 +0200 Subject: [PATCH] Add initial support to start/stop ATG with the UI services MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../Insomnia_CSSimulatorUIProtocol.json | 84 +++++++++++-- src/charging-station/ChargingStation.ts | 114 +++++++++--------- .../ChargingStationWorkerBroadcastChannel.ts | 26 ++-- .../ui-server/ui-services/UIService001.ts | 64 +++++++--- src/types/UIProtocol.ts | 6 +- src/types/WorkerBroadcastChannel.ts | 6 +- 6 files changed, 201 insertions(+), 99 deletions(-) diff --git a/src/assets/Insomnia_CSSimulatorUIProtocol.json b/src/assets/Insomnia_CSSimulatorUIProtocol.json index bd7de860..36f80849 100644 --- a/src/assets/Insomnia_CSSimulatorUIProtocol.json +++ b/src/assets/Insomnia_CSSimulatorUIProtocol.json @@ -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", @@ -104,7 +104,7 @@ { "_id": "req_aad7fd6db4c64869b60048b915010efc", "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205", - "modified": 1661802832021, + "modified": 1661803915999, "created": 1661789624998, "url": "{{baseUrl}}/{{protocol}}/{{version}}/startChargingStation", "name": "startChargingStation", @@ -136,7 +136,7 @@ { "_id": "req_d72d91cf3fb044179b8ae9d92a74f99c", "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205", - "modified": 1661802835221, + "modified": 1661803917031, "created": 1661789625002, "url": "{{baseUrl}}/{{protocol}}/{{version}}/stopChargingStation", "name": "stopChargingStation", @@ -168,7 +168,7 @@ { "_id": "req_747f458d196f4681b5fe15204b0067aa", "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205", - "modified": 1661802838358, + "modified": 1661803918135, "created": 1661789625005, "url": "{{baseUrl}}/{{protocol}}/{{version}}/openConnection", "name": "openConnection", @@ -200,7 +200,7 @@ { "_id": "req_401e6a62a33c4b6c90aaa2e019daab6d", "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205", - "modified": 1661802841482, + "modified": 1661803955362, "created": 1661789625014, "url": "{{baseUrl}}/{{protocol}}/{{version}}/closeConnection", "name": "closeConnection", @@ -232,7 +232,7 @@ { "_id": "req_2f757efe92fb4936ad4fa4b6763f9293", "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205", - "modified": 1661802844317, + "modified": 1661808615447, "created": 1661789625017, "url": "{{baseUrl}}/{{protocol}}/{{version}}/startTransaction", "name": "startTransaction", @@ -264,7 +264,7 @@ { "_id": "req_7c285fb6cb6948a08235a6c73cbeb1f9", "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205", - "modified": 1661802847088, + "modified": 1661808613804, "created": 1661789625020, "url": "{{baseUrl}}/{{protocol}}/{{version}}/stopTransaction", "name": "stopTransaction", @@ -293,6 +293,70 @@ "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", diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index c3aea842..ccd72ff2 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -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( - 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( + 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, - }); } } } diff --git a/src/charging-station/ChargingStationWorkerBroadcastChannel.ts b/src/charging-station/ChargingStationWorkerBroadcastChannel.ts index 6fd226fa..6fc700d2 100644 --- a/src/charging-station/ChargingStationWorkerBroadcastChannel.ts +++ b/src/charging-station/ChargingStationWorkerBroadcastChannel.ts @@ -105,6 +105,18 @@ export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadca requestPayload: BroadcastChannelRequestPayload ): Promise { 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 diff --git a/src/charging-station/ui-server/ui-services/UIService001.ts b/src/charging-station/ui-server/ui-services/UIService001.ts index 11925ee4..8176772b 100644 --- a/src/charging-station/ui-server/ui-services/UIService001.ts +++ b/src/charging-station/ui-server/ui-services/UIService001.ts @@ -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, ]); } diff --git a/src/types/UIProtocol.ts b/src/types/UIProtocol.ts index 3a76bd00..3906512d 100644 --- a/src/types/UIProtocol.ts +++ b/src/types/UIProtocol.ts @@ -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 { diff --git a/src/types/WorkerBroadcastChannel.ts b/src/types/WorkerBroadcastChannel.ts index 0ca44ada..65c43140 100644 --- a/src/types/WorkerBroadcastChannel.ts +++ b/src/types/WorkerBroadcastChannel.ts @@ -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 { -- 2.34.1