|
|
AIWROKÊÖ»úÖ´ÐÐÆ÷MQTTä¯ÀÀÆ÷¿Ø¶Ë
- /**
- * AIWROK ÊÖ»úÖ´ÐÐÆ÷£¨MQTT Ⱥ¿Ø¶Ë£©
- * ------------------------------------------------------------------
- * ÅäÌ×£ºÖ¸»Ǫ́.html£¨µçÄÔä¯ÀÀÆ÷´ò¿ª£©
- * ×÷ÓãºÊÖ»úÁ¬ÉÏ MQTT ºó´ýÃü£¬µçÄÔ·¢Ö¸Áî ¡ú ÊÖ»úÖ´ÐÐ ¡ú ½á¹û»Ø´«
- *
- * Ö÷ÌâÔ¼¶¨£¨ROOM »»³ÉÄã×Ô¼ºµÄ·¿¼äºÅ£¬±ÜÃâºÍ±ðÈË´®Ì¨£©
- * ÊÕ£ºaiwrok/<ROOM>/cmd/<±¾»ú»úºÅ> Ö»·¢¸øÄ³Ò»Ì¨
- * ÊÕ£ºaiwrok/<ROOM>/cmd/all ¹ã²¥£¬ËùÓлúÆ÷¶¼Ö´ÐÐ
- * ·¢£ºaiwrok/<ROOM>/ret/<±¾»ú»úºÅ> ÐÄÌø + Ö´Ðнá¹û + ½ØÍ¼
- *
- * Ö§³ÖµÄÖ¸ÁJSON£©
- * {"cmd":"PING"}
- * {"cmd":"STATUS"}
- * {"cmd":"SHOT"} ½ØÍ¼»Ø´«
- * {"cmd":"CLICK","x":540,"y":960} µã×ø±ê
- * {"cmd":"SWIPE","x1":540,"y1":1400,"x2":540,"y2":500,"ms":300} »¬¶¯
- * {"cmd":"TEXT","text":"ÄãºÃ"} ÊäÈëÖÐÎÄ
- * {"cmd":"APP","pkg":"com.tencent.mm"} ´ò¿ªÓ¦ÓÃ
- * {"cmd":"HOME"} / {"cmd":"BACK"}
- * {"cmd":"LOOP","act":"SWIPE","count":30,"min":1500,"max":4000} Ñ»·Ñø»ú
- * {"cmd":"STOP"} ֹͣѻ·
- * ´ø "id":"xxx" µÄ»ØÖ´»áÔÑù´ø»Ø£¬·½±ãµçÄÔÅä¶Ô
- * ------------------------------------------------------------------
- */
- // ==================== ÅäÖãºÖ»¸ÄÕâÈýÐÐ ====================
- var ROOM = "room001"; // ·¿¼äºÅ£¬¶ą̀µçÄÔ/¶àÌ×É豸ÓÃËü¸ôÀë
- var DEV_ID = ""; // »úºÅ£¬Áô¿Õ=×Ô¶¯Óà IMEI ºó 6 λ
- var BROKER = "tcp://broker.emqx.io:1883";
- var SHOT_MAXW = 540; // »Ø´«½ØÍ¼×î´ó¿í¶È£¬³¬³öµÈ±ÈËõС
- var SHOT_QUAL = 60; // JPEG ÖÊÁ¿ 1-100£¬µ÷С¸üÊ¡Á÷Á¿¸ü²»Ò×µôÏß
- // ========================================================
- var T = {
- cmdMine : "", cmdAll : "", ret : ""
- };
- // ---------- ÈÕÖ¾ ----------
- // ÖØÒª£ºprintl Ö»ÄÜÔڽű¾Ö÷Ï̵߳÷Óá£Paho µÄ»Øµ÷£¨ÊÕÏûÏ¢/µôÏߣ©ÅÜÔÚ±ðµÄ
- // Java Ïß³ÌÉÏ£¬ÔÚÄÇÀïÖ±½Ó printl »áÅ×Òì³£²¢´òËÀÏûÏ¢ÅÉ·¢Ị̈߳¬±íÏÖΪ
- // "Ö»ÊÕµ½µÚÒ»ÌõÖ¸Á֮ºóÈ«²¿¶ªÊ§£¬×îºó 32000 ³¬Ê±µôÏß"¡£
- // ËùÒԻص÷ÀïÖ»Èë¶Ó£¬ÓÉÖ÷Ï̶߳¨Ê±Æ÷ͳһˢ³ö¡£
- var IN_CALLBACK = false;
- var LOGQ = [];
- function log(s) {
- if (IN_CALLBACK) {
- if (LOGQ.length < 500) LOGQ.push(s); // »Øµ÷Ị̈߳ºÖ»Èë¶Ó£¬¾ø²» printl
- } else {
- try { printl("[Ö´ÐÐÆ÷] " + s); } catch (e) {}
- }
- }
- function logk(s) { log(s); }
- // Ö÷Ïß³ÌË¢ÈÕÖ¾¶ÓÁÐ
- function flushLog() {
- var n = 0;
- while (LOGQ.length > 0 && n < 30) {
- try { printl("[Ö´ÐÐÆ÷] " + LOGQ.shift()); } catch (e) { LOGQ.length = 0; break; }
- n++;
- }
- }
- // ==================== 1. ¼ÓÔØ Paho ====================
- var dexName = "paho-mqtt.dex";
- try {
- rhino.loadDex(dexName);
- log("dex ÒѼÓÔØ");
- } catch (e) {
- log("loadDex Ìø¹ý£¨¿ÉÄÜϵͳÒÑ×Ô¶¯¼ÓÔØ²å¼þ£©£º" + e.message);
- }
- try {
- importClass(Packages.org.eclipse.paho.client.mqttv3.MqttClient);
- importClass(Packages.org.eclipse.paho.client.mqttv3.MqttConnectOptions);
- importClass(Packages.org.eclipse.paho.client.mqttv3.MqttCallback);
- importClass(Packages.org.eclipse.paho.client.mqttv3.MqttMessage);
- importClass(Packages.org.eclipse.paho.client.mqttv3.persist.MemoryPersistence);
- log("Paho ÀർÈë³É¹¦");
- } catch (e) {
- log("Paho ÀർÈëʧ°Ü£º" + e.message);
- log("Çë°Ñ paho-mqtt.dex ·Åµ½±¾¹¤³ÌµÄ ²å¼þ\\ Ŀ¼ºóÖØÅÜ");
- exit();
- }
- // ==================== 2. É豸ÐÅÏ¢ ====================
- function deviceInfo() {
- var o = { brand: "?", model: "?", imei: "", w: 0, h: 0, android: "?" };
- try { o.brand = "" + device.getBrand(); } catch (e) {}
- try { o.model = "" + device.getModel(); } catch (e) {}
- try { o.imei = "" + device.getIMEI(); } catch (e) {}
- try { o.w = screen.getScreenWidth(); o.h = screen.getScreenHeight(); } catch (e) {}
- try { o.android = "" + java.lang.System.getProperty("os.version"); } catch (e) {}
- return o;
- }
- var INFO = deviceInfo();
- if (!DEV_ID) {
- DEV_ID = INFO.imei ? ("" + INFO.imei).slice(-6) : ("dev" + Math.floor(Math.random() * 10000));
- }
- DEV_ID = "" + DEV_ID;
- T.cmdMine = "aiwrok/" + ROOM + "/cmd/" + DEV_ID;
- T.cmdAll = "aiwrok/" + ROOM + "/cmd/all";
- T.ret = "aiwrok/" + ROOM + "/ret/" + DEV_ID;
- // ==================== 3. ״̬ ====================
- var client = null, connected = false;
- var needReconnect = false; // µôÏß±ê¼Ç£¬Ö÷Ï߳̿´ÃŹ·´¦Àí
- var startAt = (new Date()).getTime();
- var nRecv = 0, nSent = 0, nRun = 0;
- var loopOn = false; // Ñ»·ÈÎÎñ¿ª¹Ø
- var CMDQ = []; // Ö¸Áî¶ÓÁУº»Øµ÷Ïß³ÌÈë¶Ó£¬Ö÷Ïß³ÌÖ´ÐÐ
- // ==================== 4. »Ø´« ====================
- function report(obj, retain) {
- if (!connected) { log("δÁ¬½Ó£¬»Ø´«¶ªÆú£º" + obj.type); return; }
- try {
- // ÿÌõ¶¼´øÉ豸ÐÅÏ¢£¬Ö¸»Ǫ́Íí´ò¿ªÒ²ÄÜÁ¢¿ÌÏÔÊ¾Æ·ÅÆÐÍºÅÆÁÄ»
- obj.dev = DEV_ID; obj.room = ROOM;
- obj.brand = INFO.brand; obj.model = INFO.model;
- obj.screen = INFO.w + "x" + INFO.h;
- obj.ts = (new Date()).getTime();
- var m = new MqttMessage();
- m.setPayload(new java.lang.String(JSON.stringify(obj)).getBytes("UTF-8"));
- m.setQos(retain ? 1 : 0);
- if (retain) m.setRetained(true); // ÉÏÏßÏûÏ¢±£Áô£¬ÐÂÁ¬½ÓµÄÍøÒ³Á¢¿ÌÄÜ¿´µ½
- client.publish(T.ret, m);
- nSent++;
- } catch (e) { log("»Ø´«Ê§°Ü£º" + e.message); }
- }
- // ==================== 5. Ö¸ÁîʵÏÖ ====================
- function doClick(x, y) {
- auto.clickPoint(x, y);
- return { x: x, y: y };
- }
- function doSwipe(o) {
- var x1 = o.x1 || INFO.w / 2, y1 = o.y1 || INFO.h * 0.75;
- var x2 = o.x2 || INFO.w / 2, y2 = o.y2 || INFO.h * 0.25;
- var ms = o.ms || 300;
- auto.swip(x1, y1, x2, y2, ms, 0);
- return { x1: x1, y1: y1, x2: x2, y2: y2, ms: ms };
- }
- function doText(t) {
- input.sendString(t);
- return { len: ("" + t).length };
- }
- function doShot() {
- var bmp = screen.screenShotFull();
- if (!bmp) throw new Error("½ØÍ¼·µ»Ø¿Õ");
- var b64 = null;
- try {
- // ÏȵȱÈËõ·Åµ½ shotMaxW ¿í£¬ÔÙѹ³É JPEG£º
- // Ôʼ PNG base64 ¶¯éü 200KB£¬´ó°üÈÝÒ×ÈÃÁ¬½Ó³¬Ê±µôÏß
- var w = bmp.getWidth(), h = bmp.getHeight();
- var target = bmp;
- var from = null;
- try {
- if (w > SHOT_MAXW) {
- var sc = SHOT_MAXW / w;
- var m = new Packages.android.graphics.Matrix();
- m.postScale(sc, sc);
- target = Packages.android.graphics.Bitmap.createBitmap(bmp, 0, 0, w, h, m, true);
- from = target;
- }
- } catch (eScale) { target = bmp; }
- var bos = new java.io.ByteArrayOutputStream();
- target.compress(Packages.android.graphics.Bitmap.CompressFormat.JPEG, SHOT_QUAL, bos);
- var bytes = bos.toByteArray();
- b64 = "" + Packages.android.util.Base64.encodeToString(bytes, Packages.android.util.Base64.NO_WRAP);
- if (from) { try { from.recycle(); } catch (e2) {} }
- } catch (e) {
- // ѹËõÁ´Â·Ê§°Ü£ºÍË»ØÔͼ base64£¬ÖÁÉÙ½ØÍ¼¹¦ÄÜ»¹ÄÜÓÃ
- try { b64 = "" + bmp.toBase64(); } catch (e5) { b64 = null; }
- }
- if (!b64 || b64.length < 32) {
- try { bmp.recycle(); } catch (e3) {}
- throw new Error("½ØÍ¼Ñ¹Ëõʧ°Ü");
- }
- try { bmp.recycle(); } catch (e4) {}
- var kb = Math.round(b64.length / 1024);
- if (kb > 400) throw new Error("½ØÍ¼ÈÔ¹ý´ó " + kb + "KB£¬Çëµ÷С shotMaxW »ò shotQuality");
- return { img: b64, kb: kb };
- }
- function doApp(pkg) {
- app.openApp(pkg);
- return { pkg: pkg };
- }
- function doHome() { auto.home(); return {}; }
- function doBack() {
- // ²»Í¬°æ±¾·½·¨Ãû¿ÉÄܲ»Í¬£¬Öð¸öÊÔ£¬Ê§°ÜÒ²´òÈÕÖ¾
- if (typeof auto.back === "function") { auto.back(); return {}; }
- throw new Error("´Ë°æ±¾ auto ÎÞ back()£¬¿ÉÓà CLICK µã·µ»Ø¼ü×ø±ê");
- }
- // Ñ»·Ñø»ú£º·´¸´×öͬһ¸ö¶¯×÷ + Ëæ»úµÈ´ý£¬Ä£ÄâÕæÈË
- function runLoop(o) {
- loopOn = true;
- var act = o.act || "SWIPE";
- var count = o.count || 0; // 0 = ÎÞÏÞ£¬Ö±µ½ STOP
- var minMs = o.min || 2000, maxMs = o.max || 6000;
- var i = 0;
- logk("Ñ»·¿ªÊ¼ act=" + act + " count=" + count);
- report({ type: "LOOP", state: "start", act: act, count: count });
- (function step() {
- if (!loopOn) { logk("Ñ»·ÒÑÍ£Ö¹£¬¹² " + i + " ´Î"); report({ type: "LOOP", state: "stop", times: i }); return; }
- try {
- if (act === "SWIPE") doSwipe(o);
- else if (act === "SHOT") { var r = doShot(); report({ type: "SHOT", ok: true, kb: r.kb, img: r.img }); }
- else if (act === "CLICK") doClick(o.x || INFO.w / 2, o.y || INFO.h / 2);
- nRun++;
- i++;
- if (i % 10 === 0) { log("Ñ»·½ø¶È " + i + " ´Î"); report({ type: "LOOP", state: "run", times: i }); }
- } catch (e) {
- log("Ñ»·µ¥´Îʧ°Ü£º" + e.message);
- report({ type: "LOOP", state: "err", err: e.message, times: i });
- }
- if (count > 0 && i >= count) {
- loopOn = false;
- logk("Ñ»·Íê³É " + i + " ´Î");
- report({ type: "LOOP", state: "done", times: i });
- return;
- }
- var wait = minMs + Math.floor(Math.random() * Math.max(1, maxMs - minMs));
- setTimeout(step, wait);
- })();
- }
- // ==================== 6. Ö¸Áî·Ö·¢ ====================
- function handle(raw, from) {
- nRecv++;
- var o;
- try { o = JSON.parse(raw); }
- catch (e) { log("·Ç JSON Ö¸ÁºöÂÔ£º" + raw); return; }
- var cmd = (o.cmd || "").toUpperCase();
- log("ÊÕµ½ " + cmd + " À´×Ô " + from + " id=" + (o.id || "-"));
- var res = { type: "ACK", cmd: cmd, id: o.id || "" };
- try {
- if (cmd === "PING") { res.ok = true; res.msg = "pong"; }
- else if (cmd === "STATUS"){
- res.ok = true;
- res.info = { brand: INFO.brand, model: INFO.model, screen: INFO.w + "x" + INFO.h,
- android: INFO.android, up: Math.round(((new Date()).getTime() - startAt) / 1000),
- recv: nRecv, sent: nSent, run: nRun, loop: loopOn, connected: connected };
- }
- else if (cmd === "CLICK") { res.ok = true; res.data = doClick(parseInt(o.x, 10), parseInt(o.y, 10)); }
- else if (cmd === "SWIPE") { res.ok = true; res.data = doSwipe(o); }
- else if (cmd === "TEXT") { res.ok = true; res.data = doText(o.text || ""); }
- else if (cmd === "SHOT") {
- log("½ØÍ¼ÖС");
- var r = doShot();
- res.ok = true; res.kb = r.kb; res.img = r.img; // ½ØÍ¼Ö±½Ó´øÍ¼»Ø´«
- log("½ØÍ¼Íê³É " + r.kb + "KB");
- }
- else if (cmd === "APP") { res.ok = true; res.data = doApp(o.pkg); }
- else if (cmd === "HOME") { res.ok = true; doHome(); }
- else if (cmd === "BACK") { res.ok = true; doBack(); }
- else if (cmd === "LOOP") { runLoop(o); res.ok = true; res.msg = "Ñ»·ÒÑÆô¶¯"; }
- else if (cmd === "STOP") { loopOn = false; res.ok = true; res.msg = "ÒÑ·¢ËÍÍ£Ö¹"; }
- else { res.ok = false; res.err = "δָ֪Áî " + cmd; }
- } catch (e) {
- res.ok = false; res.err = "" + e.message;
- log("Ö´ÐÐʧ°Ü£º" + e.message);
- }
- report(res);
- }
- // ==================== 7. Á¬½Ó ====================
- function connect() {
- var cid = "aiwrok_" + ROOM + "_" + DEV_ID + "_" + Math.floor(Math.random() * 1000);
- logk("Á¬½Ó " + BROKER + " clientId=" + cid);
- client = new MqttClient(BROKER, cid, new MemoryPersistence());
- var opt = new MqttConnectOptions();
- opt.setCleanSession(true);
- opt.setKeepAliveInterval(45);
- opt.setConnectionTimeout(15);
- opt.setAutomaticReconnect(true);
- client.setCallback(new MqttCallback({
- connectionLost: function (c) {
- IN_CALLBACK = true;
- try {
- connected = false;
- needReconnect = true;
- log("µôÏߣº" + c + "£¨µÈÖ÷Ï߳̿´ÃŹ·ÖØÁ¬£©");
- } catch (e) {} finally { IN_CALLBACK = false; }
- },
- messageArrived: function (topic, msg) {
- IN_CALLBACK = true; // ±¾Ï߳̽ûÖ¹ printl / ½ûÖ¹×öÖØ»î
- try {
- var text = "" + new java.lang.String(msg.getPayload(), "UTF-8");
- var from = ("" + topic === T.cmdAll) ? "¹ã²¥" : "¶¨Ïò";
- // Ö»Èë¶Ó£¬ÕæÕýµÄÖ´Ðн»¸øÖ÷Ị̈߳¨½ØÍ¼/µã»÷Ôڻص÷Ïß³ÌÀï»á¿¨×¡ MQTT ¶ÁÑ»·£©
- if (CMDQ.length < 200) CMDQ.push({ raw: text, from: from });
- } catch (e) {
- // ¾ø²»°ÑÒì³£Å×»Ø Paho£¬·ñÔòÅÉ·¢Ï̻߳ᱻ´òËÀ
- if (LOGQ.length < 500) LOGQ.push("ÊÕ°üÒì³££º" + e.message);
- } finally { IN_CALLBACK = false; }
- },
- deliveryComplete: function (t) { }
- }));
- client.connect(opt);
- connected = true;
- needReconnect = false;
- client.subscribe(T.cmdMine, 1);
- client.subscribe(T.cmdAll, 1);
- logk("ÒѶ©ÔÄ " + T.cmdMine + " ºÍ " + T.cmdAll);
- report({ type: "ONLINE" }, true); // ±£ÁôÏûÏ¢£ºÍøÒ³ºó¿ªÒ²ÄÜ¿´µ½
- flushLog();
- }
- // ==================== 8. Æô¶¯ ====================
- logk("Æô¶¯ »úºÅ=" + DEV_ID + " ·¿¼ä=" + ROOM + " ÆÁÄ»=" + INFO.w + "x" + INFO.h + " " + INFO.brand + " " + INFO.model);
- try { connect(); }
- catch (e) { connected = false; needReconnect = true; log("Ê×´ÎÁ¬½Óʧ°Ü£º" + e.message + "£¬¿´ÃŹ·»á³ÖÐøÖØÊÔ"); }
- // ---------- Ö÷Ï߳̿´ÃŹ·£ºË¢ÈÕÖ¾ + ÖØÁ¬ + ÖØ¶©ÔÄ ----------
- // »Øµ÷Ï̲߳»ÄÜ printl£¬ÈÕÖ¾¿¿ÕâÀïË¢³öÀ´£»ÖØÁ¬ºó±ØÐëÖØÐ¶©ÔÄ£¬
- // ÒòΪ cleanSession=true ʱ Paho ²»»áÌæÄã»Ö¸´¶©ÔÄ¡£
- var resubTried = 0;
- setInterval(function () {
- // 1) Ö÷Ïß³ÌÖ´ÐÐÅŶӵÄÖ¸Áî
- var k = 0;
- while (CMDQ.length > 0 && k < 5) {
- var job = CMDQ.shift();
- try { handle(job.raw, job.from); }
- catch (e) { log("Ö¸ÁîÖ´ÐÐÒì³££º" + e.message); }
- k++;
- }
- flushLog(); // 2) Ë¢³ö»Øµ÷ÔÜϵÄÈÕÖ¾
- try {
- var real = client ? client.isConnected() : false;
- if (real && !connected) { // ×Ô¶¯ÖØÁ¬³É¹¦ÁË
- connected = true; needReconnect = false;
- try {
- client.subscribe(T.cmdMine, 1);
- client.subscribe(T.cmdAll, 1);
- log("Òѻָ´Á¬½Ó²¢ÖØÐ¶©ÔÄ");
- } catch (e) { log("ÖØ¶©ÔÄʧ°Ü£º" + e.message); }
- report({ type: "ONLINE" }, true);
- }
- if (!real && client) { // µôÏߣºÖ÷¶¯ÖØÁ¬
- connected = false;
- resubTried++;
- if (resubTried % 8 === 0) { // Լÿ 8 ÃëÊÔÒ»´Î
- log("¿´ÃŹ·´¥·¢ÖØÁ¬¡");
- try { client.reconnect(); }
- catch (e) {
- log("reconnect ʧ°Ü£º" + e.message + "£¬Öؽ¨Á¬½Ó");
- try { connect(); } catch (e2) { log("ÖØ½¨Ê§°Ü£º" + e2.message); }
- }
- }
- }
- } catch (e) { log("¿´ÃŹ·Òì³££º" + e.message); }
- }, 1000);
- // ---------- ÐÄÌø£ºµçÄԶ˾ݴËÅжÏÔÚÏß ----------
- var needShot = false; // ¸Ä³É true Ôòÿ´ÎÐÄÌø¸½´øÒ»ÕŽØÍ¼
- var beat = 0;
- setInterval(function () {
- beat += 1;
- if (connected) {
- var o = { type: "HEART", up: beat * 20, recv: nRecv, sent: nSent, run: nRun, loop: loopOn };
- if (needShot) { try { var r = doShot(); o.img = r.img; o.kb = r.kb; } catch (e) {} }
- report(o);
- } else {
- log("µ±Ç°ÀëÏߣ¬ÐÄÌøÌø¹ý£¨¿´ÃŹ·ÖØÁ¬ÖУ©");
- }
- }, 20000);
- log("ÒѽøÈë´ýÃü£ºÃ¿ 1 ÃëË¢ÈÕÖ¾/²éÁ¬½Ó£¬Ã¿ 20 ÃëÉϱ¨ÐÄÌø¡£Í£Ö¹Çëµã IDE Í£Ö¹°´Å¥");
¸´ÖÆ´úÂë
|
|