1 import type { JsonType
} from
'@/types/JsonType';
2 import { ProcedureName
, ResponseStatus
} from
'@/types/UIProtocol';
3 import type { ProtocolResponse
, ResponsePayload
} from
'@/types/UIProtocol';
5 import Utils from
'./Utils';
6 import config from
'@/assets/config';
7 import { v4
as uuidv4
} from
'uuid';
9 type ResponseHandler
= {
10 procedureName
: ProcedureName
;
11 resolve
: (value
: ResponsePayload
| PromiseLike
<ResponsePayload
>) => void;
12 reject
: (reason
?: any) => void;
15 export default class UIClient
{
16 private static _instance
: UIClient
| null = null;
18 private _ws
!: WebSocket
;
19 private _responseHandlers
: Map
<string, ResponseHandler
>;
21 private constructor() {
23 this._responseHandlers
= new Map
<string, ResponseHandler
>();
26 public static getInstance() {
27 if (UIClient
._instance
=== null) {
28 UIClient
._instance
= new UIClient();
30 return UIClient
._instance
;
33 public registerWSonOpenListener(listener
: (event
: Event
) => void) {
34 this._ws
.addEventListener('open', listener
);
37 public async startSimulator(): Promise
<ResponsePayload
> {
38 return this.sendRequest(ProcedureName
.START_SIMULATOR
, {});
41 public async stopSimulator(): Promise
<ResponsePayload
> {
42 return this.sendRequest(ProcedureName
.STOP_SIMULATOR
, {});
45 public async listChargingStations(): Promise
<ResponsePayload
> {
46 return this.sendRequest(ProcedureName
.LIST_CHARGING_STATIONS
, {});
49 public async startChargingStation(hashId
: string): Promise
<ResponsePayload
> {
50 return this.sendRequest(ProcedureName
.START_CHARGING_STATION
, { hashId
});
53 public async stopChargingStation(hashId
: string): Promise
<ResponsePayload
> {
54 return this.sendRequest(ProcedureName
.STOP_CHARGING_STATION
, { hashId
});
57 public async openConnection(hashId
: string): Promise
<ResponsePayload
> {
58 return this.sendRequest(ProcedureName
.OPEN_CONNECTION
, {
63 public async closeConnection(hashId
: string): Promise
<ResponsePayload
> {
64 return this.sendRequest(ProcedureName
.CLOSE_CONNECTION
, {
69 public async startTransaction(
72 idTag
: string | undefined
73 ): Promise
<ResponsePayload
> {
74 return this.sendRequest(ProcedureName
.START_TRANSACTION
, {
81 public async stopTransaction(
83 transactionId
: number | undefined
84 ): Promise
<ResponsePayload
> {
85 return this.sendRequest(ProcedureName
.STOP_TRANSACTION
, {
91 private openWS(): void {
92 this._ws
= new WebSocket(
93 `ws://${config.uiServer.host}:${config.uiServer.port}`,
94 config
.uiServer
.protocol
96 this._ws
.onmessage
= this.responseHandler
.bind(this);
97 this._ws
.onerror
= (errorEvent
) => {
98 console
.error('WebSocket error: ', errorEvent
);
100 this._ws
.onclose
= (closeEvent
) => {
101 console
.info('WebSocket close: ', closeEvent
);
105 private setResponseHandler(
107 procedureName
: ProcedureName
,
108 resolve
: (value
: ResponsePayload
| PromiseLike
<ResponsePayload
>) => void,
109 reject
: (reason
?: any) => void
111 this._responseHandlers
.set(id
, { procedureName
, resolve
, reject
});
114 private getResponseHandler(id
: string): ResponseHandler
| undefined {
115 return this._responseHandlers
.get(id
);
118 private deleteResponseHandler(id
: string): boolean {
119 return this._responseHandlers
.delete(id
);
122 private async sendRequest(command
: ProcedureName
, data
: JsonType
): Promise
<ResponsePayload
> {
124 return Utils
.promiseWithTimeout(
125 new Promise((resolve
, reject
) => {
127 const msg
= JSON
.stringify([uuid
, command
, data
]);
129 if (this._ws
.readyState
!== WebSocket
.OPEN
) {
132 if (this._ws
.readyState
=== WebSocket
.OPEN
) {
135 throw new Error(`Send request ${command} message: connection not opened`);
138 this.setResponseHandler(uuid
, command
, resolve
, reject
);
141 Error(`Send request ${command} message timeout`),
143 this._responseHandlers
.delete(uuid
);
148 private responseHandler(messageEvent
: MessageEvent
<string>): void {
149 const data
= JSON
.parse(messageEvent
.data
) as ProtocolResponse
;
151 if (Array.isArray(data
) === false) {
152 throw new Error('Response not an array: ' + JSON
.stringify(data
, null, 2));
155 const [uuid
, response
] = data
;
157 if (this._responseHandlers
.has(uuid
) === true) {
158 switch (response
.status) {
159 case ResponseStatus
.SUCCESS
:
160 this.getResponseHandler(uuid
)?.resolve(response
);
162 case ResponseStatus
.FAILURE
:
163 this.getResponseHandler(uuid
)?.reject(response
);
166 console
.error(`Response status not supported: ${response.status}`);
168 this.deleteResponseHandler(uuid
);
170 throw new Error('Not a response to a request: ' + JSON
.stringify(data
, null, 2));