1 import type { RawData
} from
'ws';
3 import BaseError from
'../../../exception/BaseError';
4 import { Bootstrap
} from
'../../../internal';
5 import type { JsonType
} from
'../../../types/JsonType';
9 ProtocolRequestHandler
,
14 } from
'../../../types/UIProtocol';
15 import logger from
'../../../utils/Logger';
16 import UIServiceWorkerBroadcastChannel from
'../../UIServiceWorkerBroadcastChannel';
17 import type { AbstractUIServer
} from
'../AbstractUIServer';
19 const moduleName
= 'AbstractUIService';
21 export default abstract class AbstractUIService
{
22 protected readonly version
: ProtocolVersion
;
23 protected readonly uiServer
: AbstractUIServer
;
24 protected readonly requestHandlers
: Map
<ProcedureName
, ProtocolRequestHandler
>;
25 protected uiServiceWorkerBroadcastChannel
: UIServiceWorkerBroadcastChannel
;
27 constructor(uiServer
: AbstractUIServer
, version
: ProtocolVersion
) {
28 this.version
= version
;
29 this.uiServer
= uiServer
;
30 this.requestHandlers
= new Map
<ProcedureName
, ProtocolRequestHandler
>([
31 [ProcedureName
.LIST_CHARGING_STATIONS
, this.handleListChargingStations
.bind(this)],
32 [ProcedureName
.START_SIMULATOR
, this.handleStartSimulator
.bind(this)],
33 [ProcedureName
.STOP_SIMULATOR
, this.handleStopSimulator
.bind(this)],
35 this.uiServiceWorkerBroadcastChannel
= new UIServiceWorkerBroadcastChannel(this);
38 public async requestHandler(request
: RawData
| JsonType
): Promise
<void> {
39 let messageId
: string;
40 let command
: ProcedureName
;
41 let requestPayload
: RequestPayload
| undefined;
42 let responsePayload
: ResponsePayload
;
44 [messageId
, command
, requestPayload
] = this.requestValidation(request
);
46 if (this.requestHandlers
.has(command
) === false) {
48 `${command} is not implemented to handle message payload ${JSON.stringify(
56 // Call the request handler to build the response payload
57 responsePayload
= await this.requestHandlers
.get(command
)(messageId
, requestPayload
);
60 logger
.error(`${this.logPrefix(moduleName, 'messageHandler')} Handle request error:`, error
);
62 status: ResponseStatus
.FAILURE
,
66 errorMessage
: (error
as Error).message
,
67 errorStack
: (error
as Error).stack
,
71 if (responsePayload
!== undefined) {
73 this.sendResponse(messageId
?? 'error', responsePayload
);
79 procedureName
: ProcedureName
,
80 requestPayload
: RequestPayload
82 this.uiServer
.sendRequest(
83 this.uiServer
.buildProtocolRequest(messageId
, procedureName
, requestPayload
)
87 public sendResponse(messageId
: string, responsePayload
: ResponsePayload
): void {
88 this.uiServer
.sendResponse(this.uiServer
.buildProtocolResponse(messageId
, responsePayload
));
91 public logPrefix(modName
: string, methodName
: string): string {
92 return this.uiServer
.logPrefix(modName
, methodName
);
95 // Validate the raw data received from the UI server
96 private requestValidation(rawData
: RawData
| JsonType
): ProtocolRequest
{
100 // 'requestValidation'
101 // )} Data received in string format: ${rawData.toString()}`
104 const data
= JSON
.parse(rawData
.toString()) as JsonType
[];
106 if (Array.isArray(data
) === false) {
107 throw new BaseError('UI protocol request is not an array');
110 if (data
.length
!== 3) {
111 throw new BaseError('UI protocol request is malformed');
114 return data
as ProtocolRequest
;
117 private handleListChargingStations(): ResponsePayload
{
118 // TODO: remove cast to unknown
120 status: ResponseStatus
.SUCCESS
,
121 ...Array.from(this.uiServer
.chargingStations
.values()),
122 } as unknown
as ResponsePayload
;
125 private async handleStartSimulator(): Promise
<ResponsePayload
> {
126 await Bootstrap
.getInstance().start();
127 return { status: ResponseStatus
.SUCCESS
};
130 private async handleStopSimulator(): Promise
<ResponsePayload
> {
131 await Bootstrap
.getInstance().stop();
132 return { status: ResponseStatus
.SUCCESS
};