Add UI protocol Insomnia project export instead of just the collection
[e-mobility-charging-stations-simulator.git] / src / charging-station / ui-server / UIWebSocketServer.ts
1 import type { IncomingMessage } from 'http';
2
3 import WebSocket from 'ws';
4
5 import type { ServerOptions } from '../../types/ConfigurationData';
6 import { WebSocketCloseEventStatusCode } from '../../types/WebSocket';
7 import Configuration from '../../utils/Configuration';
8 import logger from '../../utils/Logger';
9 import Utils from '../../utils/Utils';
10 import { AbstractUIServer } from './AbstractUIServer';
11 import UIServiceFactory from './ui-services/UIServiceFactory';
12 import { UIServiceUtils } from './ui-services/UIServiceUtils';
13
14 const moduleName = 'UIWebSocketServer';
15
16 export default class UIWebSocketServer extends AbstractUIServer {
17 public constructor(options?: ServerOptions) {
18 super();
19 this.server = new WebSocket.Server(options ?? Configuration.getUIServer().options);
20 }
21
22 public start(): void {
23 this.server.on('connection', (socket: WebSocket, request: IncomingMessage): void => {
24 const [protocol, version] = UIServiceUtils.getProtocolAndVersion(socket.protocol);
25 if (UIServiceUtils.isProtocolAndVersionSupported(protocol, version) === false) {
26 logger.error(
27 `${this.logPrefix(
28 moduleName,
29 'start.server.onconnection'
30 )} Unsupported UI protocol version: '${protocol}${version}'`
31 );
32 socket.close(WebSocketCloseEventStatusCode.CLOSE_PROTOCOL_ERROR);
33 }
34 if (!this.uiServices.has(version)) {
35 this.uiServices.set(version, UIServiceFactory.getUIServiceImplementation(version, this));
36 }
37 // FIXME: check connection validity
38 socket.on('message', (rawData) => {
39 this.uiServices
40 .get(version)
41 .requestHandler(rawData)
42 .catch(() => {
43 /* Error caught by AbstractUIService */
44 });
45 });
46 socket.on('error', (error) => {
47 logger.error(
48 `${this.logPrefix(moduleName, 'start.socket.onerror')} Error on WebSocket:`,
49 error
50 );
51 });
52 });
53 }
54
55 public stop(): void {
56 this.chargingStations.clear();
57 }
58
59 public sendRequest(request: string): void {
60 this.broadcastToClients(request);
61 }
62
63 public sendResponse(response: string): void {
64 // TODO: send response only to the client that sent the request
65 this.broadcastToClients(response);
66 }
67
68 public logPrefix(modName?: string, methodName?: string): string {
69 const logMsg =
70 modName && methodName
71 ? ` UI WebSocket Server | ${modName}.${methodName}:`
72 : ' UI WebSocket Server |';
73 return Utils.logPrefix(logMsg);
74 }
75
76 private broadcastToClients(message: string): void {
77 for (const client of (this.server as WebSocket.Server).clients) {
78 if (client?.readyState === WebSocket.OPEN) {
79 client.send(message);
80 }
81 }
82 }
83 }