Add one sanity check at UI server incoming requests handling
[e-mobility-charging-stations-simulator.git] / src / charging-station / ui-server / ui-services / AbstractUIService.ts
1 import { RawData } from 'ws';
2
3 import BaseError from '../../../exception/BaseError';
4 import { JsonType } from '../../../types/JsonType';
5 import {
6 ProtocolCommand,
7 ProtocolRequest,
8 ProtocolRequestHandler,
9 ProtocolVersion,
10 } from '../../../types/UIProtocol';
11 import logger from '../../../utils/Logger';
12 import Utils from '../../../utils/Utils';
13 import { AbstractUIServer } from '../AbstractUIServer';
14
15 export default abstract class AbstractUIService {
16 protected readonly version: ProtocolVersion;
17 protected readonly uiServer: AbstractUIServer;
18 protected readonly messageHandlers: Map<ProtocolCommand, ProtocolRequestHandler>;
19
20 constructor(uiServer: AbstractUIServer, version: ProtocolVersion) {
21 this.version = version;
22 this.uiServer = uiServer;
23 this.messageHandlers = new Map<ProtocolCommand, ProtocolRequestHandler>([
24 [ProtocolCommand.LIST_CHARGING_STATIONS, this.handleListChargingStations.bind(this)],
25 ]);
26 }
27
28 public async messageHandler(request: RawData): Promise<void> {
29 let messageId: string;
30 let command: ProtocolCommand;
31 let payload: JsonType;
32 const protocolRequest = JSON.parse(request.toString()) as ProtocolRequest;
33 if (Utils.isIterable(protocolRequest)) {
34 [messageId, command, payload] = protocolRequest;
35 } else {
36 throw new BaseError('UI protocol request is not iterable');
37 }
38 // TODO: should probably be moved to the ws verify clients callback
39 if (protocolRequest.length !== 3) {
40 throw new BaseError('UI protocol request is malformed');
41 }
42 let messageResponse: JsonType;
43 if (this.messageHandlers.has(command)) {
44 try {
45 // Call the message handler to build the message response
46 messageResponse = (await this.messageHandlers.get(command)(payload)) as JsonType;
47 } catch (error) {
48 // Log
49 logger.error(this.uiServer.logPrefix() + ' Handle message error: %j', error);
50 throw error;
51 }
52 } else {
53 // Throw exception
54 throw new BaseError(
55 `${command} is not implemented to handle message payload ${JSON.stringify(
56 payload,
57 null,
58 2
59 )}`
60 );
61 }
62 // Send the message response
63 this.uiServer.sendResponse(this.buildProtocolMessage(messageId, command, messageResponse));
64 }
65
66 protected buildProtocolMessage(
67 messageId: string,
68 command: ProtocolCommand,
69 payload: JsonType
70 ): string {
71 return JSON.stringify([messageId, command, payload]);
72 }
73
74 private handleListChargingStations(): JsonType {
75 return Array.from(this.uiServer.chargingStations);
76 }
77 }