Add a configuration section for the UI WS server
[e-mobility-charging-stations-simulator.git] / src / charging-station / UIWebSocketServer.ts
CommitLineData
4198ad5c 1import { Protocol, ProtocolCommand, ProtocolRequest, ProtocolVersion } from '../types/UIProtocol';
6a49ad23 2import WebSocket, { OPEN, Server, ServerOptions } from 'ws';
4198ad5c
JB
3
4import AbstractUIService from './UIWebSocketServices/AbstractUIService';
5import BaseError from '../exception/BaseError';
6a49ad23 6import Configuration from '../utils/Configuration';
4198ad5c
JB
7import { IncomingMessage } from 'http';
8import UIServiceFactory from './UIWebSocketServices/UIServiceFactory';
9import Utils from '../utils/Utils';
4198ad5c
JB
10import logger from '../utils/Logger';
11
6a49ad23 12export default class UIWebSocketServer extends Server {
4198ad5c
JB
13 public uiService: AbstractUIService;
14
6a49ad23 15 public constructor(options?: ServerOptions, callback?: () => void) {
4198ad5c 16 // Create the WebSocket Server
6a49ad23 17 super(options ?? Configuration.getUIWebSocketServer().options, callback);
4198ad5c
JB
18 }
19
20 public broadcastToClients(message: string | Record<string, unknown>): void {
21 for (const client of this.clients) {
6a49ad23 22 if (client?.readyState === OPEN) {
4198ad5c
JB
23 client.send(message);
24 }
25 }
26 }
27
28 public start(): void {
29 this.on('connection', (socket: WebSocket, request: IncomingMessage): void => {
30 const protocolIndex = socket.protocol.indexOf(Protocol.UI);
31 const version = socket.protocol.substring(protocolIndex + Protocol.UI.length) as ProtocolVersion;
32 this.uiService = UIServiceFactory.getUIServiceImplementation(version, this);
33 if (!this.uiService) {
410a760d 34 throw new BaseError(`Could not find a UI service implementation for UI protocol version ${version}`);
4198ad5c
JB
35 }
36 // FIXME: check connection validity
37 socket.on('message', (messageData) => {
38 let [command, payload]: ProtocolRequest = [ProtocolCommand.UNKNOWN, {}];
39 const protocolRequest = JSON.parse(messageData.toString()) as ProtocolRequest;
40 if (Utils.isIterable(protocolRequest)) {
41 [command, payload] = protocolRequest;
42 } else {
410a760d 43 throw new BaseError('UI protocol request is not iterable');
4198ad5c
JB
44 }
45 this.uiService.handleMessage(command, payload).catch(() => {
46 logger.error(`${this.logPrefix()} Error while handling command %s message: %j`, command, payload);
47 });
48 });
49 socket.on('error', (error) => {
50 logger.error(`${this.logPrefix()} Error on WebSocket: %j`, error);
51 });
52 });
53 }
54
55 public stop(): void {
56 this.close();
57 }
58
59 public logPrefix(): string {
410a760d 60 return Utils.logPrefix(' UI WebSocket Server:');
4198ad5c
JB
61 }
62}