1 import BaseError from
'../exception/BaseError';
2 import { RequestCommand
} from
'../types/ocpp/Requests';
5 StartTransactionRequest
,
6 StartTransactionResponse
,
7 StopTransactionRequest
,
8 StopTransactionResponse
,
9 } from
'../types/ocpp/Transaction';
11 BroadcastChannelProcedureName
,
12 BroadcastChannelRequest
,
13 BroadcastChannelRequestPayload
,
14 BroadcastChannelResponsePayload
,
16 } from
'../types/WorkerBroadcastChannel';
17 import { ResponseStatus
} from
'../ui/web/src/types/UIProtocol';
18 import logger from
'../utils/Logger';
19 import type ChargingStation from
'./ChargingStation';
20 import WorkerBroadcastChannel from
'./WorkerBroadcastChannel';
22 const moduleName
= 'ChargingStationWorkerBroadcastChannel';
24 type CommandResponse
= StartTransactionResponse
| StopTransactionResponse
;
26 export default class ChargingStationWorkerBroadcastChannel
extends WorkerBroadcastChannel
{
27 private readonly chargingStation
: ChargingStation
;
29 constructor(chargingStation
: ChargingStation
) {
31 this.chargingStation
= chargingStation
;
32 this.onmessage
= this.requestHandler
.bind(this) as (message
: MessageEvent
) => void;
33 this.onmessageerror
= this.messageErrorHandler
.bind(this) as (message
: MessageEvent
) => void;
36 private async requestHandler(messageEvent
: MessageEvent
): Promise
<void> {
37 if (this.isResponse(messageEvent
.data
)) {
40 const [uuid
, command
, requestPayload
] = this.validateMessageEvent(messageEvent
)
41 .data
as BroadcastChannelRequest
;
43 if (requestPayload
?.hashIds
!== undefined || requestPayload
?.hashId
!== undefined) {
45 requestPayload
?.hashId
=== undefined &&
46 requestPayload
?.hashIds
?.includes(this.chargingStation
.stationInfo
.hashId
) === false
51 requestPayload
?.hashIds
=== undefined &&
52 requestPayload
?.hashId
!== this.chargingStation
.stationInfo
.hashId
56 if (requestPayload
?.hashId
!== undefined) {
58 `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: 'hashId' field usage in PDU is deprecated, use 'hashIds' instead`
63 let responsePayload
: BroadcastChannelResponsePayload
;
64 let commandResponse
: CommandResponse
;
66 commandResponse
= await this.commandHandler(command
, requestPayload
);
67 if (commandResponse
=== undefined) {
69 hashId
: this.chargingStation
.stationInfo
.hashId
,
70 status: ResponseStatus
.SUCCESS
,
74 hashId
: this.chargingStation
.stationInfo
.hashId
,
75 status: this.commandResponseToResponseStatus(commandResponse
),
80 `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: Handle request error:`,
84 hashId
: this.chargingStation
.stationInfo
.hashId
,
85 status: ResponseStatus
.FAILURE
,
89 errorMessage
: (error
as Error).message
,
90 errorStack
: (error
as Error).stack
,
93 this.sendResponse([uuid
, responsePayload
]);
96 private messageErrorHandler(messageEvent
: MessageEvent
): void {
98 `${this.chargingStation.logPrefix()} ${moduleName}.messageErrorHandler: Error at handling message:`,
103 private async commandHandler(
104 command
: BroadcastChannelProcedureName
,
105 requestPayload
: BroadcastChannelRequestPayload
106 ): Promise
<CommandResponse
| undefined> {
108 case BroadcastChannelProcedureName
.START_CHARGING_STATION
:
109 this.chargingStation
.start();
111 case BroadcastChannelProcedureName
.STOP_CHARGING_STATION
:
112 await this.chargingStation
.stop();
114 case BroadcastChannelProcedureName
.OPEN_CONNECTION
:
115 this.chargingStation
.openWSConnection();
117 case BroadcastChannelProcedureName
.CLOSE_CONNECTION
:
118 this.chargingStation
.closeWSConnection();
120 case BroadcastChannelProcedureName
.START_TRANSACTION
:
121 return this.chargingStation
.ocppRequestService
.requestHandler
<
122 StartTransactionRequest
,
123 StartTransactionResponse
124 >(this.chargingStation
, RequestCommand
.START_TRANSACTION
, {
125 connectorId
: requestPayload
.connectorId
,
126 idTag
: requestPayload
.idTag
,
128 case BroadcastChannelProcedureName
.STOP_TRANSACTION
:
129 return this.chargingStation
.ocppRequestService
.requestHandler
<
130 StopTransactionRequest
,
131 StopTransactionResponse
132 >(this.chargingStation
, RequestCommand
.STOP_TRANSACTION
, {
133 transactionId
: requestPayload
.transactionId
,
134 meterStop
: this.chargingStation
.getEnergyActiveImportRegisterByTransactionId(
135 requestPayload
.transactionId
,
138 idTag
: this.chargingStation
.getTransactionIdTag(requestPayload
.transactionId
),
139 ...(requestPayload
.reason
&& { reason
: requestPayload
.reason
}),
141 case BroadcastChannelProcedureName
.START_AUTOMATIC_TRANSACTION_GENERATOR
:
142 this.chargingStation
.startAutomaticTransactionGenerator(requestPayload
.connectorIds
);
144 case BroadcastChannelProcedureName
.STOP_AUTOMATIC_TRANSACTION_GENERATOR
:
145 this.chargingStation
.stopAutomaticTransactionGenerator(requestPayload
.connectorIds
);
148 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
149 throw new BaseError(`Unknown worker broadcast channel command: ${command}`);
153 private commandResponseToResponseStatus(commandResponse
: CommandResponse
): ResponseStatus
{
154 if (commandResponse
?.idTagInfo
?.status === AuthorizationStatus
.ACCEPTED
) {
155 return ResponseStatus
.SUCCESS
;
157 return ResponseStatus
.FAILURE
;