1 import Utils from
'./Utils';
9 import config from
'@/assets/config';
11 type ResponseHandler
= {
12 procedureName
: ProcedureName
;
13 resolve
: (value
: ResponsePayload
| PromiseLike
<ResponsePayload
>) => void;
14 reject
: (reason
?: unknown
) => void;
17 export default class UIClient
{
18 private static instance
: UIClient
| null = null;
20 private ws
!: WebSocket
;
21 private responseHandlers
: Map
<string, ResponseHandler
>;
23 private constructor() {
25 this.responseHandlers
= new Map
<string, ResponseHandler
>();
28 public static getInstance() {
29 if (UIClient
.instance
=== null) {
30 UIClient
.instance
= new UIClient();
32 return UIClient
.instance
;
35 public registerWSonOpenListener(listener
: (event
: Event
) => void) {
36 this.ws
.addEventListener('open', listener
);
39 public async startSimulator(): Promise
<ResponsePayload
> {
40 return this.sendRequest(ProcedureName
.START_SIMULATOR
, {});
43 public async stopSimulator(): Promise
<ResponsePayload
> {
44 return this.sendRequest(ProcedureName
.STOP_SIMULATOR
, {});
47 public async listChargingStations(): Promise
<ResponsePayload
> {
48 return this.sendRequest(ProcedureName
.LIST_CHARGING_STATIONS
, {});
51 public async startChargingStation(hashId
: string): Promise
<ResponsePayload
> {
52 return this.sendRequest(ProcedureName
.START_CHARGING_STATION
, { hashIds
: [hashId
] });
55 public async stopChargingStation(hashId
: string): Promise
<ResponsePayload
> {
56 return this.sendRequest(ProcedureName
.STOP_CHARGING_STATION
, { hashIds
: [hashId
] });
59 public async openConnection(hashId
: string): Promise
<ResponsePayload
> {
60 return this.sendRequest(ProcedureName
.OPEN_CONNECTION
, {
65 public async closeConnection(hashId
: string): Promise
<ResponsePayload
> {
66 return this.sendRequest(ProcedureName
.CLOSE_CONNECTION
, {
71 public async startTransaction(
74 idTag
: string | undefined
75 ): Promise
<ResponsePayload
> {
76 return this.sendRequest(ProcedureName
.START_TRANSACTION
, {
83 public async stopTransaction(
85 transactionId
: number | undefined
86 ): Promise
<ResponsePayload
> {
87 return this.sendRequest(ProcedureName
.STOP_TRANSACTION
, {
93 public async startAutomaticTransactionGenerator(
96 ): Promise
<ResponsePayload
> {
97 return this.sendRequest(ProcedureName
.START_AUTOMATIC_TRANSACTION_GENERATOR
, {
99 connectorIds
: [connectorId
],
103 public async stopAutomaticTransactionGenerator(
106 ): Promise
<ResponsePayload
> {
107 return this.sendRequest(ProcedureName
.STOP_AUTOMATIC_TRANSACTION_GENERATOR
, {
109 connectorIds
: [connectorId
],
113 private openWS(): void {
114 this.ws
= new WebSocket(
115 `ws://${config.uiServer.host}:${config.uiServer.port}`,
116 config
.uiServer
.protocol
118 this.ws
.onmessage
= this.responseHandler
.bind(this);
119 this.ws
.onerror
= (errorEvent
) => {
120 console
.error('WebSocket error: ', errorEvent
);
122 this.ws
.onclose
= (closeEvent
) => {
123 console
.info('WebSocket closed: ', closeEvent
);
127 private setResponseHandler(
129 procedureName
: ProcedureName
,
130 resolve
: (value
: ResponsePayload
| PromiseLike
<ResponsePayload
>) => void,
131 reject
: (reason
?: unknown
) => void
133 this.responseHandlers
.set(id
, { procedureName
, resolve
, reject
});
136 private getResponseHandler(id
: string): ResponseHandler
| undefined {
137 return this.responseHandlers
.get(id
);
140 private deleteResponseHandler(id
: string): boolean {
141 return this.responseHandlers
.delete(id
);
144 private async sendRequest(
145 command
: ProcedureName
,
147 ): Promise
<ResponsePayload
> {
149 return Utils
.promiseWithTimeout(
150 new Promise((resolve
, reject
) => {
151 uuid
= crypto
.randomUUID();
152 const msg
= JSON
.stringify([uuid
, command
, data
]);
154 if (this.ws
.readyState
!== WebSocket
.OPEN
) {
157 if (this.ws
.readyState
=== WebSocket
.OPEN
) {
160 throw new Error(`Send request '${command}' message: connection not opened`);
163 this.setResponseHandler(uuid
, command
, resolve
, reject
);
166 Error(`Send request '${command}' message timeout`),
168 this.responseHandlers
.delete(uuid
);
173 private responseHandler(messageEvent
: MessageEvent
<string>): void {
174 const response
= JSON
.parse(messageEvent
.data
) as ProtocolResponse
;
176 if (Array.isArray(response
) === false) {
177 throw new Error(`Response not an array: ${JSON.stringify(response, null, 2)}`);
180 const [uuid
, responsePayload
] = response
;
182 if (this.responseHandlers
.has(uuid
) === true) {
183 switch (responsePayload
.status) {
184 case ResponseStatus
.SUCCESS
:
185 this.getResponseHandler(uuid
)?.resolve(responsePayload
);
187 case ResponseStatus
.FAILURE
:
188 this.getResponseHandler(uuid
)?.reject(responsePayload
);
191 console
.error(`Response status not supported: ${responsePayload.status}`);
193 this.deleteResponseHandler(uuid
);
195 throw new Error(`Not a response to a request: ${JSON.stringify(response, null, 2)}`);