import { Protocol } from "src/entities/WSProtocol"; export default class ClientConnection { ws: WebSocket | null = null; url = ""; user_name = ""; password = ""; _is_login = false; _rpc_id_counter = 0; rpc_map = new Map< number, (is_fail: boolean, packet: Protocol.Commands, data: string) => void >(); public login_callback: | ((this: ClientConnection, logined: boolean) => void) | null = null; public message_callback: | (( this: ClientConnection, command: string, packet: Protocol.Commands, data: string ) => void) | null = null; constructor( url: string, user_name?: string | null, password?: string | null ) { this.reconnectTo(url, user_name, password); } get is_connected() { return this.ws && this.ws.readyState == WebSocket.OPEN; } get is_login() { return this._is_login; } public reconnectTo( url: string, user_name?: string | null, password?: string | null ) { this.url = url; this.user_name = user_name ?? ""; this.password = password ?? ""; if (this.ws) { this.ws.close(); } this.ws = new WebSocket(url); this.initializeWs(); } initializeWs() { if (this.ws) { this.ws.onclose = (ev) => { this.onClose(ev); }; this.ws.onerror = (ev) => { this.onError(ev); }; this.ws.onopen = (ev) => { this.onOpen(ev); }; this.ws.onmessage = (ev) => { this.onMessage(ev); }; } } login() { if (this.is_connected) { const request = new Protocol.LoginRequest(this.user_name, this.password); this.ws?.send(JSON.stringify(request)); } } onClose(ev: CloseEvent) { this._is_login = false; console.log("onClose"); } onError(ev: Event) { this._is_login = false; setTimeout(() => { this.reconnectTo(this.url, this.user_name, this.password); }, 5000); } onOpen(ev: Event) { this._is_login = false; this.login(); } onMessage(ev: MessageEvent) { try { const packet = JSON.parse(ev.data) as Protocol.PacketEntity; if (packet) { if (packet.has_exception) { console.error(ev.data); } if (Protocol.Commands.AllCommands.has(packet.command)) { if ( packet.flag == Protocol.PacketEntity.FLAG_RESPONSE || packet.flag == Protocol.PacketEntity.FLAG_NOTIFY ) { if (packet.command == Protocol.Commands.kLogin) { const login_response = JSON.parse( ev.data ) as Protocol.LoginResponse; if (login_response) { this._is_login = !login_response.has_exception && login_response.success; if ( this.login_callback && typeof this.login_callback == "function" ) { this.login_callback(this._is_login); } } } if (this.rpc_map.has(packet.rpc_id)) { const f = this.rpc_map.get(packet.rpc_id); if (f && typeof f == "function") { f(false, packet, ev.data); this.rpc_map.delete(packet.rpc_id); } } if (this.message_callback) { this.message_callback(packet.command, packet, ev.data); } } } } } catch (e) { console.error(e); } } public async doRpc(reuqest: any | Protocol.PacketEntity) { return new Promise((resolve, reject) => { if (!reuqest) { reject(); } const rpc_id = ++this._rpc_id_counter; if (this.rpc_map.has(rpc_id)) { const f = this.rpc_map.get(rpc_id); if (f && typeof f == "function") { f(true, new Protocol.Commands(), ""); this.rpc_map.delete(rpc_id); } } reuqest.rpc_id = rpc_id; this.ws?.send(JSON.stringify(reuqest)); this.rpc_map.set( rpc_id, (is_fail: boolean, packet: Protocol.Commands, data: string) => { if (is_fail) { reject(); } else { try { const response = JSON.parse( data ) as Protocol.GetApplicationConfigResponseEntity; if (response) { resolve(response); } else { reject(); console.log("reject"); } } catch { reject(); console.log("reject"); } } } ); }); } public async getSignalSources() { return new Promise((resolve, reject) => { const rpc_id = ++this._rpc_id_counter; if (this.rpc_map.has(rpc_id)) { const f = this.rpc_map.get(rpc_id); if (f && typeof f == "function") { f(true, new Protocol.Commands(), ""); this.rpc_map.delete(rpc_id); } } this.ws?.send( JSON.stringify(new Protocol.GetSignalSourcesRequest(rpc_id)) ); this.rpc_map.set( rpc_id, (is_fail: boolean, packet: Protocol.Commands, data: string) => { if (is_fail) { reject(); } else { try { const response = JSON.parse( data ) as Protocol.GetSignalSourcesResponse; if (response) { resolve(response); } else { reject(); console.log("reject"); } } catch { reject(); console.log("reject"); } } } ); }); } public async getApplicationSettins() { try { return (await this.doRpc( new Protocol.GetApplicationConfigRequestEntity() )) as Protocol.GetApplicationConfigResponseEntity; } catch (e) { console.error(e); } } }