1 import { JsonType
} from
'@/type/JsonType';
7 } from
'@/type/UIProtocol';
8 import Utils from
'./Utils';
9 import config from
'@/assets/config';
10 import { v4
as uuidv4
} from
'uuid';
12 type ResponseHandler
= {
13 resolve
: (value
: ResponsePayload
| PromiseLike
<ResponsePayload
>) => void;
14 reject
: (reason
?: any) => void;
15 procedureName
: ProcedureName
;
18 export default class UIClient
{
19 private static _instance
: UIClient
| null = null;
21 private _ws
!: WebSocket
;
22 private _responseHandlers
: Map
<string, ResponseHandler
>;
24 private constructor() {
26 this._responseHandlers
= new Map
<string, ResponseHandler
>();
29 public static get
instance() {
30 if (UIClient
._instance
=== null) {
31 UIClient
._instance
= new UIClient();
33 return UIClient
._instance
;
36 public onOpen(listener
: (this: WebSocket
, ev
: Event
) => void) {
37 this._ws
.addEventListener('open', listener
);
40 public async startSimulator(): Promise
<ResponsePayload
> {
41 return this.sendRequest(ProcedureName
.START_SIMULATOR
, {});
44 public async stopSimulator(): Promise
<ResponsePayload
> {
45 return this.sendRequest(ProcedureName
.STOP_SIMULATOR
, {});
48 public async listChargingStations(): Promise
<ResponsePayload
> {
49 return this.sendRequest(ProcedureName
.LIST_CHARGING_STATIONS
, {});
52 public async startTransaction(
55 idTag
: string | undefined
56 ): Promise
<ResponsePayload
> {
57 return this.sendRequest(ProcedureName
.START_TRANSACTION
, {
64 public async stopTransaction(
66 transactionId
: number | undefined
67 ): Promise
<ResponsePayload
> {
68 return this.sendRequest(ProcedureName
.STOP_TRANSACTION
, {
74 public async openConnection(hashId
: string): Promise
<ResponsePayload
> {
75 return this.sendRequest(ProcedureName
.OPEN_CONNECTION
, {
80 public async closeConnection(hashId
: string): Promise
<ResponsePayload
> {
81 return this.sendRequest(ProcedureName
.CLOSE_CONNECTION
, {
86 private openWS(): void {
87 this._ws
= new WebSocket(
88 `ws://${config.emobility.host}:${config.emobility.port}`,
89 config
.emobility
.protocol
91 this._ws
.onmessage
= this.responseHandler
.bind(this);
94 private setResponseHandler(
96 resolve
: (value
: ResponsePayload
| PromiseLike
<ResponsePayload
>) => void,
97 reject
: (reason
?: any) => void,
98 procedureName
: ProcedureName
100 this._responseHandlers
.set(id
, { resolve
, reject
, procedureName
});
103 private getResponseHandler(id
: string): ResponseHandler
| undefined {
104 return this._responseHandlers
.get(id
);
107 private async sendRequest(command
: ProcedureName
, data
: JsonType
): Promise
<ResponsePayload
> {
109 return Utils
.promiseWithTimeout(
110 new Promise((resolve
, reject
) => {
112 const msg
= JSON
.stringify([uuid
, command
, data
]);
114 if (this._ws
.readyState
!== WebSocket
.OPEN
) {
117 if (this._ws
.readyState
=== WebSocket
.OPEN
) {
120 throw new Error(`Send request ${command} message: connection not opened`);
123 this.setResponseHandler(uuid
, resolve
, reject
, command
);
126 Error(`Send request ${command} message timeout`),
128 this._responseHandlers
.delete(uuid
);
133 private responseHandler(messageEvent
: MessageEvent
<string>): void {
134 const data
= JSON
.parse(messageEvent
.data
) as ProtocolResponse
;
136 if (Array.isArray(data
) === false) {
137 throw new Error('Response not an array: ' + JSON
.stringify(data
, null, 2));
140 const [uuid
, response
] = data
;
142 if (this._responseHandlers
.has(uuid
) === true) {
143 switch (response
.status) {
144 case ResponseStatus
.SUCCESS
:
145 this.getResponseHandler(uuid
)?.resolve(response
);
147 case ResponseStatus
.FAILURE
:
148 this.getResponseHandler(uuid
)?.reject(response
);
151 throw new Error(`Response status not supported: ${response.status}`);
154 throw new Error('Not a response to a request: ' + JSON
.stringify(data
, null, 2));