Simplify AbtractUIService logPrefix method
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStationWorkerBroadcastChannel.ts
1 import BaseError from '../exception/BaseError';
2 import { RequestCommand } from '../types/ocpp/Requests';
3 import {
4 AuthorizationStatus,
5 StartTransactionRequest,
6 StartTransactionResponse,
7 StopTransactionReason,
8 StopTransactionRequest,
9 StopTransactionResponse,
10 } from '../types/ocpp/Transaction';
11 import {
12 BroadcastChannelProcedureName,
13 BroadcastChannelRequest,
14 BroadcastChannelRequestPayload,
15 BroadcastChannelResponsePayload,
16 MessageEvent,
17 } from '../types/WorkerBroadcastChannel';
18 import { ResponseStatus } from '../ui/web/src/type/UIProtocol';
19 import logger from '../utils/Logger';
20 import ChargingStation from './ChargingStation';
21 import WorkerBroadcastChannel from './WorkerBroadcastChannel';
22
23 const moduleName = 'ChargingStationWorkerBroadcastChannel';
24
25 type CommandResponse = StartTransactionResponse | StopTransactionResponse;
26
27 export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChannel {
28 private readonly chargingStation: ChargingStation;
29
30 constructor(chargingStation: ChargingStation) {
31 super();
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;
35 }
36
37 private async requestHandler(messageEvent: MessageEvent): Promise<void> {
38 if (this.isResponse(messageEvent.data)) {
39 return;
40 }
41
42 const [uuid, command, requestPayload] = messageEvent.data as BroadcastChannelRequest;
43
44 if (requestPayload?.hashId !== this.chargingStation.hashId) {
45 return;
46 }
47
48 let responsePayload: BroadcastChannelResponsePayload;
49 let commandResponse: CommandResponse;
50 try {
51 commandResponse = await this.commandHandler(command, requestPayload);
52 if (commandResponse === undefined) {
53 responsePayload = { status: ResponseStatus.SUCCESS };
54 } else {
55 responsePayload = { status: this.commandResponseToResponseStatus(commandResponse) };
56 }
57 } catch (error) {
58 logger.error(
59 `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: Handle request error:`,
60 error
61 );
62 responsePayload = {
63 status: ResponseStatus.FAILURE,
64 command,
65 requestPayload,
66 commandResponse,
67 errorMessage: (error as Error).message,
68 errorStack: (error as Error).stack,
69 };
70 }
71 this.sendResponse([uuid, responsePayload]);
72 }
73
74 private messageErrorHandler(messageEvent: MessageEvent): void {
75 logger.error(
76 `${this.chargingStation.logPrefix()} ${moduleName}.messageErrorHandler: Error at handling message:`,
77 { messageEvent, messageEventData: messageEvent.data }
78 );
79 }
80
81 private async commandHandler(
82 command: BroadcastChannelProcedureName,
83 requestPayload: BroadcastChannelRequestPayload
84 ): Promise<CommandResponse | undefined> {
85 switch (command) {
86 case BroadcastChannelProcedureName.START_TRANSACTION:
87 return this.chargingStation.ocppRequestService.requestHandler<
88 StartTransactionRequest,
89 StartTransactionResponse
90 >(this.chargingStation, RequestCommand.START_TRANSACTION, {
91 connectorId: requestPayload.connectorId,
92 idTag: requestPayload.idTag,
93 });
94 case BroadcastChannelProcedureName.STOP_TRANSACTION:
95 return this.chargingStation.ocppRequestService.requestHandler<
96 StopTransactionRequest,
97 StopTransactionResponse
98 >(this.chargingStation, RequestCommand.STOP_TRANSACTION, {
99 transactionId: requestPayload.transactionId,
100 meterStop: this.chargingStation.getEnergyActiveImportRegisterByTransactionId(
101 requestPayload.transactionId
102 ),
103 idTag: this.chargingStation.getTransactionIdTag(requestPayload.transactionId),
104 reason: StopTransactionReason.NONE,
105 });
106 case BroadcastChannelProcedureName.START_CHARGING_STATION:
107 this.chargingStation.start();
108 break;
109 case BroadcastChannelProcedureName.STOP_CHARGING_STATION:
110 await this.chargingStation.stop();
111 break;
112 default:
113 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
114 throw new BaseError(`Unknown broadcast channel command: ${command}`);
115 }
116 }
117
118 private commandResponseToResponseStatus(commandResponse: CommandResponse): ResponseStatus {
119 if (commandResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
120 return ResponseStatus.SUCCESS;
121 }
122 return ResponseStatus.FAILURE;
123 }
124 }