|
|
WSSÐÒéʾÀý AIWROK °æwebsocket
- /**
- * WSS ÐÒéʾÀý - AIWROK °æ
- *
- * ʹÓà AIWROK ÔÉú websocket ¶ÔÏóʵÏÖ ws:// ºÍ wss://£¨TLS ¼ÓÃÜ£©Á¬½Ó
- * Ö§³Ö£ºË«ÏòͨÐÅ¡¢ÐÄÌø±£»î¡¢¶ÏÏßÖØÁ¬¡¢JSON ÏûÏ¢ÊÕ·¢
- *
- * AIWROK ÔÉú WebSocket API£º
- * new websocket() - ´´½¨ÊµÀý
- * ws.setSocketID(String) - ÉèÖÃΨһID
- * ws.event(onOpen, onMsg, onErr, onClose) - ¹ÒÔØËĸö»Øµ÷
- * ws.connet(String) - Á¬½Ó·þÎñÆ÷£¨×¢ÒâÊÇË«n£©
- * ws.send(String) - ·¢ËÍÏûÏ¢
- * ws.close() - ¹Ø±ÕÁ¬½Ó
- *
- * ws:// ºÍ wss:// µÄÇø±ð£º
- * wss:// ×ß TLS ¼ÓÃÜͨµÀ£¬Êý¾Ý´«Ê䰲ȫ
- * AIWROK µÄ websocket ¶ÔÏó»á×Ô¶¯´¦Àí TLS ÎÕÊÖ
- *
- * ÒÀÀµ£ºAIWROK ÔÉú websocket ¶ÔÏó£¬ÁãÒÀÀµ
- *
- * ʹÓ÷½·¨£º
- * 1. ÐÞ¸Ä CFG.serverUrl ΪÄãµÄ wss:// µØÖ·
- * 2. AIWROK ÖÐÖ±½ÓÔËÐб¾½Å±¾
- * 3. ÈÕÖ¾´°¿Ú²é¿´Á¬½Ó״̬ºÍÊÕ·¢ÏûÏ¢
- */
- // ========== ÅäÖÃ ==========
- var CFG = {
- // WSS ·þÎñÆ÷µØÖ·£¨TLS ¼ÓÃÜ£©
- // wss:// ×ß¼ÓÃÜͨµÀ£¬ws:// ×ßÃ÷ÎÄͨµÀ
- serverUrl: "wss://echo.websocket.org/ws",
- // ÐÄÌø¼ä¸ô£¨Ã룩£¬¶¨Ê±·¢ PING ±£³ÖÁ¬½Ó
- heartbeatIntervalSec: 15,
- // ÖØÁ¬ÅäÖÃ
- reconnectIntervalMs: 3000, // ÖØÁ¬»ù´¡¼ä¸ô£¨ºÁÃ룩
- maxReconnectAttempts: 999, // ×î´óÖØÁ¬´ÎÊý£¨999=ÎÞÏÞ£©
- reconnectMultiplier: 1.5, // Ö¸ÊýÍ˱ܱ¶Êý
- maxReconnectDelayMs: 30000, // ×î´óÖØÁ¬ÑÓ³Ù£¨ºÁÃ룩
- // µ÷ÊÔÈÕÖ¾
- debug: true,
- // ½Å±¾ÔËÐÐʱ³¤£¨ºÁÃ룩£¬0=ÎÞÏÞ
- runDuration: 0
- };
- // ========== È«¾Ö״̬ ==========
- var G = {
- ws: null, // websocket ʵÀý
- connected: false, // ÊÇ·ñÒÑÁ¬½Ó
- reconnectCount: 0, // ÒÑÖØÁ¬´ÎÊý
- currentDelay: CFG.reconnectIntervalMs, // µ±Ç°ÖØÁ¬ÑÓ³Ù
- running: true, // ÔËÐбêÖ¾
- startTime: 0, // Æô¶¯Ê±¼ä
- msgSentCount: 0, // ÒÑ·¢ËÍÏûÏ¢Êý
- msgRecvCount: 0, // ÒѽÓÊÕÏûÏ¢Êý
- lastPongAt: 0, // ÉÏ´ÎÊÕµ½PONGʱ¼ä
- heartbeatTimer: null // ÐÄÌø¶¨Ê±Æ÷
- };
- // ========== ʱ¼ä¹¤¾ß ==========
- function nowMs() {
- return (new Date()).getTime();
- }
- function nowSec() {
- return Math.floor(nowMs() / 1000);
- }
- // ========== É豸ÐÅÏ¢ ==========
- function getDeviceInfo() {
- var info = { imei: "", brand: "", model: "", screen: "" };
- try { info.imei = device.getIMEI() || ""; } catch (e) {}
- try { info.brand = device.getBrand() || ""; } catch (e) {}
- try { info.model = device.getModel() || ""; } catch (e) {}
- try { info.screen = screen.getScreenWidth() + "x" + screen.getScreenHeight(); } catch (e) {}
- return info;
- }
- // ========== ÏûÏ¢·¢ËÍ ==========
- function sendMsg(data) {
- if (!G.connected || !G.ws) {
- printl("[WARN] δÁ¬½Ó£¬ÎÞ·¨·¢ËÍ");
- return false;
- }
- try {
- var raw;
- if (typeof data === "string") {
- raw = data;
- } else {
- raw = JSON.stringify(data);
- }
- G.ws.send(raw);
- G.msgSentCount++;
- printl("[SEND] " + raw.slice(0, 200));
- return true;
- } catch (e) {
- printl("[ERROR] " + "·¢ËÍÒì³£: " + e.message);
- return false;
- }
- }
- // ========== ´¦ÀíÊÕµ½µÄÏûÏ¢ ==========
- function handleMessage(raw) {
- G.msgRecvCount++;
- printl("[RECV] " + raw.slice(0, 200));
- var obj = null;
- try {
- obj = JSON.parse(raw);
- } catch (e) {
- printl("[DEBUG] " + "·Ç JSON ÏûÏ¢: " + raw.slice(0, 100));
- return;
- }
- // ¸ù¾ÝÏûÏ¢ÀàÐÍ´¦ÀíÒµÎñÂß¼
- if (obj.type === "WELCOME") {
- printl("[INFO] " + "·þÎñÆ÷»¶Ó: " + (obj.msg || ""));
- } else if (obj.type === "PING" || obj.type === "ping") {
- // ·þÎñ¶ËÐÄÌø£¬»Ø PONG
- G.lastPongAt = nowMs();
- sendMsg({ type: "PONG", ts: nowSec() });
- } else if (obj.type === "PONG" || obj.type === "pong") {
- // ÊÕµ½ PONG£¬¸üÐÂÐÄÌøÊ±¼ä
- G.lastPongAt = nowMs();
- printl("[DEBUG] ÊÕµ½ PONG");
- } else if (obj.type === "CMD_SCREENSHOT") {
- handleScreenshotCmd(obj);
- } else if (obj.type === "CMD_CLICK") {
- handleClickCmd(obj);
- } else if (obj.type === "CMD_STATUS") {
- handleStatusCmd(obj);
- } else {
- printl("[DEBUG] " + "δ´¦ÀíµÄÏûÏ¢ÀàÐÍ: " + obj.type);
- }
- }
- // ========== ÒµÎñÖ¸Á½ØÍ¼ ==========
- function handleScreenshotCmd(obj) {
- try {
- var bitmap = screen.screenShotFull();
- if (!bitmap) {
- sendMsg({ type: "CMD_RESP", cmd: "CMD_SCREENSHOT", ok: false, msg: "½ØÍ¼·µ»Ø¿Õ" });
- return;
- }
- var base64 = "" + bitmap.toBase64();
- try { bitmap.recycle(); } catch (e) {}
- sendMsg({
- type: "CMD_RESP",
- cmd: "CMD_SCREENSHOT",
- ok: true,
- cmdId: obj.cmdId,
- data: { base64: base64, length: base64.length }
- });
- } catch (e) {
- sendMsg({ type: "CMD_RESP", cmd: "CMD_SCREENSHOT", ok: false, msg: e.message });
- }
- }
- // ========== ÒµÎñÖ¸Áµã»÷ ==========
- function handleClickCmd(obj) {
- try {
- var x = parseInt(obj.data.x, 10);
- var y = parseInt(obj.data.y, 10);
- if (isNaN(x) || isNaN(y)) {
- sendMsg({ type: "CMD_RESP", cmd: "CMD_CLICK", ok: false, msg: "×ø±êÎÞЧ" });
- return;
- }
- if (typeof action !== "undefined") {
- action.click(x, y);
- } else if (typeof hid !== "undefined") {
- hid.click(x, y);
- }
- sendMsg({ type: "CMD_RESP", cmd: "CMD_CLICK", ok: true, cmdId: obj.cmdId });
- } catch (e) {
- sendMsg({ type: "CMD_RESP", cmd: "CMD_CLICK", ok: false, msg: e.message });
- }
- }
- // ========== ÒµÎñÖ¸Á״̬²éѯ ==========
- function handleStatusCmd(obj) {
- var info = getDeviceInfo();
- info.type = "CMD_RESP";
- info.cmd = "CMD_STATUS";
- info.ok = true;
- info.cmdId = obj.cmdId;
- info.runtimeSec = nowSec() - G.startTime;
- info.msgSentCount = G.msgSentCount;
- info.msgRecvCount = G.msgRecvCount;
- info.reconnectCount = G.reconnectCount;
- sendMsg(info);
- }
- // ========== ÐÄÌø¶¨Ê±Æ÷ ==========
- function startHeartbeat() {
- stopHeartbeat();
- var hbMs = CFG.heartbeatIntervalSec * 1000;
- try {
- G.heartbeatTimer = setTimeout(function tick() {
- try {
- if (!G.running || !G.connected) return;
- // ¼ì²éÐÄÌø³¬Ê±
- if (G.lastPongAt > 0 && (nowMs() - G.lastPongAt) > hbMs + 10000) {
- printl("[WARN] ÐÄÌø³¬Ê±£¬Ö÷¶¯¶Ï¿ªÖØÁ¬");
- try { G.ws.close(); } catch (e) {}
- return;
- }
- sendMsg({ type: "PING", ts: nowSec() });
- G.heartbeatTimer = setTimeout(tick, hbMs);
- } catch (e) {
- printl("[ERROR] " + "ÐÄÌøÒì³£(ÒѶµ×¡): " + e.message);
- G.heartbeatTimer = setTimeout(tick, hbMs);
- }
- }, hbMs);
- } catch (e) {
- // setTimeout ²»´æÔÚʱÓà runTime.setTimeout ¶µµ×
- try {
- G.heartbeatTimer = runTime.setTimeout(function tick() {
- try {
- if (!G.running || !G.connected) return;
- if (G.lastPongAt > 0 && (nowMs() - G.lastPongAt) > hbMs + 10000) {
- printl("[WARN] ÐÄÌø³¬Ê±£¬Ö÷¶¯¶Ï¿ªÖØÁ¬");
- try { G.ws.close(); } catch (e2) {}
- return;
- }
- sendMsg({ type: "PING", ts: nowSec() });
- G.heartbeatTimer = runTime.setTimeout(tick, hbMs);
- } catch (e3) {
- G.heartbeatTimer = runTime.setTimeout(tick, hbMs);
- }
- }, hbMs);
- } catch (e4) {}
- }
- }
- function stopHeartbeat() {
- if (G.heartbeatTimer) {
- try { clearTimeout(G.heartbeatTimer); } catch (e) {}
- try { runTime.stopTimeout(G.heartbeatTimer); } catch (e) {}
- G.heartbeatTimer = null;
- }
- }
- // ========== WebSocket »Øµ÷º¯Êý ==========
- // Á¬½Ó³É¹¦
- function wsOnConnected() {
- G.connected = true;
- G.reconnectCount = 0;
- G.currentDelay = CFG.reconnectIntervalMs;
- G.lastPongAt = nowMs();
- printl("[INFO] Á¬½Ó³É¹¦ (onConnected) ¡ª TLS ÎÕÊÖÍê³É");
- // Æô¶¯ÐÄÌø
- startHeartbeat();
- // Á¬½Ó³É¹¦ºó·¢ËÍ×¢²áÏûÏ¢
- var info = getDeviceInfo();
- sendMsg({
- type: "REGISTER",
- device: info,
- ts: nowSec()
- });
- }
- // ÊÕµ½Îı¾ÏûÏ¢
- function wsOnTextMessage(msg) {
- var raw;
- try { raw = String(msg); } catch (e) { raw = "" + msg; }
- handleMessage(raw);
- }
- // Á¬½Ó´íÎó
- function wsOnConnectError(err) {
- G.connected = false;
- var errMsg = "unknown";
- try { errMsg = String(err); } catch (e) {}
- if (!errMsg || errMsg === "null" || errMsg === "undefined") {
- errMsg = "Á¬½Ó´íÎó(ÎÞÏêϸÐÅÏ¢)";
- }
- printl("[ERROR] " + "Á¬½Ó´íÎó (onConnectError): " + errMsg);
- stopHeartbeat();
- scheduleReconnect();
- }
- // Á¬½Ó¶Ï¿ª
- function wsOnDisconnected() {
- G.connected = false;
- printl("[WARN] Á¬½Ó¶Ï¿ª (onDisconnected)");
- stopHeartbeat();
- scheduleReconnect();
- }
- // ========== ½¨Á¢Á¬½Ó ==========
- function connect() {
- // ÏÈÇåÀí¾ÉÁ¬½Ó
- if (G.ws) {
- try { G.ws.close(); } catch (e) {}
- G.ws = null;
- }
- G.connected = false;
- printl("[INFO] ÕýÔÚÁ¬½Ó: " + CFG.serverUrl + " (ÖØÁ¬ " + G.reconnectCount + "/" + CFG.maxReconnectAttempts + ")");
- // ´´½¨ AIWROK ÔÉú websocket ʵÀý
- var ws = null;
- try {
- ws = new websocket();
- } catch (e) {
- printl("[ERROR] " + "new websocket() ʧ°Ü: " + e.message);
- scheduleReconnect();
- return;
- }
- G.ws = ws;
- // ÉèÖà SocketID£¨Î¨Ò»±êʶ£©
- try {
- ws.setSocketID("aiwrok_" + nowMs());
- } catch (e) {
- printl("[DEBUG] " + "setSocketID ʧ°Ü(·ÇÖÂÃü): " + e.message);
- }
- // ¹ÒÔØ»Øµ÷ʼþ
- var eventOk = false;
- try {
- ws.event(wsOnConnected, wsOnTextMessage, wsOnConnectError, wsOnDisconnected);
- eventOk = true;
- printl("[DEBUG] ws.event() ¹Òʼþ³É¹¦");
- } catch (e1) {
- printl("[WARN] ws.event() ʧ°Ü: " + e1.message + " ¡ª ³¢ÊÔÊôÐÔ¸³Öµ");
- }
- // Èç¹û event() ²»ÐУ¬ÓÃÊôÐÔ¸³Öµ¶µµ×
- if (!eventOk) {
- try {
- ws.onConnected = wsOnConnected;
- ws.onTextMessage = wsOnTextMessage;
- ws.onConnectError = wsOnConnectError;
- ws.onDisconnected = wsOnDisconnected;
- printl("[DEBUG] ÊôÐÔ¸³Öµ¹Òʼþ³É¹¦");
- } catch (e2) {
- printl("[ERROR] " + "Á½ÖÖ¹Òʼþ·½Ê½¶¼Ê§°Ü: " + e2.message);
- scheduleReconnect();
- return;
- }
- }
- // ·¢ÆðÁ¬½Ó£¨×¢Òâ: connet Ë«n£©
- try {
- ws.connet(CFG.serverUrl);
- printl("[DEBUG] connet() Òѵ÷ÓÃ");
- } catch (e3) {
- printl("[WARN] connet() Òì³£: " + e3.message + " ¡ª ³¢ÊÔ connect()");
- try {
- ws.connect(CFG.serverUrl);
- } catch (e4) {
- printl("[ERROR] " + "connect() Ҳʧ°Ü: " + e4.message);
- scheduleReconnect();
- }
- }
- }
- // ========== ÖØÁ¬µ÷¶È ==========
- function scheduleReconnect() {
- if (!G.running) return;
- if (G.reconnectCount >= CFG.maxReconnectAttempts) {
- printl("[ERROR] ÒÑ´ï×î´óÖØÁ¬´ÎÊý " + CFG.maxReconnectAttempts + "£¬Í£Ö¹");
- return;
- }
- G.reconnectCount++;
- // Ö¸ÊýÍ豆 + Ëæ»ú¶¶¶¯
- G.currentDelay = Math.min(
- G.currentDelay * CFG.reconnectMultiplier,
- CFG.maxReconnectDelayMs
- );
- var jitter = Math.floor(G.currentDelay * (0.8 + Math.random() * 0.4));
- printl("[INFO] ÖØÁ¬ " + G.reconnectCount + "/" + CFG.maxReconnectAttempts +
- " ¡ª " + (jitter / 1000).toFixed(1) + "s ºóÖØÊÔ");
- try {
- setTimeout(function () {
- if (G.running) {
- try { connect(); } catch (e) {
- printl("[ERROR] " + "ÖØÁ¬»Øµ÷Òì³£(ÒѶµ×¡): " + e.message);
- scheduleReconnect();
- }
- }
- }, jitter);
- } catch (e) {
- try {
- runTime.setTimeout(function () {
- if (G.running) {
- try { connect(); } catch (e2) {
- printl("[ERROR] " + "ÖØÁ¬»Øµ÷Òì³£(ÒѶµ×¡): " + e2.message);
- scheduleReconnect();
- }
- }
- }, jitter);
- } catch (e3) {}
- }
- }
- // ========== ¹Ø±ÕÇåÀí ==========
- function cleanup() {
- G.running = false;
- stopHeartbeat();
- if (G.ws) {
- try { G.ws.close(); } catch (e) {}
- G.ws = null;
- }
- G.connected = false;
- printl("[INFO] ×ÊÔ´ÒÑÇåÀí");
- }
- // ========== Ö÷³ÌÐò ==========
- function main() {
- try {
- G.startTime = nowSec();
- printl("[INFO] ==========================================");
- printl("[INFO] WSS WebSocket ¿Í»§¶Ë (AIWROKÔÉú) Æô¶¯");
- printl("[INFO] " + " ·þÎñÆ÷: " + CFG.serverUrl);
- printl("[INFO] ÐÄÌø¼ä¸ô: " + CFG.heartbeatIntervalSec + "s");
- printl("[INFO] ×î´óÖØÁ¬: " + CFG.maxReconnectAttempts + " ´Î");
- printl("[INFO] " + " É豸ÐÅÏ¢: " + JSON.stringify(getDeviceInfo()));
- printl("[INFO] ==========================================");
- // ·¢ÆðÊ×´ÎÁ¬½Ó
- connect();
- // Ö÷Ï̱߳£»î£¨Á´Ê½ setTimeout£¬·Ç×èÈû£©
- var tick = 0;
- (function keepAlive() {
- try {
- if (!G.running) {
- printl("[INFO] Ö÷Ï̱߳£»îÍ˳ö");
- return;
- }
- tick++;
- // ÿ 20 Ãë´òÓ¡Ò»´Î״̬
- if (tick % 20 === 0) {
- printl("[INFO] " + "[±£»î] ÒÑÔËÐÐ=" + (nowSec() - G.startTime) +
- "s Á¬½Ó=" + G.connected +
- " ·¢ËÍ=" + G.msgSentCount +
- " ½ÓÊÕ=" + G.msgRecvCount +
- " ÖØÁ¬=" + G.reconnectCount);
- }
- } catch (e) {
- printl("[ERROR] " + "±£»îÒì³£(ÒѶµ×¡): " + e.message);
- }
- try { setTimeout(keepAlive, 1000); }
- catch (e) {
- try { runTime.setTimeout(keepAlive, 1000); } catch (e2) {}
- }
- })();
- // Èç¹ûÉèÖÃÁËÔËÐÐʱ³¤£¬µ½Ê±×Ô¶¯Í˳ö
- if (CFG.runDuration > 0) {
- sleep.millisecond(CFG.runDuration);
- cleanup();
- }
- // ·ñÔòÎÞÏÞÔËÐУ¨¿¿±£»îÑ»·Î¬³Ö£©
- } catch (e) {
- printl("[FATAL] " + "Ö÷³ÌÐòÒì³£: " + e.message + "\n" + (e.stack || ""));
- try { cleanup(); } catch (e2) {}
- }
- }
- // ========== Æô¶¯ ==========
- main();
¸´ÖÆ´úÂë
|
|