class WebSocketConnection extends Connection { static priority = 800; static name = 'WS'; #ws; #packet_buffer; #reconnect; onConnChange(s){} constructor(hub) { super(hub); this.options.enabled = false; this.options.ip = false; this.options.port = false; this.options.connect_timeout = 3000; this.#packet_buffer = new PacketBufferScanFirst(data => { this.hub._parsePacket(this, data); }); } isConnected() { return this.#ws && this.#ws.readyState == 1; } async begin(){} async discover(){} async search(){} async connect() { if (this.#ws) return; this._setState(ConnectionState.CONNECTING); this.#reconnect = true; this.#ws = await WebSocketConnection.#wsOpenAsync(`ws://${this.options.ip}:${this.options.port}/`, ['hub'], this.options.connect_timeout); this._setState(ConnectionState.CONNECTED); this.#packet_buffer.clear(); this.#ws.onclose = async () => { this._setState(ConnectionState.DISCONNECTED); this.#ws = undefined; await sleep(500); if (this.#reconnect) await this.connect(); }; this.#ws.onmessage = (e) => { this.#packet_buffer.push(e.data); }; } async disconnect() { this._setState(ConnectionState.DISCONNECTED); this.#reconnect = false; if (this.isConnected()) this.#ws.close(); } async send(text) { if (this.isConnected()) this.#ws.send(text); } /** * * @param {string} url * @param {string[]} protos * @param {number} timeout * @returns {Promise} */ static #wsOpenAsync(url, protos, timeout) { return new Promise((res, rej) => { const tid = setTimeout(handler, timeout); function handler(e) { ws.removeEventListener('open', handler); ws.removeEventListener('error', handler); clearTimeout(tid); if (ws.readyState === WebSocket.OPEN) res(ws); else rej(e ?? new TimeoutError()); } const ws = new WebSocket(url, protos); ws.addEventListener('open', handler); ws.addEventListener('error', handler); }) } }