1 import BaseError from
'../exception/BaseError';
2 import { RequestCommand
} from
'../types/ocpp/Requests';
5 StartTransactionRequest
,
6 StartTransactionResponse
,
8 StopTransactionRequest
,
9 StopTransactionResponse
,
10 } from
'../types/ocpp/Transaction';
12 BroadcastChannelProcedureName
,
13 BroadcastChannelRequest
,
14 BroadcastChannelRequestPayload
,
15 BroadcastChannelResponsePayload
,
17 } from
'../types/WorkerBroadcastChannel';
18 import { ResponseStatus
} from
'../ui/web/src/types/UIProtocol';
19 import logger from
'../utils/Logger';
20 import type ChargingStation from
'./ChargingStation';
21 import WorkerBroadcastChannel from
'./WorkerBroadcastChannel';
23 const moduleName
= 'ChargingStationWorkerBroadcastChannel';
25 type CommandResponse
= StartTransactionResponse
| StopTransactionResponse
;
27 export default class ChargingStationWorkerBroadcastChannel
extends WorkerBroadcastChannel
{
28 private readonly chargingStation
: ChargingStation
;
30 constructor(chargingStation
: ChargingStation
) {
32 this.chargingStation
= chargingStation
;
33 this.onmessage
= this.requestHandler
.bind(this) as (message
: MessageEvent
) => void;
34 this.onmessageerror
= this.messageErrorHandler
.bind(this) as (message
: MessageEvent
) => void;
37 private async requestHandler(messageEvent
: MessageEvent
): Promise
<void> {
38 if (this.isResponse(messageEvent
.data
)) {
41 this.validateMessageEvent(messageEvent
);
43 const [uuid
, command
, requestPayload
] = messageEvent
.data
as BroadcastChannelRequest
;
46 requestPayload
?.hashId
=== undefined &&
47 (requestPayload
?.hashIds
as string[])?.includes(this.chargingStation
.stationInfo
.hashId
) ===
53 requestPayload
?.hashIds
=== undefined &&
54 requestPayload
?.hashId
!== this.chargingStation
.stationInfo
.hashId
58 if (requestPayload
?.hashId
!== undefined) {
60 `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: 'hashId' field usage in PDU is deprecated, use 'hashIds' instead`
64 let responsePayload
: BroadcastChannelResponsePayload
;
65 let commandResponse
: CommandResponse
;
67 commandResponse
= await this.commandHandler(command
, requestPayload
);
68 if (commandResponse
=== undefined) {
70 hashId
: this.chargingStation
.stationInfo
.hashId
,
71 status: ResponseStatus
.SUCCESS
,
75 hashId
: this.chargingStation
.stationInfo
.hashId
,
76 status: this.commandResponseToResponseStatus(commandResponse
),
81 `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: Handle request error:`,
85 hashId
: this.chargingStation
.stationInfo
.hashId
,
86 status: ResponseStatus
.FAILURE
,
90 errorMessage
: (error
as Error).message
,
91 errorStack
: (error
as Error).stack
,
94 this.sendResponse([uuid
, responsePayload
]);
97 private messageErrorHandler(messageEvent
: MessageEvent
): void {
99 `${this.chargingStation.logPrefix()} ${moduleName}.messageErrorHandler: Error at handling message:`,
100 { messageEvent
, messageEventData
: messageEvent
.data
}
104 private async commandHandler(
105 command
: BroadcastChannelProcedureName
,
106 requestPayload
: BroadcastChannelRequestPayload
107 ): Promise
<CommandResponse
| undefined> {
109 case BroadcastChannelProcedureName
.START_CHARGING_STATION
:
110 this.chargingStation
.start();
112 case BroadcastChannelProcedureName
.STOP_CHARGING_STATION
:
113 await this.chargingStation
.stop();
115 case BroadcastChannelProcedureName
.OPEN_CONNECTION
:
116 this.chargingStation
.openWSConnection();
118 case BroadcastChannelProcedureName
.CLOSE_CONNECTION
:
119 this.chargingStation
.closeWSConnection();
121 case BroadcastChannelProcedureName
.START_TRANSACTION
:
122 return this.chargingStation
.ocppRequestService
.requestHandler
<
123 StartTransactionRequest
,
124 StartTransactionResponse
125 >(this.chargingStation
, RequestCommand
.START_TRANSACTION
, {
126 connectorId
: requestPayload
.connectorId
,
127 idTag
: requestPayload
.idTag
,
129 case BroadcastChannelProcedureName
.STOP_TRANSACTION
:
130 return this.chargingStation
.ocppRequestService
.requestHandler
<
131 StopTransactionRequest
,
132 StopTransactionResponse
133 >(this.chargingStation
, RequestCommand
.STOP_TRANSACTION
, {
134 transactionId
: requestPayload
.transactionId
,
135 meterStop
: this.chargingStation
.getEnergyActiveImportRegisterByTransactionId(
136 requestPayload
.transactionId
,
139 idTag
: this.chargingStation
.getTransactionIdTag(requestPayload
.transactionId
),
140 reason
: StopTransactionReason
.NONE
,
142 case BroadcastChannelProcedureName
.START_AUTOMATIC_TRANSACTION_GENERATOR
:
143 this.chargingStation
.startAutomaticTransactionGenerator(requestPayload
.connectorIds
);
145 case BroadcastChannelProcedureName
.STOP_AUTOMATIC_TRANSACTION_GENERATOR
:
146 this.chargingStation
.stopAutomaticTransactionGenerator(requestPayload
.connectorIds
);
149 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
150 throw new BaseError(`Unknown worker broadcast channel command: ${command}`);
154 private commandResponseToResponseStatus(commandResponse
: CommandResponse
): ResponseStatus
{
155 if (commandResponse
?.idTagInfo
?.status === AuthorizationStatus
.ACCEPTED
) {
156 return ResponseStatus
.SUCCESS
;
158 return ResponseStatus
.FAILURE
;