|
|
websocket远程停止手机接收器
- // ============================================================================
- // 接入示例 - 你的业务脚本如何接入「远程停止接收器」
- // ============================================================================
- // 【AIWROK 加载明文 JS 的正确方式】
- // - Import("xxx.js") ← 只能加载加密后的 JS,明文不行!
- // - thread.runJsFile("xxx.js", "线程名") ← 可以加载明文 JS(推荐)
- //
- // 所以接入只需 3 行:
- // var stopThread = new thread();
- // stopThread.runJsFile("远程停止接收器.js", "stop_receiver");
- //
- // 子线程独立上下文,不影响主脚本业务
- // 收到电脑端 STOP_ALL 指令时,子线程调用 runTime.stopAllRuning()
- // 会停止所有子线程(包括它自己)和主脚本
- // ============================================================================
- // === 启动远程停止接收器(子线程)===
- var stopThread = new thread();
- stopThread.runJsFile("远程停止接收器.js", "stop_receiver");
- // === 以下是你自己的业务代码(示例)===
- printl("=== 我的业务脚本启动 ===");
- // 模拟一个长时间运行的任务
- var counter = 0;
- while (true) {
- counter++;
- printl("业务执行中... 第" + counter + "次");
- try { sleep.second(2); } catch (e) { break; }
- // 演示:跑10次后自己结束(实际不需要,电脑发 STOP_ALL 指令就会全停)
- if (counter >= 10) {
- printl("业务完成");
- break;
- }
- }
- printl("=== 业务脚本结束 ===");
- // ============================================================================
- // 工作流程:
- // 1. 主脚本启动 → 创建子线程 stop_receiver(连接电脑服务器)
- // 2. 主脚本继续跑业务
- // 3. 电脑端点「一键全停」→ 广播 STOP_ALL
- // 4. 子线程收到 → runTime.stopAllRuning() → 主脚本 + 所有子线程全停
- // ============================================================================
复制代码- // ============================================================================
- // 远程停止接收器 v5 - 按已验证可用的 WebSocket 模式重写
- // ============================================================================
- // 【加载方式】在主脚本开头加 3 行:
- // var stopThread = new thread();
- // stopThread.runJsFile("远程停止接收器.js", "stop_receiver");
- //
- // 配置:改下方 SERVER_IP 为你电脑的局域网 IP
- // ============================================================================
- var CONFIG = {
- SERVER_IP: "192.168.10.103",
- SERVER_PORT: "8886",
- WS_PATH: "/",
- DEVICE_NAME: "",
- PING_MS: 25000,
- RECONNECT_BASE_MS: 2000
- };
- // ============================================================================
- // 全局状态
- // ============================================================================
- var G = {
- ws: null,
- connected: false,
- deviceName: "",
- lastPongAt: 0,
- heartbeatTimer: null,
- retryCount: 0,
- running: true
- };
- function LOG(tag, msg) {
- printl("[停止接收器][" + tag + "] " + msg);
- }
- function getDeviceName() {
- if (CONFIG.DEVICE_NAME) return CONFIG.DEVICE_NAME;
- try { return device.getBrand() + "_" + device.getModel(); }
- catch (e) { return "phone_" + new Date().getTime(); }
- }
- function sendMsg(type, data) {
- if (!G.ws || !G.connected) return false;
- try {
- var obj = { type: type, ts: new Date().getTime(), data: data || {} };
- G.ws.send(JSON.stringify(obj));
- return true;
- } catch (e) {
- LOG("ERROR", "send 异常: " + e);
- return false;
- }
- }
- // ============================================================================
- // 心跳(runTime.setTimeout 递归,与已验证代码一致)
- // ============================================================================
- function startHeartbeat() {
- stopHeartbeat();
- G.lastPongAt = new Date().getTime();
- function tick() {
- if (!G.connected) return;
- var now = new Date().getTime();
- if (now - G.lastPongAt > CONFIG.PING_MS + 10000) {
- LOG("WARN", "心跳超时,主动断开");
- try { G.ws.close(); } catch (e) {}
- return;
- }
- sendMsg("PING", { t: now });
- G.heartbeatTimer = runTime.setTimeout(tick, CONFIG.PING_MS);
- }
- G.heartbeatTimer = runTime.setTimeout(tick, CONFIG.PING_MS);
- }
- function stopHeartbeat() {
- if (G.heartbeatTimer) {
- try { runTime.stopTimeout(G.heartbeatTimer); } catch (e) {}
- G.heartbeatTimer = null;
- }
- }
- // ============================================================================
- // 连接核心(完全照搬已验证的 WebSocket手机端常用实例.js 模式)
- // ============================================================================
- function doConnect() {
- G.connected = false;
- G.deviceName = getDeviceName();
- var url = "ws://" + CONFIG.SERVER_IP + ":" + CONFIG.SERVER_PORT + CONFIG.WS_PATH;
- LOG("INFO", "连接 " + url + " 设备=" + G.deviceName);
- var ws = new websocket();
- G.ws = ws;
- try { ws.setSocketID("stop_" + new Date().getTime()); } catch (e) {}
- // 定义四个回调
- var _onOpen = function () {
- LOG("OK", "onopen 触发!连接成功");
- G.connected = true;
- G.retryCount = 0;
- G.lastPongAt = new Date().getTime();
- // 上报设备信息
- sendMsg("REGISTER", { device: G.deviceName });
- startHeartbeat();
- };
- var _onMsg = function (msg) {
- try {
- var raw = "";
- try { raw = String(msg); } catch (e) { raw = "" + msg; }
- var obj = null;
- try { obj = JSON.parse(raw); } catch (e) { return; }
- var cmd = obj.cmd || "";
- var type = obj.type || "";
- if (cmd === "STOP_ALL") {
- LOG("WARN", ">>> 收到全停指令! <<<");
- _stopEverything();
- return;
- }
- if (type === "PING" || cmd === "PING") {
- sendMsg("PONG", { ts: new Date().getTime() });
- return;
- }
- if (type === "PONG") {
- G.lastPongAt = new Date().getTime();
- return;
- }
- } catch (e) {
- LOG("ERROR", "处理消息异常: " + e);
- }
- };
- var _onErr = function (err) {
- var m = "";
- try { m = String(err); } catch (e) {}
- LOG("WARN", "onerror: " + (m || "无详情"));
- G.connected = false;
- stopHeartbeat();
- };
- var _onClose = function () {
- LOG("INFO", "onclose:连接断开");
- G.connected = false;
- stopHeartbeat();
- };
- // ① 优先尝试属性赋值(官方示例 websocket.js 用的方式)
- try {
- ws.onopen = _onOpen;
- ws.onmessage = _onMsg;
- ws.onerror = _onErr;
- ws.onclose = _onClose;
- LOG("INFO", "回调注册: 属性赋值");
- } catch (eProp) {
- LOG("WARN", "属性赋值失败: " + eProp + ",尝试 event()");
- // ② 回退 event(4参数)
- try {
- ws.event(_onOpen, _onMsg, _onErr, _onClose);
- LOG("INFO", "回调注册: ws.event(4参数)");
- } catch (eEvt) {
- LOG("ERROR", "两种方式都失败: " + eEvt);
- return false;
- }
- }
- // 发起连接
- try {
- LOG("INFO", "调用 connet('" + url + "')...");
- ws.connet(url);
- } catch (e1) {
- try {
- LOG("WARN", "connet 抛异常: " + e1 + ",尝试 connect()");
- ws.connect(url);
- } catch (e2) {
- LOG("ERROR", "connet/connect 均失败: " + e1 + " / " + e2);
- return false;
- }
- }
- // 等待 onopen(最多 15 秒)
- var waitCount = 0;
- while (!G.connected && waitCount < 150) {
- sleep.millisecond(100);
- waitCount++;
- }
- if (G.connected) {
- LOG("OK", "已连接 服务器=" + CONFIG.SERVER_IP + ":" + CONFIG.SERVER_PORT);
- } else {
- LOG("WARN", "15 秒内 onopen 未触发");
- }
- return G.connected;
- }
- // ============================================================================
- // 主循环:连接 → 等待断开 → 重连
- // ============================================================================
- function mainLoop() {
- while (G.running) {
- G.retryCount++;
- if (G.retryCount > 999) {
- LOG("ERROR", "已达最大重连次数");
- break;
- }
- var ok = doConnect();
- if (!ok) {
- var waitMs = CONFIG.RECONNECT_BASE_MS * Math.min(Math.pow(2, G.retryCount - 1), 5);
- waitMs = waitMs + Math.floor(Math.random() * 1000);
- LOG("WARN", (waitMs / 1000).toFixed(1) + "s 后重连 (第" + G.retryCount + "次)");
- try { G.ws.close(); } catch (e) {}
- sleep.millisecond(waitMs);
- continue;
- }
- // 已连接:等待断开
- while (G.running && G.connected) {
- sleep.millisecond(500);
- }
- if (!G.running) break;
- // 断线了
- var waitMs2 = CONFIG.RECONNECT_BASE_MS * Math.min(Math.pow(2, G.retryCount - 1), 5);
- waitMs2 = waitMs2 + Math.floor(Math.random() * 1000);
- LOG("WARN", "断线 " + (waitMs2 / 1000).toFixed(1) + "s 后重连");
- try { G.ws.close(); } catch (e) {}
- sleep.millisecond(waitMs2);
- }
- stopHeartbeat();
- try { G.ws.close(); } catch (e) {}
- LOG("INFO", "接收器结束");
- }
- // ============================================================================
- // 全停
- // ============================================================================
- function _stopEverything() {
- LOG("WARN", ">>> 执行全停 <<<");
- G.running = false;
- try { runTime.stopAllRuning(); } catch (e) {}
- try { app.stopScript(); } catch (e) {}
- try { exit(); } catch (e) {}
- }
- // ============================================================================
- // 启动
- // ============================================================================
- LOG("INFO", "远程停止接收器 v5 启动");
- mainLoop();
- LOG("INFO", "启动完成");
复制代码
|
|