RTU_ALL_AI/config/web/js/ws-client.js

104 lines
2.4 KiB
JavaScript

/**
* @file ws-client.js
* @brief WebSocket 客户端封装 — 自动重连 + 事件分发
*/
var WsClient = {
ws: null, url: '', status: 'disconnected', timer: null,
msgCbs: [], statusCbs: [],
onMsg: function(cb) { this.msgCbs.push(cb); },
onStatus: function(cb) { this.statusCbs.push(cb); },
connect: function(url) {
if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING))
{
return;
}
this.url = url;
this._setStatus('connecting');
try
{
this.ws = new WebSocket(url);
this.ws.binaryType = 'arraybuffer';
}
catch (e)
{
this._setStatus('disconnected');
this._schedule();
return;
}
this.ws.onopen = function() {
var self = WsClient;
self._setStatus('connected');
if (self.timer) { clearTimeout(self.timer); self.timer = null; }
self.send({ type: 'get_cmds' });
};
this.ws.onclose = function() {
var self = WsClient;
self._setStatus('disconnected');
self.ws = null;
self._schedule();
};
this.ws.onerror = function() {};
this.ws.onmessage = function(e) {
var self = WsClient;
var raw = e.data;
if (raw instanceof ArrayBuffer)
{
self.msgCbs.forEach(function(cb) { try { cb(null, raw); } catch(ex) {} });
return;
}
var data = null;
try { data = JSON.parse(raw); } catch(ex) {}
self.msgCbs.forEach(function(cb) { try { cb(data || raw, null); } catch(ex) {} });
};
},
send: function(obj) {
if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
{
if (typeof toast === 'function') { toast(I18n.t('toast.ws_error'), 'error'); }
return;
}
var raw = (typeof obj === 'object') ? JSON.stringify(obj) : String(obj);
this.ws.send(raw);
},
_setStatus: function(s) {
if (this.status === s) return;
this.status = s;
var dot = document.getElementById('nav-status-dot');
var txt = document.getElementById('nav-status-text');
if (dot) { dot.className = 'nav-status-dot ' + s; }
if (txt)
{
var map = { connected: I18n.t('status.connected'), disconnected: I18n.t('status.disconnected'), connecting: I18n.t('status.connecting') };
txt.textContent = map[s] || s;
}
this.statusCbs.forEach(function(cb) { cb(s); });
},
_schedule: function() {
var self = this;
if (self.timer) return;
self.timer = setTimeout(function() {
self.timer = null;
if (self.status === 'disconnected') { self.connect(self.url); }
}, 3000);
}
};